Tutorial: Intro to Developing Bluetooth Smart Applications for Android

Tutorial: Intro to Developing Bluetooth Smart Applications for Android

UPDATE: To see what has changed in Android 5.0, check out this post.

Today I'd like to talk about the Bluetooth Low Energy (or LE) APIs now available in the Android framework, and show you how easy it is to add some really interesting capabilities to mobile applications using this technology. Bluetooth LE was introduced to the core Android framework in 4.3, or API Level 18. Prior to this, there were several OEM-specific SDKs providing this behavior, but we will not be going into detail on those here.

Bluetooth GATT Basics

Bluetooth Low Energy, or Bluetooth Smart, is a part of the Bluetooth v4.0 specification aimed at providing a fast and low-power method of communicating with wireless sensors and peripherals.

There are four primary roles that a device can fulfill in the Bluetooth LE paradigm:

  • Broadcaster
  • Observer
  • Central
  • Peripheral

We are going to look at two examples today; first with the Android application acting in the Central role to communicate with a Peripheral device, and second with the Android device acting in an Observer role monitoring data advertisements from several Broadcaster devices.

Bluetooth LE is primarily built around the Generic Attribute profile, or GATT, as it is often called. This profile defines a structured approach to how peripherals expose data to other devices. Peripheral information is organized as a collection of Services that describe logical functions of the device. A specific sensor or feature (such as thermometer or heart rate monitor) would have its own service. Each Service includes a collection of Characteristics to transfer discrete data values between devices. A Characteristic can represent service data (such as the current value of the heart rate) or configuration data (such as whether this peripheral should notify anyone when its value changes).

Characteristics are minimally made up of property flags and a value. The flags describe information about a characteristic's capabilities; such as whether it is readable, writeable, or supports notification. Additionally, they may contain one or more descriptor elements to indicate the value's type and perhaps provide additional configuration that is specific to the given characteristics. If this sounds like a lot of layers to try and follow, fear not. When you see them all put together in a real-world example each of their roles should become clear.

The Bluetooth Special Interest Group does define many standard collections of common services into profiles that commercial devices can implement, in an effort to foster interoperability between communicating devices. For Bluetooth LE, examples of this would include the Heart Rate Profile, Proximity Profile, or the Time Profile. When interacting with a device that claims to implement a certain profile, developers can expect that a certain collection of service and characteristics exist on that device.

However, unlike with many classic Bluetooth profiles, the Android APIs for GATT devices do not currently provide profile-level abstractions. In order to communicate effectively with a Bluetooth LE device from Android, you must determine ahead of time the services and characteristics that you expect on the target remote device. The APIs will then allow you to scan for those specific services, then directly read and write the characteristics that are of interest.

It is also important to note that, at this stage, Android does not support creating an application that will cause the device to act in the Peripheral, or GATT server, role. It is only able to scan for, and connect to, other Peripheral devices.

DEMO: Android GATT Central Application

In our first demo, we have the CC2541 SensorTag from Texas Instruments. This is a device that implements a GATT server in order to provide data from each of its six sensors (temperature, humidity, pressure, accelerometer, gyroscope, and magnetometer). Each sensor is defined by its own service, and each service contains a characteristic to read the given sensor value. Most of the sensor services also contain a characteristic or two for configuring or enabling the sensor data updates.

Bluetooth LE Broadcasters

One really cool feature of Bluetooth LE is this role of a Broadcaster, or a device that does not accept incoming connections, but rather pushes out the data is has inside its device discovery, or advertisement, data. In the previous example, we had to make a connection to the remote device once the scan was complete in order to read and write characteristic data. We then had to go through the process of iterating over all the characteristics we needed to touch in getting the updates set up initially. This takes time, and in an application where devices may just be passing by, we want something simpler.

With a Broadcaster, data is placed directly into the advertisement packets. As an Observer application we can read everything we need from the devices during the LE scanning process without ever making a connection. Each advertisement contains a collection of advertisement data structures, each containing a length, type, and payload. The structure type identifiers are defined by the Bluetooth Special Interest group in the Generic Access Profile, and include elements like control flags, device name, service UUIDs, service data, and transmit power level (which is useful for determining proximity).

There is another significant benefit of Broadcaster applications to the accessory developers. The Bluetooth stack required to implement advertisements only without accepting connections is significantly simpler; which generally lowers both development effort and cost.

