• 【原创】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 = 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)试试,说不定就柳暗花明了。

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

  • 相关阅读:
    leetcode 912. 排序数组
    leetcode 633. 平方数之和
    leetcode 1512. 好数对的数目
    leetcode 1822. 数组元素积的符号
    leetcode 145. 二叉树的后序遍历
    leetcode 11. 盛最多水的容器
    leetcode 28 实现strStr()
    leetcode 27. 移除元素
    leetcode 26. 删除有序数组中的重复项
    产品化思维之公式系统
  • 原文地址:https://www.cnblogs.com/michaelzero/p/6796689.html
Copyright © 2020-2023  润新知