Android4.3 蓝牙BLE初步
一、关键概念: **Generic Attribute Profile (GATT)** 通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。 **Attribute Protocol (ATT)** GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。 **Characteristic** Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。 **Descriptor** 对Characteristic的描述,例如范围、计量单位等。 **Service** Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement”的Characteristic。 二、角色和职责: Android设备与BLE设备交互有两组角色: 中心设备和外围设备(Central vs. peripheral); GATT server vs. GATT client. Central vs. peripheral: 中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。 GATT server vs. GATT client: 这两种角色取决于BLE连接成功后,两个设备间通信的方式。 举例说明: 现有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。 当连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。 三、权限及feature: 和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限: 除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature: 按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature: // Use this check to determine whether BLE is supported on the device. Then // you can selectively disable BLE-related features. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); finish(); } 四、启动蓝牙: 在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。 如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。 打开蓝牙的步骤: 1、获取BluetoothAdapter BluetoothAdapter是Android系统中所有蓝牙操作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙操作了。 获取BluetoothAdapter代码示例如下: // Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); 注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API level 18)。 2、判断是否支持蓝牙,并打开蓝牙 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。 如果没打开,需要让用户打开蓝牙: private BluetoothAdapter mBluetoothAdapter; … // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } 五、搜索BLE设备: 通过调用BluetoothAdapter的[startLeScan()](http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback))搜索BLE设备。调用此方法时需要传入 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`参数。 因此你需要实现 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`接口,BLE设备的搜索结果将通过这个callback返回。 由于搜索需要尽量减少功耗,因此在实际使用时需要注意: 1、当找到对应的设备后,立即停止扫描; 2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。 搜索的示例代码如下: /** * Activity for scanning and displaying available BLE devices. */ public class DeviceScanActivity extends ListActivity { private BluetoothAdapter mBluetoothAdapter; private boolean mScanning; private Handler mHandler; ...