DEMO: Android LE Observer Application

In our next demo, we have three connection-less temperature beacons from KS Technologies; a company dedicated to helping developers create some really amazing Bluetooth LE solutions. The beacon tags all contain a temperature sensor, and the value of the current temperature is broadcast as service data inside their advertisement packet. This drastically reduces the code we have to write.


You can get the code for these examples over at my Github page. If you'd like to get your hands on some of these accessory beacons, head over to KS Technologies.

If you're looking to learn more about Android development, check out my upcoming Android Internals training course at NewCircle. Save 20% with coupon code: SMART

About the Author

If you liked this post you'll probably be interested in these:



Stephen Nussbaum | Consultant
Posted on Aug 30, 2016 (7 months ago)

Hi Dave, Great tutorials, thanks. I am trying to determine which type of communications to set up for my project, a Broadcast-Observer or Control-Peripheral. My project includes two sensors on separate platforms that generate a discrete signal that indicates an event has occurred. No analog pressure values required just a discrete function that the sensor output has exceeded a certain threshold. Each sensor, with its local controller will transmit via BLE to the phone app. The app simply increments a counter for each sensor anytime time a transmission is received from the respective sensor platform. The sensors are completely autonomous and asynchronous. The UI page will show the counter values for each sensor and will also include a reset button so the user can clear the counters at the appropriate time. If I use the simpler broadcast-observer scheme can the app pick up transmissions that may overlap in time? What is the highest frequency that I can expect the app able to handle? I can try this out and see how well it works but if you have some insight based on the limited info presented here I would take your recommendation either way. Thanks in advance for your feedback.

Camille Filhatre | Biotraq
Posted on May 02, 2016 (11 months ago)

Hello, Thank you very much for this tuto ! I tried your exemple with the SensorTag but unfortunatelly it doesn't work ... There is no Services discovered (onSearchComplete() = Device=C4:BE:84:72:63:86 Status=0 05-02 15:13:22.589 19806-20142/fr.android.moi.mynewapp D/BluetoothGattActivity: Services Discovered: 0 ), I don't know why... I am new at programming ... I have this error in the logcat : Attempt to invoke virtual method 'int android.bluetooth.BluetoothGattCharacteristic.getProperties()' on a null object reference... Can you help me please ? Thank you Sorry if there are some mistakes but English is not my first langage ;)

Posted on Mar 04, 2016 (1 year ago)

Hello Dave, I have a few questions concerning the mesh networking and the ability for Android marshmallow to create it. * Is it possible to create a mesh network using BLE between devices while some have different versions of Android ? how can i achieve mesh network using BLE. i want applictaion in android which control hardware via bluetooth which interface with CSR. plz help

Posted on Mar 04, 2016 (1 year ago)

Hi dave.i want to make project based on BLE . an android application which interface with rfduino . in this project i want to control led like led on led off or brightness of led max or minimum. plz help me i search application in github bt i cant understand dat

Jon Dew | Not affiliated
Posted on Feb 16, 2016 (1 year ago)

Hi Dave, thanks for the tutorials... got a question no one else has been able to answer... Basically, I'm working on an Android app that connects via BLE to a bracelet. Whenever someone calls, the app sends a signal to the bracelet to make it vibrate. It's up and running ok, but another feature of the app is that the firmware on the bracelet can be updated via an OTA transaction. But in order to do that, the bracelet needs to be plugged in and charging so that the connection speed parameters can be kicked up a notch. The connection parameters I'm referring to are these: https://devzone.nordicsemi.com/question/60/what-is-connection-parameters/ But the weird part about those parameters is that the exchange between the remote device and Android seem to be going on behind the scenes - the app has nothing to do with it and as far as I know, the app cannot even inspect what the current parameters are. (am I right?) The reason this is an issue, is that intermittently, the OTA transaction is failing due to timeouts... as if the bracelet device is not plugged in and has not asked for a boosted parameter set from the master (Android), or alternatively, it asked but Android either didn't get the request or rejected the request. Is there any way you know of to verify (within the app) what the current connection parameter settings are? (Because I have seen the packets exchanged ok with snoop/WireShark... but unable to figure out how to inspect those parameters from within the app.) And further, is there a way to tell Android to change the parameters on the fly (other than a characteristic WRITE which depends on the peripheral firmware having such a service available, which our older and existing live versions do not have.)? I'd appreciate any help you can send my way! Thanks in advance!

