Android Bluetooth Low power (Android Bluetooth)

Source: Internet
Author: User

Android 4.3 (API level 18) has started to introduce the core features of Bluetooth low energy (BLE, Bluetooth) and provides APIs that enable applications to scan devices, query services, The characteristics (attribute feature) of the read-write device. Compared to traditional Bluetooth, BLE is designed to significantly reduce power consumption. This makes it possible for low-power communication between Android applications and BLE devices, such as distance sensors, heart rate monitors, fitness devices, and so on.

1. Key Terms and concepts
1.1 Here is a summary of some BLE key terms and concepts:

* Generic Attribute profile (GATT): GATT profile is a general specification for sending and receiving short pieces of data, such as the well-known "attribute (attribute)" on BLE connections. All current low-power application profiles are based on GATT. In addition, Bluetooth Technology Alliance (bluetooth® SIG) has defined profiles for many BLE devices. Profile is a specification that defines how a device works in a specified application. Note that a single device can implement multiple profiles. For example, a device can contain a heart rate monitor and a battery charge detector.
* Attribute Protocol (ATT, attribute Agreement): GATT is built on the basis of ATT and is therefore always a gatt/att. The ATT is optimized for the operation of the BLE device. To do this, it uses fewer bytes of data as much as possible. Each property is uniquely determined by the UUID. A UUID is a string ID in a standard 128-bit format that uniquely identifies a single message. Properties are transmitted via the ATT protocol after they are formatted as characteristics and services.
* Characteristic: A characteristic contains a value, and 0 or more descriptor that describe the characteristic value. You can think of characteristic as a type, similar to a class.
* Descriptor: The attribute defined in the descriptor (descriptor) is used to describe a characteristic value. For example, a descriptor can specify a readability description within an acceptable range for a value of characteristic, or specify a unit of measure for a characteristic value.
* Service:
A service is a collection of characteristic. For example, you can hold a service called "Heart rate Monitor", which contains characteristic such as "heart rate measurement". You can find a series of GATT-based profiles and service on

1.2 Roles and functions

Here are some of the applicable roles and functions of an Android device when interacting with a BLE device:

* Central equipment and peripheral equipment. This applies to the connection of the BLE itself. The device that serves as the central device role is responsible for scanning and searching for ads, and acting as a peripheral is responsible for sending ads.

* GATT Service side and GATT client. This depends on how two devices communicate with each other after establishing the connection.

To understand the difference between the two, imagine you have an Android phone and a ble device as an activity tracker. The phone will assume the central device role; the activity Tracker will assume the peripheral role (you need to have two roles to establish a BLE connection, both of which assume that the peripheral roles cannot communicate with each other, and both act as central device roles and cannot communicate with each other).

Once the phone and the activity tracker are connected, they can transfer the GATT media data to each other. Depending on the data they transmit, one party needs to assume the role of the server. For example, if the activity tracker wants to send sensor data to the phone, the activity tracker needs to serve as the server's role. If the activity tracker wants to receive data from the phone, the phone needs to serve as the server's role.

In the example of this document, the Android application (running on an Android device) is the GATT client. The application obtains data from the GATT server, which driven by a ble heart rate monitor device that supports heart rates profile. But you can alternately let your Android application play the role of the GATT server. Specific reference Bluetoothgattservice.

2. Ble Permissions (BLE permission)

In order to use the Bluetooth feature in your application, you must declare android.permission.BLUETOOTH permissions. You need this permission to perform some Bluetooth communication operations, such as requesting links, accepting connections, and transferring data.

If you want your app to scan your device or manage Bluetooth settings, you must also declare android.permission.BLUETOOTH_ADMIN permissions. Note that if you use Bluetooth_admin permissions, you must also declare the Bluetooth permission.

Declare the Bluetooth permissions in your application manifest file, for example:

<uses-permission android:name= "Android.permission.BLUETOOTH"/><uses-permission android:name= " Android.permission.BLUETOOTH_ADMIN "/>

If you want to declare that your application can only run on devices that support BLE, you can include the following declaration into your application manifest file:

<uses-feature android:name= "Android.hardware.bluetooth_le" android:required= "true"/>

However, if you want your application to be able to run on a device that does not support BLE, you should set the property in the tag above to required= "false". Then use the Packagemanager.hassystemfeature () method during the run to determine if the device supports BLE:

