[资料分享] Android 5.0 BLE低功耗蓝牙从设备应用

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


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


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


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


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


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


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





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


1     
2     



接着我们上套路了,判断手机是否支持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 = 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                 @Override
39                 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         @Override
101         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                 @Override
107                 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         @Override
123         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                 @Override
133                 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)试试,说不定就柳暗花明了。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复