首页 > 代码库 > 【原创】Android 5.0 BLE低功耗蓝牙从设备应用

【原创】Android 5.0 BLE低功耗蓝牙从设备应用

如果各位觉得有用,转载+个出处。

现如今安卓的低功耗蓝牙应用十分普遍了,智能手环、手表遍地都是,基本都是利用BLE通信来交互数据。BLE基本在安卓、IOS两大终端设备上都有很好支持,所以有很好发展前景。

现市面上各种手环、手表的智能设备中基本都充当"从设备"这样的角色,基本由智能设备完成蓝牙广播,由手机进行连接,然后交互数据。

根据上述方式的应用在安卓4.3、IOS 7.0的版本上就得到了支持,应用也比较广泛,园里应该有很多相关实现,大家可以自己找找,如果不愿意找,抽空再写一篇。

今天主要是为了说在安卓5.0时升级了广播相关API,园里也有一些说明,但之所以还写这篇是因为数据交换的提及很少。

既然将手机要做广播了,那么实质手机就变成手环、手表的角色,一个从设备了。

如果你愿意,可以拿另一台手机做个主设备,这样他们就可以交流了。

好了,我们进入代码正题吧...

 

首先应用权限设置。在AndroidManifest.xml中还是要加入BLE控制权限,不然异常一定与你为伍。

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

 

 接着我们上套路了,判断手机是否支持BLE以及是否支持BLE从设备。

 1   if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { 2             showToast("该设备不支持蓝牙低功耗通讯"); 3             this.finish(); 4             return; 5         } 6  7         bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); 8  9         bluetoothAdapter = bluetoothManager.getAdapter();10 11         if (bluetoothAdapter == null) {12             showToast("该设备不支持蓝牙低功耗通讯");13             this.finish();14             return;15         }16 17         bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();18         if (bluetoothLeAdvertiser == null) {19             showToast("该设备不支持蓝牙低功耗从设备通讯");20             this.finish();21             return;22         }

我建议你先拿你调试设备试试,大多数同学走到这里都绝望了。你问我为啥?你试试就知道了。

 

如果你一脸what???的话,那恭喜你,你的调试设备是被选中的孩子,让我们继续乘风破浪吧。顺便在评论里告诉我下你用啥设备哦。

这时候我们开启广播的旋风吧。

 1  //广播设置 2         AdvertiseSettings.Builder settingBuilder = new AdvertiseSettings.Builder(); 3         settingBuilder.setConnectable(true); 4         settingBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED); 5         settingBuilder.setTimeout(0); //我填过别的,但是不能广播。后来我就坚定的0了 6         settingBuilder.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH); 7         AdvertiseSettings settings = settingBuilder.build(); 8  9 10         //广播参数11         AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();12         bluetoothAdapter.setName("H8-BlePpl"); //你想叫啥名字,你愿意就好13         dataBuilder.setIncludeDeviceName(true);14         dataBuilder.setIncludeTxPowerLevel(true);15 16         dataBuilder.addServiceUuid(ParcelUuid.fromString(Const.UUID_SERVICE)); //可自定义UUID,看看官方有没有定义哦17         AdvertiseData data =http://www.mamicode.com/ dataBuilder.build();18 19         bluetoothLeAdvertiser.startAdvertising(settings, data, advertiseCallback);

然后你的小手机就开始广播了,说大家来连我啊连我啊。别总搜地址,貌似地址动态会变的,还是用名儿吧毕竟你起了啊。

我之前傻傻的查了手机蓝牙MAC地址,后来发现不是广播的那个...