Use the following method to determine if the device supports BLE, and then you can choose to disable the BLE function if (!getpackagemanager (). Hassystemfeature (Packagemanager.feature_bluetooth _le) {    Toast.maketext (this, r.string.ble_not_supported, Toast.length_short). Show ();    Finish ();}

3. Setting up ble (set ble)

Before your application communicates with BLE, you need to confirm that the device supports BLE. If supported, confirm that it is enabled. Note that this check step is only required if the <uses-festure.../> is set to false.

If BLE is not supported, you should gracefully prohibit some of the features that use BLE. If BLE is supported, but is currently disabled, then you need to ask the user to enable Bluetooth enabled without leaving your application state. This process requires the use of bluetoothadapter, which is done in two steps:

3.1 Get Bluetoothadapter.

Basically all activity that uses Bluetooth needs bluetoothadapter. The bluetoothadapter represents the Bluetooth adapter (Bluetooth send receiver) of the device itself. There is a Bluetoothadapter object throughout the system, and your application can interact with that object. The following code snippet shows if you get the adapter. Note the following method uses the Getsystemservice () method to obtain a Bluetoothmanager instance, and then obtains bluetoothadapter through Bluetoothmanager. Android 4.3 (API level 18) only started to support Bluetoothmanager:

Initialize the Bluetooth adapter. Final Bluetoothmanager Bluetoothmanager =        (Bluetoothmanager) Getsystemservice (context.bluetooth_ SERVICE); mbluetoothadapter = Bluetoothmanager.getadapter ();

3.2 Bluetooth enabled

Next, you need to make sure that Bluetooth is up. Call the Isenable () method to check whether Bluetooth is currently enabled. If the method returns false, it means that Bluetooth is disabled. Check whether Bluetooth is enabled in the following code snippet. If not enabled, the code snippet displays an error prompting the user to go to the settings to enable Bluetooth:

Private Bluetoothadapter mbluetoothadapter;...//confirms that the device supports Bluetooth and is enabled. If not,//displays a dialog box asking the user to authorize Bluetooth enabled. if (Mbluetoothadapter = = NULL | |!mbluetoothadapter.isenabled ()) {    Intent enablebtintent = new Intent (bluetoothadapter.action_request_enable);    Startactivityforresult (Enablebtintent, REQUEST_ENABLE_BT);}

4. Finding ble Devices (search ble device)

To search for a ble device, you can use the Startlescan () method. This method requires a Bluetoothadapter.lescancallback object as a parameter. You must implement this callback interface, because the results of the scan will be returned through this interface. Since the search device is a power-hungry operation, you should follow these guidelines for use:

* Once you find your target device, you should stop searching right away.

* do not die loop search and set the maximum time to search. A previously accessible device may have been removed from the detectable range, and continued scanning will only consume power.

The following code snippet shows how to start and stop a search:

/** * Scans and displays activity that can access the BLE device. */public class Devicescanactivity extends Listactivity {    private bluetoothadapter mbluetoothadapter;    Private Boolean mscanning;    Private Handler Mhandler;    Stop scanning after 10 seconds.    Private static final Long scan_period = 10000;    ...    private void Scanledevice (final Boolean enable) {        if (enable) {            //) stops scanning after a predefined scan time period.            Mhandler.postdelayed (New Runnable () {                @Override public                void Run () {                    mscanning = false;                    Mbluetoothadapter.stoplescan (Mlescancallback);                }            }, scan_period);            Mscanning = true;            Mbluetoothadapter.startlescan (Mlescancallback);        } else {            mscanning = false;            Mbluetoothadapter.stoplescan (Mlescancallback);        }        ...    } ...}

If you only want to search for a specific type of peripheral device, you can replace the Startlescan (uuid[], Bluetoothadapter.lescancallback) method and provide an array of UUID objects that your application supports for the GATT service.

The following is an implementation of the Bluetoothadapter.lescancallback, which is an interface for receiving BLE search results:

Private Ledevicelistadapter mledevicelistadapter;...//Device search callback interface. Private Bluetoothadapter.lescancallback Mlescancallback =        New Bluetoothadapter.lescancallback () {    @Override public    void Onlescan (final Bluetoothdevice device, int rssi,            byte[] scanrecord) {        runonuithread (new Runnable () {           @Override           public void Run () {               mledevicelistadapter.adddevice (device);               Mledevicelistadapter.notifydatasetchanged ();}});}   ;

Note: As described in the Bluetooth documentation, you can only search for a BLE device or search for a traditional Bluetooth device at the same time. You cannot search for BLE devices and traditional Bluetooth devices at the same time.

5. Connecting to a GATT Server (connecting a GATT service)

The first step in interacting with a BLE device is to connect to it-more precisely, the GATT service on the connected device. To connect the GATT service on a BLE device, you can use the Connectgatt () method. This method requires three parameters: a Context object, AutoConnect (a Boolean value that indicates whether to automatically connect when the BLE device is reachable), and a Bluetoothgattcallbackduixiang:

Mbluetoothgatt = Device.connectgatt (this, false, mgattcallback);

The code above connects the GATT service managed by the BLE device and returns a Bluetoothgatt instance where it can perform operations related to the GATT client. This caller (Android application) is the GATT client. The Bluetoothgattcallback object inside is used to deliver the results of the operation to the client, such as the connection state, as well as the results of some future GATT client operations.

In this example, the BLE application provides an activity (devicecontrolactivity) to connect, display data, and display the service and characteristic of the GATT supported by the BLE device. Based on the user's input, this activity will communicate with a service called Bluetoothleservice, which interacts with the BLE device via the Android BLE API.

A service.public class Bluetoothleservice extends Service {Private final static String that interacts with the BLE device via the Android BLE API    TAG = BluetoothLeService.class.getSimpleName ();    Private Bluetoothmanager Mbluetoothmanager;    Private Bluetoothadapter Mbluetoothadapter;    Private String mbluetoothdeviceaddress;    Private Bluetoothgatt Mbluetoothgatt;    private int mconnectionstate = state_disconnected;    private static final int state_disconnected = 0;    private static final int state_connecting = 1;    private static final int state_connected = 2;    Public final static String action_gatt_connected = "Com.example.bluetooth.le.ACTION_GATT_CONNECTED";    Public final static String action_gatt_disconnected = "Com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; Public final static String action_gatt_services_discovered = "Com.example.bluetooth.le.ACTION_GATT_SERVICES_DIS    COVERED "; Public final static String action_data_available = "Com.examplE.bluetooth.le.action_data_available ";    Public final static String Extra_data = "Com.example.bluetooth.le.EXTRA_DATA"; Public final static UUID uuid_heart_rate_measurement = Uuid.fromstring (samplegattattributes.heart_rate_measurem    ENT);    The various callback methods defined by the BLE API. Private final Bluetoothgattcallback mgattcallback = new Bluetoothgattcallback () {@Override publi c void Onconnectionstatechange (Bluetoothgatt gatt, int status, int newstate) {String intentacti            On                if (newstate = = bluetoothprofile.state_connected) {intentaction = action_gatt_connected;                Mconnectionstate = state_connected;                Broadcastupdate (intentaction);                LOG.I (TAG, "Connecting GATT services.");            LOG.I (TAG, "Try to start service search:" + mbluetoothgatt.discoverservices ()); } else if (newstate = = bluetoothprofile.state_disconnected) {intentaction = ACtion_gatt_disconnected;                Mconnectionstate = state_disconnected;                LOG.I (TAG, "disconnect GATT server.");            Broadcastupdate (intentaction); }} @Override//New services discovered public void onservicesdiscovered (Bluetoothgatt GATT, int status) {if (status = = Bluetoothgatt.gatt_success) {broadcastupdate (action_gatt_services_d            iscovered);            } else {LOG.W (TAG, "onservicesdiscovered Received:" + status); }} @Override//Result of a characteristic read operation public void Oncharacteristicread (Bl Uetoothgatt GATT, bluetoothgattcharacteristic characteristic, int status) {if (s            Tatus = = bluetoothgatt.gatt_success) {broadcastupdate (action_data_available, characteristic); }        }     ...    }; ...}

When a particular callback method is called, it will appropriately invoke the Broadcastupdate () helper method and pass an action ID. Note The data in this section is parsed according to the profile specification of the Bluetooth heart rate measurement:

private void Broadcastupdate (final String action) {final Intent Intent = new Intent (action); Sendbroadcast (intent);} private void Broadcastupdate (final String action, final bluetoothgattcharacteristic Characteri    Stic) {final Intent Intent = new Intent (action);    Specific processing according to the profile of the heart rate measurement.    Follow a profile specification for data parsing.        if (Uuid_heart_rate_measurement.equals (Characteristic.getuuid ())) {int flag = characteristic.getproperties ();        int format =-1;            if (flag & 0x01)! = 0) {format = bluetoothgattcharacteristic.format_uint16;        LOG.D (TAG, "heart rate format UINT16.");            } else {format = bluetoothgattcharacteristic.format_uint8;        LOG.D (TAG, "heart rate format UINT8.");        } final int heartrate = characteristic.getintvalue (format, 1);        LOG.D (TAG, String.Format ("Received heart rate:%d", heartrate));    Intent.putextra (Extra_data, string.valueof (heartrate)); } ElSE {//For other profiles, format the data as 16 forbidden data.        Final byte[] data = Characteristic.getvalue (); if (data! = null && data.length > 0) {final StringBuilder StringBuilder = new StringBuilder (data.le            Ngth);            for (byte bytechar:data) stringbuilder.append (String.Format ("%02x", Bytechar));        Intent.putextra (Extra_data, New String (DATA) + "\ n" + stringbuilder.tostring ()); }} sendbroadcast (intent);}

Back to Devicecontrolactivity, the following event is handled by a broadcasereceiver:

Handle the various times the service is sent over.//action_gatt_connected: Connected to a GATT service.//action_gatt_disconnected: Disconnected a GATT service.//Action_gatt _services_discovered: The GATT service was found.//action_data_available: Receives data from the device. This may be the result of a read or notification operation. Private final Broadcastreceiver mgattupdatereceiver = new Broadcastreceiver () {@Override public void onreceive (Cont        Ext context, Intent Intent) {final String action = Intent.getaction ();            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals (ACTION)) {mconnected = true;            Updateconnectionstate (r.string.connected);        Invalidateoptionsmenu ();            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals (ACTION)) {mconnected = false;            Updateconnectionstate (r.string.disconnected);            Invalidateoptionsmenu ();        Clearui ();                } else if (Bluetoothleservice.            Action_gatt_services_discovered.equals (Action)) {//displays all supported service and characteristic. Displaygattservices (MBluetoothleservice.getsupportedgattservices ()); } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals (ACTION)) {Displaydata (Intent.getstringextra (Bluetoo        Thleservice.extra_data)); }    }};

6. Reading ble Attribute (read ble property)

Once your Android application connects to a GATT service and discovers the service on the device, you can read and write properties in the read-write location. For example, the following code fragment iterates through service and characteristic of services and displays them on the interface:

public class Devicecontrolactivity extends Activity {...///shows how to iterate over the supported GATT Services/characteristics.    In this example, we populate the data structure bound to Expandablelistview.         private void Displaygattservices (list<bluetoothgattservice> gattservices) {if (gattservices = = null) return;        String uuid = null;                String unknownservicestring = Getresources ().        GetString (R.string.unknown_service);                String unknowncharastring = Getresources ().        GetString (r.string.unknown_characteristic); arraylist

7. Receiving GATT Notification (receiving GATT notice)

The BLE application requires that it is common to receive notifications when a specified characteristic of a device changes. The following code snippet shows how to set up notifications for a characteristic by using setcharacteristicnotification ():

Private Bluetoothgatt Mbluetoothgatt; Bluetoothgattcharacteristic Characteristic;boolean Enabled;...mbluetoothgatt.setcharacteristicnotification ( characteristic, enabled);.. Bluetoothgattdescriptor descriptor = characteristic.getdescriptor (        uuid.fromstring ( samplegattattributes.client_characteristic_config));d Escriptor.setvalue (bluetoothgattdescriptor.enable_ Notification_value); Mbluetoothgatt.writedescriptor (descriptor);

Once the notification is enabled for a characteristic, the oncharacteristicchanged () method is triggered when the characteristic on the remote device changes:

@Override//characteristic notificationpublic void oncharacteristicchanged (Bluetoothgatt GATT,        Bluetoothgattcharacteristic characteristic) {    broadcastupdate (action_data_available, characteristic);}

8. Closing the client app (close the Clients app)

Once your application is finished using the BLE device, you should call the close () method so that the system can properly free up the resources it uses:

public void Close () {    if (Mbluetoothgatt = = null) {        return;    }    Mbluetoothgatt.close ();    Mbluetoothgatt = null;}

Original address:

Android Bluetooth Low power (Android Bluetooth)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.