FireBLE/First app for android

来自Firefly wiki
跳转至: 导航搜索

Android BLE

Android的4.3(API Level 18)support the buletooth Low power function,It provide more API,API help developer found devices,check,read & write when develop application,BLE Low power let Android app work lunch more time,like proximity sensor, heart rate display,fitness equipment,etc.

Concepts

  • Generic Attribute Profile (GATT) GATT is the General specifications when BLE sent data or receive data.
  • Attribute Protocol (ATT) property protocol is base on UUID,it use for mark property.
  • Characteristic contains one vaule and“0”or several descriptor
  • Descriptor is a property use for Characteristic
  • Service is a unit for Characteristic

Roles and Responsibilities

The roles divided central and peripheral.For example,the Android phone and BLE heart rate display,Android phone is the central,it controls BLEheart rate display;BLE heart rate display is the peripheral,it is controlled by Android phone.

BLE Promissions

When devloping BLE,Android application need this permission:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
In addition,when application need to judge BLE exist or not,we can modify AndroidManifest.xml like this:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
in the code,we can judge like this:

 // Use this check to determine whether BLE is supported on the device. Then
 // you can selectively disable BLE-related features.
 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
     Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
     finish();
 }

BLE development

Setting of BLE

1.Get BluetoothAdapter

 // Initializes Bluetooth adapter.
 final BluetoothManager bluetoothManager =
         (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
 mBluetoothAdapter = bluetoothManager.getAdapter();

2.Open Bluetooth

 private BluetoothAdapter mBluetoothAdapter;
 ...
 // Ensures Bluetooth is available on the device and it is enabled. If not,
 // displays a dialog requesting user permission to enable Bluetooth.
 if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
 }

Scanning BLE devices

When we need to find BLE device,we need to use startLeScan() function,this function use BluetoothAdapter.LeScanCallback Object as a parameter.When we stop to find Ble device,we need to use stopLeScan()function,this function use BluetoothAdapter.LeScanCallback Object as a parameter

 /**
  * Activity for scanning and displaying available BLE devices.
  */
 public class DeviceScanActivity extends ListActivity {
 
     private BluetoothAdapter mBluetoothAdapter;
     private boolean mScanning;
     private Handler mHandler;
 
     // Stops scanning after 10 seconds.
     private static final long SCAN_PERIOD = 10000;
     ...
     private void scanLeDevice(final boolean enable) {
         if (enable) {
             // Stops scanning after a pre-defined scan 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);
         }
         ...
     }
 ...
     private LeDeviceListAdapter mLeDeviceListAdapter;
 ...
     // Device scan callback.
     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();
              }
           });
        }
     };
 }

Connect to GATT Server

When we need to Connect Ble device,we need connectGatt() function,this function has 3 parameter,a Context object,a bool use for mark autoconnect,a BluetoothGattCallback object

 mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
 BluetoothGattCallback is a callback methods of BLE connecting status:
     // Various callback methods defined by the BLE API.
     private final BluetoothGattCallback mGattCallback =
             new BluetoothGattCallback() {
         @Override
         public void onConnectionStateChange(BluetoothGatt gatt, int status,
                 int newState) {
             String intentAction;
             if (newState == BluetoothProfile.STATE_CONNECTED) {
                 intentAction = ACTION_GATT_CONNECTED;
                 mConnectionState = STATE_CONNECTED;
                 broadcastUpdate(intentAction);
                 Log.i(TAG, "Connected to GATT server.");
                 Log.i(TAG, "Attempting to start service discovery:" +
                         mBluetoothGatt.discoverServices());
 
             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                 intentAction = ACTION_GATT_DISCONNECTED;
                 mConnectionState = STATE_DISCONNECTED;
                 Log.i(TAG, "Disconnected from GATT server.");
                 broadcastUpdate(intentAction);
             }
         }
 
         @Override
         // New services discovered
         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
             if (status == BluetoothGatt.GATT_SUCCESS) {
                 broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
             } else {
                 Log.w(TAG, "onServicesDiscovered received: " + status);
             }
         }
 
         @Override
         // Result of a characteristic read operation
         public void onCharacteristicRead(BluetoothGatt gatt,
                 BluetoothGattCharacteristic characteristic,
                 int status) {
             if (status == BluetoothGatt.GATT_SUCCESS) {
                 broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
             }
         }
      ...
     };

