1、关键概念:
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。
2、角色和职责:
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端可能更合适。
3、权限及feature:
和经典蓝牙同样,应用使用蓝牙,须要声明BLUETOOTH权限,若是须要扫描设备或者操做蓝牙设置,则还须要BLUETOOTH_ADMIN权限:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
除了蓝牙权限外,若是须要BLE feature则还须要声明uses-feature:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
按时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();
}
4、启动蓝牙:
在使用蓝牙BLE以前,须要确认Android设备是否支持BLE feature(required为false时),另外要须要确认蓝牙是否打开。
若是发现不支持BLE,则不能使用BLE相关的功能。若是支持BLE,可是蓝牙没打开,则须要打开蓝牙。
打开蓝牙的步骤:
一、获取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)。
二、判断是否支持蓝牙,并打开蓝牙
获取到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);
}
5、搜索BLE设备:
因为搜索须要尽可能减小功耗,所以在实际使用时须要注意:
一、当找到对应的设备后,当即中止扫描;
二、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。
搜索的示例代码以下:
/**
* Activity for scanning and displaying available BLE devices.
*/
public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
...
}
...
}
其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
private LeDeviceListAdapter mLeDeviceListAdapter;
...
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,二者彻底独立,不可同时被搜索。
6、链接GATT Server:
两个设备经过BLE通讯,首先须要创建GATT链接。这里咱们讲的是Android设备做为client端,链接GATT Server。
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
BluetoothGatt常规用到的几个操做示例:
connect() :链接远程设备。
discoverServices() : 搜索链接设备所支持的service。
disconnect():断开与远程设备的GATT链接。
close():关闭GATT Client端。
readCharacteristic(characteristic) :读取指定的characteristic。
setCharacteristicNotification(characteristic, enabled) :设置当指定characteristic值变化时,发出通知。
getServices() :获取远程设备所支持的services。
等等。
注:
一、某些函数调用之间存在前后关系。例如首先须要connect上才能discoverServices。
二、 一些函数调用是异步的,须要获得的值不会当即返回,而会在BluetoothGattCallback的回调函数中返回。例如 discoverServices与onServicesDiscovered回调,readCharacteristic与 onCharacteristicRead回调,setCharacteristicNotification与 onCharacteristicChanged回调等。
http://www.blogjava.net/zh-weir/archive/2014/04/02/407373.html