Sree Kumar A.V | Y media Labs
Posted on May 26, 2015 (2 years ago)

Hi Dave, Thanks for the Demo, it was really helpful to begin with. I'm developing an Android App based on BLE, in which user will be able to lock and unlock the device using smart phone. There couple of use cases, That I'm not quite sure about how to handle. 1) Device sleeping When android device sleeps, how we I can run a service, if acquire partial wake lock, I wont be able to release it, so battery will be killed soon. Using AlarmManger to trigger Scanning is the only solution for this issue ?. But I had seen, google fit app could able to fetch the sensor values, even if the device is sleeping ?? How they are achieving that respecting battery life. 2) Detecting proximity When the user comes near to the Door, it should unlock the door, with out taking the phone out and manually scanning ?? How I can achieve that ? Thanks in Advance, your guidance will be an asset to me... Regards Sree

Matthieu Boussemart | FINDER
Posted on Apr 29, 2015 (2 years ago)

Hello Dave, I have a few questions concerning the mesh networking and the ability for Android KitKat to create it. * Is it possible to create a mesh network using BLE between devices while some have different versions of Android ? (5.0 / 4.4 for example) * Does it requiere authorization each time a device connects to another as a node ? (to relay the data) So much more questions grow in my mind, could you help me ? Thank a lot. Matthieu

Dave Smith | NewCircle, Inc.
Posted on Apr 13, 2015 (2 years ago)

Lem - BLE scanning works in reverse from Bluetooth Classic scanning. In BLE, the peripheral is the advertiser (transmitter), and the scanner is the receiver. In other words, if a peripheral does not advertise there is no way to detect that it exists. The advertising interval is really the only practical way to control the power consumption of a BLE devices while advertising. Typically when the device is not transmitting an advertisement (in between each interval), it would be asleep to save power.

Lem Adane | Gemco, Inc.
Posted on Apr 13, 2015 (2 years ago)

Hi, I just want to find out if BLE peripheral device can be in sleep mode and wake up only when it is scanned by an observer device. Meaning it does not advertise data during sleep mode, but only respond when scanned using specific UUIDs. Is this possible? Is it also possible to wake it up for regular advertising and turn it back to sleep mode again using UUIDs while scanning? Im talking about GAP (no-pairing) not GATT (with pairing). Thanks in advance.

Mustafa YANCI | Istanbul Kultur University
Posted on Apr 13, 2015 (2 years ago)

Dave, Thank you so much for your quick return. That worked. I want to ask another question. Can I develop a new UI using these source codes? Is there any simple way to develop UI without coding or with a little coding? We do not need an advanced UI. We just want to show data of one of the sensors on a new UI. Thank you again.

Dave Smith | NewCircle, Inc.
Posted on Apr 08, 2015 (2 years ago)

Mustafa - The sample code hasn't been updated since Android Studio hit 1.0, and the plugin version requirements are a bit different. The easiest thing for you to do would be to: 1. Download the sample application directory (the 'BluetoothGatt' directory linked in the post) 2. Delete the build.gradle file 3. Use the 'Import Project' wizard to bring in the project Without the build.gradle file, Android Studio will treat the source as an Eclipse project and it will import the files correctly--creating the project files necessary with the correct versions.

Mustafa YANCI | Istanbul Kultur University
Posted on Apr 08, 2015 (2 years ago)

Hi Dave. Thank you for this exercise firstly. I and Burcu Gürses are studying on a graduation project and we have to develop an android app for BLE. We're new on android development and we have no much time to learn coding. We wanted to use (and "if we need" edit, ) sample codes and we started to develop using Android Studio. We downloaded your source code and tried to open with android studio but didn't work. Android Studio can not debug&build the project. It gives "No render target selected" And also there is an " Error:(1, 0) Plugin with id 'android' not found. " message in Messages box. There is also a "gradle project sync failed basic functionality will not work properly" error message in a yellow bar on top of android studio. I thought that this source code may be compatible with android 4.3 but may not be compatible with android studio. Am I right? Or, if this source code is compatible with(or created with) android studio, what can we do to run this project? Is there any configuration to run? I know I am asking very basic questions but we and our project instructor(our teacher) do not know anything about android development. Our teacher brought us TI cc2541 sensortag and wanted to us develop a mobile app that getting data from this kit. Our project is basically about bluetooth and BLE. We made a lot of theoretical researches about bluetooth technology but in practical, we have nothing. We have made researches about mobile platforms as iOS, Android and Windows Phone and decided to develop on android. Do you think best choice is android for somene doesn't know anything about mobile development? If you help us, we'd be grateful to you. Thank you so much.