Read GATT

When we Read GATT,we need use readCharacteristic() function,thie function have a BluetoothGattCharacteristic object as parameter:

     public boolean readCharacteristic(UUID gatservice_uuid,UUID char_uuid){
     	synchronized(mGattLock){
     		try{
 		    	if(mBluetoothGatt==null || mBluetoothGattServiceList==null) return false;
 		    	BluetoothGattService bgs = mBluetoothGatt.getService(gatservice_uuid);
 		    	if(bgs==null) return false;
 		    	BluetoothGattCharacteristic bgc = bgs.getCharacteristic(char_uuid);
 		    	if(bgc==null) return false;
 		    	int properties = bgc.getProperties();
 		    	if(((properties&BluetoothGattCharacteristic.PROPERTY_READ ) == BluetoothGattCharacteristic.PROPERTY_READ ))
 				{
 		    		return mBluetoothGatt.readCharacteristic(bgc);
 				}else{
 					LOGD(gatservice_uuid+"->"+char_uuid+" can not read !");
 					return false;
 				}
     		}catch(Exception ex){
     			return false ;
     		}
            }
        }

Write GATT

When we write GATT we need use writeCharacteristic()function,thie function have a BluetoothGattCharacteristic object as parameter:

     public boolean writeCharacteristic(UUID gatservice_uuid,UUID char_uuid,String value){
     	synchronized(mGattLock){
     		try{
 		    	if(mBluetoothGatt==null || mBluetoothGattServiceList==null) return false;
 		    	BluetoothGattService bgs = mBluetoothGatt.getService(gatservice_uuid);
 		    	if(bgs==null){
 		    		LOGD("bgs:"+bgs+"->"+" can not find ! write error");
 		    		return false;
 		    	}
 		    	BluetoothGattCharacteristic bgc = bgs.getCharacteristic(char_uuid);
 		    	if(bgc==null) {
 		    		LOGD("bgc:"+bgc+"->"+" can not find ! write error");
 		    		return false;
 		    	}
 		    	int properties = bgc.getProperties();
 		    	if( ( ( properties&BluetoothGattCharacteristic.PROPERTY_WRITE ) == BluetoothGattCharacteristic.PROPERTY_WRITE )
 		    			|| ( ( properties&BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE ) == BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE )
 		    			|| ( ( properties&BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE ) == BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE ) )
 				{
 		    		bgc.setValue(value);
 		    		return mBluetoothGatt.writeCharacteristic(bgc);
 				}else{
 					LOGD(gatservice_uuid+"->"+char_uuid+" can not write !");
 					return false;
 				}
     		}catch(Exception ex){
     			LOGD("writeCharacteristic mBluetoothGatt dead .");
     			return false ;
     		}
     	}

}

Receive BLE Notification

When we receive BLE notification we need use setCharacteristicNotification()function,thie function have a BluetoothGattDescriptor object as parameter:

     private static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
     public boolean setCharacteristicNotification(UUID gatservice_uuid,UUID char_uuid,boolean enable){
     	synchronized(mGattLock){
     		try{
 		    	if(mBluetoothGatt==null || mBluetoothGattServiceList==null) return false;
 		    	BluetoothGattService bgs = mBluetoothGatt.getService(gatservice_uuid);
 		    	if(bgs==null) return false;
 		    	BluetoothGattCharacteristic bgc = bgs.getCharacteristic(char_uuid);
 		    	if(bgc==null) return false;
 		    	int properties = bgc.getProperties();
 		    	if((properties&BluetoothGattCharacteristic.PROPERTY_NOTIFY ) == BluetoothGattCharacteristic.PROPERTY_NOTIFY )
 				{
 		    		if(mBluetoothGatt.setCharacteristicNotification(bgc,enable))
 		    		{
 		    			BluetoothGattDescriptor descriptor = bgc.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
 		                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
 		                return mBluetoothGatt.writeDescriptor(descriptor);
 		    		}else{
 		    			return false;
 		    		}
 				}else{
 					LOGD(gatservice_uuid+"->"+char_uuid+" can not notify !");
 					return false;
 				}
   		}catch(Exception ex){
     			LOGD("setCharacteristicNotification mBluetoothGatt dead .");
     			return false ;
     		}
     	}
     }

Close application

When we have no need to use the BLE device,we should use close()method to close application:

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