开发入门
更新时间:2017-08-08 阅读:3810
目录
Android BLE
Android的4.3(API Level 18)引入了蓝牙低耗能的内置平台支持,提供相应的API,应用程序可以用它来发现设备,查询服务,和读/写特征。在对比传统蓝牙,蓝牙低功耗(BLE)被设计成更低的功耗,这允许Android应用使用具有低功率的设备,如接近传感器,心脏速率显示器,健身设备,等等BLE设备。
基本概念
- Generic Attribute Profile (GATT) GATT是在BLE连接中用以接收和发送属性数据的通用规格。
- Attribute Protocol (ATT) 属性协议是以UUID来标识属性的协议。
- Characteristic 特征包含一个值和0或n个描述该值的描述符。
- Descriptor 描述符是一个用以描述特征值的属性。
- Service 服务是是特征的集合。
角色和职责
角色分为中央(Central)和周边(peripheral),以Android手机和BLE心脏速率显示器为例,Android手机的角色就是中央,它的职责是控制BLE心脏速率显示器;而BLE心脏速率显示器的角色是周边,它的职责是响应Android手机的控制。
BLE权限
在BLE开发中,Android应用需要以下权限:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
另外,应用判断存不存在BLE特性,可以在AndroidManifest.xml中加入:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
而在代码中,可以这样判断:
// 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开发
设置BLE
1.获取BluetoothAdapter
// Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter();
2.打开蓝牙
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); }
查找BLE设备
要查找BLE设备,你要调用startLeScan()方法,这个方法以一个BluetoothAdapter.LeScanCallback对象作为参数。停止查找,你要调用stopLeScan()方法,这个方法以一个BluetoothAdapter.LeScanCallback对象作为参数。
/** * 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(); } }); } }; }
连接到GATT Server
连接设备调用connectGatt()方法,这个方法有3个参数,一个Context对象,一个表示自动连接的布尔值,一个BluetoothGattCallback对象:
mBluetoothGatt = device.connectGatt(this, false, mGattCallback); BluetoothGattCallback是一个BLE连接状态的回调: // 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); } } ... };
读GATT属性
读GATT属性要调用readCharacteristic()方法,这个方法有一个BluetoothGattCharacteristic对象作为参数:
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 ; } } }
写GATT属性
读GATT属性要调用writeCharacteristic()方法,这个方法有一个BluetoothGattCharacteristic对象作为参数:
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 ; } } }
接收BLE通知
接收BLE通知要调用setCharacteristicNotification()方法,这方法有一个BluetoothGattDescriptor对象作为参数:
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 ; } } }
关闭客户端应用
使用完BLE设备,需要调用close()方法:
public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; }