zoukankan      html  css  js  c++  java
  • 【原创】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做的调试机子,其他还有啥型号请各位分享下。姑娘我跪谢啦~~

  • 相关阅读:
    hdu5360 Hiking(水题)
    hdu5348 MZL's endless loop(欧拉回路)
    hdu5351 MZL's Border(规律题,java)
    hdu5347 MZL's chemistry(打表)
    hdu5344 MZL's xor(水题)
    hdu5338 ZZX and Permutations(贪心、线段树)
    hdu 5325 Crazy Bobo (树形dp)
    hdu5323 Solve this interesting problem(爆搜)
    hdu5322 Hope(dp)
    Lightoj1009 Back to Underworld(带权并查集)
  • 原文地址:https://www.cnblogs.com/michaelzero/p/6796689.html
Copyright © 2011-2022 走看看