Dave Smith | NewCircle, Inc.
Posted on Apr 06, 2015 (2 years ago)

Burcu - The linked GATT sample code is written to use the 4.3-based APIs, so it will work on a 4.3 device. If you are having problems, you will need to be more specific about what they are and/or make a post on StackOverflow where it is easier to look at the code.

Burcu Gürses | Student
Posted on Apr 06, 2015 (2 years ago)

Hi All How can use your soruce code in android 4.3 ? I tried to run your code in android studio program for android 4.3 but dosent work it . what can I do to working sensor tag code?

Dave Smith | NewCircle, Inc.
Posted on Mar 20, 2015 (2 years ago)

Manisha - The source code is linked in the post above, but here is the link to the GitHub page once more as well: https://github.com/devunwired/accessory-samples/tree/master/BluetoothGatt

Manish Butola | Teamdecode
Posted on Mar 20, 2015 (2 years ago)

HI All, Do anyone have a complete source code for this application.

Sue M | Developer Inc
Posted on Mar 02, 2015 (2 years ago)

Hi Dave,Thank you so much for this awesome tutorial!..It sure made my life a lot easier starting out into bluetooth le.I have a question though.I'm trying to implement a continuous background scanning,for 4.3 devices.It's slightly different from your implementation,with the two runnables that call the start and stop scanning methods.I don't know if this question is appropriate here because i'm trying to accomplish the same in C#.So my challenge is,i want it to start scanning when a boolean 'mScanning' is positive.This should then stop after a pre-defined period,sleep for a few seconds,set the boolean value to false then start scanning again.Currently it doesn't work as expected.It scans continuously and the values like the RSSI reading doesn't even change on the screen,yet it scans continuously.Could you kindly help me implement this type of scanning?I would truly appreciate if you could point me in the right direction. Below is my code: protected override void OnResume () { base.OnResume (); // Ensures Bluetooth is enabled on the device. If Bluetooth is not // currently enabled, // fire an intent to display a dialog asking the user to grant // permission to enable it. if (mBluetoothAdapter == null) { Toast.MakeText (this, "BluetoothAdapter is null", ToastLength.Short).Show (); } if (!mBluetoothAdapter.IsEnabled) { Intent enableBtIntent = new Intent ( BluetoothAdapter.ActionRequestEnable); StartActivityForResult (enableBtIntent, REQUEST_ENABLE_BT); } //Scan for ble devices ScanLeDevice (true); } void ScanLeDevice (bool enable) { if (enable) { if (mHandler == null) { Toast.MakeText (this, "Handler is null", ToastLength.Short).Show (); return; } try{ Runnable scanRunnable = null; scanRunnable = new Runnable(delegate { mScanning = false; mBluetoothAdapter.StopLeScan (this); InvalidateOptionsMenu (); ThreadPool.QueueUserWorkItem((state) => { SlowMethod(); }); }); // Post again after certain ms depending on the scan period specified. mHandler.PostDelayed(scanRunnable,SCAN_PERIOD); mHandler.Post(scanRunnable); mScanning = true; mBluetoothAdapter.StartLeScan (this); }catch(Exception e){ Log.Error (TAG,e.ToString()); } } else { mScanning = false; mBluetoothAdapter.StopLeScan (this); } InvalidateOptionsMenu (); } public void SlowMethod(){ Thread.Sleep (SLEEP_PERIOD); RunOnUiThread (new Action (delegate { mScanning = true; mBluetoothAdapter.StartLeScan (this); InvalidateOptionsMenu (); })); }

Dave Smith | NewCircle, Inc.
Posted on Feb 17, 2015 (2 years ago)

