低功耗蓝牙 BLE 客户端篇

最近忙着折腾智能手表Android Wear2.0的开发,由于国内用不了play服务,所以谷歌为wear提供的一套和手机通信的API都不能用。为了在手机和手表之间传递数据,我不得不考虑使用蓝牙来建立手机和手表之间的通讯。在这个过程中被坑了许多次,所以记录下来方便自己查阅。
(PS: 国内有的教程使用的API以被弃用,许多东西是我自己看着官方文档总结出来的,如有不对的地方请帮我指出来。)


1.准备工作

工欲善其事,必先利其器。Android Wear2.0时的目标SDK版本已经在23以上了,安卓在6.0的时候加入了运行时权限系统,所以想开发蓝牙客户端的第一步,就是拿到应用所需要的必要权限。

需要的权限如下:

  • android.permission.BLUETOOTH
  • android.permission.BLUETOOTH_ADMIN
  • android.permission.ACCESS_COARSE_LOCATION

对于前两个权限,比较好理解,一个用于连接蓝牙设备,一个用于搜索蓝牙设备。可是这最后一个模糊地理位置权限是什么鬼?原来谷歌认为扫描周围蓝牙4.0设备可以获取用户的大概位置,所以要求开发者申请模糊位置权限。没有这个权限的话虽然能正常开始扫描蓝牙BLE设备,但是一个结果都不会返回,一点儿用都没有。

首先在AndroidManifest.xml之中声明权限:

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

接着,需要在运行时申请权限:

//首先判断是否是安卓6.0以上,然后申请权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        this.requestPermissions(new String[]{
                Manifest.permission.BLUETOOTH_ADMIN,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.ACCESS_COARSE_LOCATION
    },0);
}

之后在onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) 回调方法中确认用户是否同意了权限。


2.查找蓝牙BLE设备

查找蓝牙设备要用到这样几个类:

  • BluetoothManager 蓝牙管理器
  • BluetoothAdapter 这个是我们本机的蓝牙设备
  • BluetoothLeScanner 低功耗蓝牙BLE扫描器
  • ScanCallback 扫描器需要使用的回调

基本过程就是,首先获取BluetoothManager,然后通过BluetoothManager获取到BluetoothAdapter,BluetoothAdapter获取到BluetoothLeScanner,用BluetoothLeScanner来注册回调并扫描蓝牙BLE设备。

BluetoothManager bm = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
BluetoothAdapter adapter = bm.getAdapter();
BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
scanner.startScan(scanCallback);  //scanCallback是回调

如此便开始了扫描进程。接下来扫描的结果,会通过ScanCallback里面的
onScanResult(int callbackType, ScanResult result)方法返回,
result.getDevice()方法可以返回扫描到的蓝牙设备BluetoothDevice对象,这个就是我们下一步连接用的必要对象。


3.连接蓝牙BLE设备

连接蓝牙设备要用到这样几个类:

  • BluetoothDevice 蓝牙设备
  • BluetoothGatt 手机和蓝牙设备连接的“通道”
  • BluetoothGattCallback 和蓝牙设备通讯的回调,收发数据相关的代码都在这里实现

连接蓝牙BLE设备就比较容易了:

bluetoothDevice.connectGatt(this,false,gattCallback);

接着在gattCallback里面重写
onConnectionStateChange(BluetoothGatt gatt, int status, int newState)方法
判断当连接成功时,就可以保存gatt引用,使用方法传入的gatt对象和蓝牙BLE设备通讯了。
不过这里有个坑,gattCallback里面的回调并不是运行在主线程上面的,也就是说在回调之中不能直接操作UI对象,需要通知主线程来更改UI。

标签: bluetooth-ble

评论已关闭