广播回调我干了点新增服务的活儿,不干你拿啥通信来。

 1  private AdvertiseCallback advertiseCallback = new AdvertiseCallback() { 2         @Override 3         public void onStartSuccess(AdvertiseSettings settingsInEffect) { 4             super.onStartSuccess(settingsInEffect); 5             runOnUiThread(new Runnable() { 6                 @Override 7                 public void run() { 8                     showInfo("1.1 AdvertiseCallback-onStartSuccess"); 9                 }10             });11 12 13             bluetoothGattServer = bluetoothManager.openGattServer(getApplicationContext(),14                     bluetoothGattServerCallback);15 16             BluetoothGattService service = new BluetoothGattService(UUID.fromString(Const.UUID_SERVICE),17                     BluetoothGattService.SERVICE_TYPE_PRIMARY);18 19             UUID UUID_CHARREAD = UUID.fromString(Const.UUID_CHARACTERISTIC);20 21             //特征值读写设置22             BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(UUID_CHARREAD,23                     BluetoothGattCharacteristic.PROPERTY_WRITE |24                             BluetoothGattCharacteristic.PROPERTY_READ |25                             BluetoothGattCharacteristic.PROPERTY_NOTIFY,26                     BluetoothGattCharacteristic.PERMISSION_WRITE);27 28             UUID UUID_DESCRIPTOR = UUID.fromString(Const.UUID_CHARACTERISTIC_CONFIG);29 30             BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE);31             characteristicWrite.addDescriptor(descriptor);32             service.addCharacteristic(characteristicWrite);33 34             bluetoothGattServer.addService(service);35 36 37             runOnUiThread(new Runnable() {38                 @Override39                 public void run() {40                     showInfo("1.2. Service Builded ok");41                 }42             });43 44         }};

当你收到广播成功回调后,来吧,特征值啊~~反正要通信呐~~

被你发现了我偷懒读写特征值用了一个,其实你愿意用两个就用两个吧。

我用的NOTIFICATION方式做主设备的读取,你也可用INDICATION方式做。

服务建立完成后,也会收到通知。BLE嘛~~都是异步回调~~我是习惯了!

  1   private BluetoothGattServerCallback bluetoothGattServerCallback = new BluetoothGattServerCallback() {  2         @Override  3         public void onServiceAdded(int status, BluetoothGattService service) {  4             super.onServiceAdded(status, service);  5   6             final String info = service.getUuid().toString();  7             runOnUiThread(new Runnable() {  8                 @Override  9                 public void run() { 10                     showInfo("1.3 BluetoothGattServerCallback-onServiceAdded " + info); 11                 } 12             }); 13  14  15         } 16  17         @Override 18         public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { 19             super.onConnectionStateChange(device, status, newState); 20             final String info = device.getAddress() + "|" + status + "->" + newState; 21  22             runOnUiThread(new Runnable() { 23                 @Override 24                 public void run() { 25                     showInfo("1.4 onConnectionStateChange " + info); 26                 } 27             }); 28         } 29  30         @Override 31         public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, 32                                                 BluetoothGattCharacteristic characteristic) { 33             super.onCharacteristicReadRequest(device, requestId, offset, characteristic); 34  35  36             final String deviceInfo = "Address:" + device.getAddress(); 37             final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + characteristic.getUuid() + "|Value:" + 38                     Util.bytes2HexString(characteristic.getValue()); 39  40             runOnUiThread(new Runnable() { 41                 @Override 42                 public void run() { 43  44                     showInfo("============================================="); 45                     showInfo("设备信息 " + deviceInfo); 46                     showInfo("数据信息 " + info); 47                     showInfo("=========onCharacteristicReadRequest========="); 48  49                 } 50             }); 51  52             bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue()); 53  54         } 55  56         @Override 57         public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { 58             super.onCharacteristicWriteRequest(device, requestId, characteristic, 59                     preparedWrite, responseNeeded, offset, value); 60  61             final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress(); 62             final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + characteristic.getUuid() + "|Value:" + Util.bytes2HexString(value); 63  64  65             bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value); 66            //TODO:你做数据处理 67  68  69             runOnUiThread(new Runnable() { 70                 @Override 71                 public void run() { 72  73                     showInfo("============================================="); 74                     showInfo("设备信息 " + deviceInfo); 75                     showInfo("数据信息 " + info); 76                     showInfo("=========onCharacteristicWriteRequest========="); 77  78                 } 79             }); 80  81  82         } 83  84  85         @Override 86         public void onNotificationSent(BluetoothDevice device, int status) { 87             super.onNotificationSent(device, status); 88  89             final String info = "Address:" + device.getAddress() + "|status:" + status; 90  91             runOnUiThread(new Runnable() { 92                 @Override 93                 public void run() { 94                     showInfo("onNotificationSent " + info); 95                 } 96             }); 97         } 98  99 100         @Override101         public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {102             final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress();103             final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + descriptor.getUuid() + "|Value:" + Util.bytes2HexString(value);104 105             runOnUiThread(new Runnable() {106                 @Override107                 public void run() {108 109                     showInfo("=============================================");110                     showInfo("设备信息 " + deviceInfo);111                     showInfo("数据信息 " + info);112                     showInfo("=========onDescriptorWriteRequest=========");113 114                 }115             });116 117 118             // 告诉连接设备做好了119             bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);120         }121 122         @Override123         public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {124 125             super.onDescriptorReadRequest(device, requestId, offset, descriptor);126 127             final String deviceInfo = "Name:" + device.getAddress() + "|Address:" + device.getAddress();128             final String info = "Request:" + requestId + "|Offset:" + offset + "|characteristic:" + descriptor.getUuid();129 130 131             runOnUiThread(new Runnable() {132                 @Override133                 public void run() {134 135                     showInfo("=============================================");136                     showInfo("设备信息 " + deviceInfo);137                     showInfo("数据信息 " + info);138                     showInfo("=========onDescriptorReadRequest=========");139 140                 }141             });142 143             // 告诉连接设备做好了144             bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);145 146 147         }148 149     };

基本上从设备就做完了。

调试的时候你用主设备查服务列表可能查不到你的UUID_SERVICE,但是别慌,你getServcie(UUID_SERVICE)试试,说不定就柳暗花明了。

 

还有就是我拿的华为Honor 8做的调试机子,其他还有啥型号请各位分享下。姑娘我跪谢啦~~

【原创】Android 5.0 BLE低功耗蓝牙从设备应用