Vinod - iBeacons are devices that provide their data to surrounding devices in the advertisement packet, they are not stored as GATT characteristics that have read/write capability (by default). As such, they cannot be modified in a consistent way per the iBeacon spec. Some specific beacon manufacturers (Estimote, for example) do allow an application to program the beacon parameters by connecting and writing characteristics. However that will be specific to the manufacturer of your beacon and the SDK they provide to set those values. This is not a universal thing for all iBeacons.

Vinod Kumar Krishnamoorthy Ganesan | Tata consultancy services
Posted on Feb 17, 2015 (2 years ago)

I am working building app with BLE iBeacons for Android Application, I want to change the Tx power and major and minor values and UUID of the iBeacons using the GATT service, i could establish connect but facing issue with writing the value to the Beacon, How can i achieve this please help me out. Thanks in advance.

Mobile application training in Chennai | Technology career and development center
Posted on Feb 17, 2015 (2 years ago)

Nice post ! Thanks for sharing ....

Chandra Ghanta | Qualcomm, Inc.
Posted on Jan 16, 2015 (2 years ago)

Does/Will AndroidWear support GATT and BLE or Just "BT Classic" and RFCOMM? I am developing a system that will support Android Wear OS and will need to support BLE (for sensor). Also, I am looking for small, low power "hostless" BT Classic + BLE SoC,. Any suggestions are welcome that will looking for a chip. Thx. Chandra

Dave Smith | NewCircle, Inc.
Posted on Dec 31, 2014 (2 years ago)

Thanks for the information, William. I will keep my eyes on this one; Bluedroid has had a long road getting up to par as a proper, stable BT stack...and that battle is far from over. It seems you also fell victim to the mass Obsolete hammer that Google slashed across the bug tracker a few weeks ago. I have subscribed to the related issue (58896) that is still open. It might make sense to transfer your comments to that issue since Google didn't merge the two (which they probably should have). Do you know if this has changed at all with iOS 8? Also, did you test Android 5.0 on Wear or just 5.0 on the device? 5.0 Wear might have different BT behavior as it's a slightly updated point release (it's a longshot).

William Belcher | Self
Posted on Dec 31, 2014 (2 years ago)

I have been working on writing code that allows the android wear platform to interface with an iPhone using BLE via ANCS. Theoretically it should work, but when looking at the Bluetooth logs after it refuses to establish a connection I get a Connection Refused -PSM Not Supported from the iPhone. I am using the default Bluetooth le sample from the android website as a starter point. Apparently I am not the only one with this issue. Here is an excerpt from a post on stack overflow. Excerpt: http://stackoverflow.com/questions/18052593/how-to-connect-android-device-to-an-ios-device-over-ble-bluetooth-low-energy I've already gone through this for at least one week having this same issue. I've already asked a question here and I've already answered on my own. The main problem is an Android BUG issue. It's sending a non permitted command on a fixed L2CAP channnel. But when Android is communicating with normal peripheral BLE devices, it works pretty well. Infact the BLE sampple works like a charm. The problem is when is comunicating with an iOS device for example: Just after the connection is made, they start negotiating their connection parameters (this phase doesn't happen whith normal BLe peripheral), and this is when the problem comes up. Android sends a bad command to iOS, iOS answers drop the connection. That's basically how it works. Some issues have been already reported at Google, and one of them have been already accepted and I hope they will start working on it soon. Unfortunately, what you can do, is to wait until next Android release. Anyway, I highly suggest you to have a look at my issue report with all my test documents if you want to make some light on this problem. Here's the link: https://code.google.com/p/android/issues/detail?id=58725 Since Android 5 has been out, I am still getting the same error. Do you have any insight or help?? Thanks Will

Deepak Mital | Self
Posted on Dec 23, 2014 (2 years ago)

Hi, I am wondering if the GATT characteristics used by wearables and/or smartwatch manufacturers are released as some SDK. I want to connect to the smartwatch on my platform other than the smartphone. Thanks, Deepak

Chetan M | Winjit
Posted on Dec 08, 2014 (2 years ago)

Hi Dave, Thanks for providing such a wonderful tutorial over BLE connection. With this tutorial i resolved my problem. Now i want to perform some more operation like as 1) I want to write data over bluetooth on sensor device and that device will return me out put according to input provided. How can i achieve this please help me out. Thanks.