①配置权限
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
②检测设备是否支持BLE
1、需要在manifest中配置
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
2、在Activity的onCreate中检测
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
//手机不支持BLE,提示用户并退出
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
③获取BluetoothAdapter
//①API18及以上版本获取BluetoothAdapter方法
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//②原始方式
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
④打开蓝牙
//①直接打开,不带用户界面
bluetoothAdapter.enable();
//②发送隐士意图,询问用户是否打开
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
⑤搜索BLE设备
// 10秒以后停止搜索 (很重要).
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
if (enable) {
// 到达预设停止时间后,停止搜索
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);
}
...
}
=========================================================
//接收搜索回调的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设备或者传统蓝牙设备,同一时间不可以同时搜索两种设备。
⑥连接蓝牙设备获取BluetoothGatt(很重要,交互的主要对象)
mBluetoothGatt = device.connectGatt(this, false, mGattCallback)
BluetoothGattCallback –> mGattCallback(很重要,客户端蓝牙设备与远端蓝牙设备的交互的数据的回传都有其负责)
⑦处理回传数据
连接(结果会回调到mGattCallback的onConnectionStateChange中)–成功–>查找服务(结果会回调到mGattCallback的onServicesDiscovered中)–找到对应服务–>解析其中的特性(characteristic),针对期可读、可写、可被通知的特性进行操作,达到与远端蓝牙设备进行数据交互的目的。
当主动去读取远端设备数据时,会回调到mGattCallback的onCharacteristicRead方法
当往远端设备写入数据时,会回调到mGattCallback的onCharacteristicWrite方法
当远端设备数据发生变化,会回调到mGattCallback的onCharacteristicChanged方法
针对期可读、可写、可被通知的特性进行操作–示例
int i = paramBluetoothGattCharacteristic.getProperties();
if ((i | 0x2) > 0) //读取远端设备数据
{
if (this.mNotifyCharacteristic != null)
{
setCharacteristicNotification(this.mNotifyCharacteristic, false);
this.mNotifyCharacteristic = null;
}
readCharacteristic(paramBluetoothGattCharacteristic);
}
if ((i | 0x8) > 0) //向远端设备写数据
{
paramBluetoothGattCharacteristic.setValue(Constants.hexStringToByteArray("FDFDFA050D0A"));
this.mGatt.writeCharacteristic(paramBluetoothGattCharacteristic);
}
if ((i | 0x10) > 0) //设置可被通知的特性,远端设备该属性发生变化时,回调
{
this.mNotifyCharacteristic = paramBluetoothGattCharacteristic;
setCharacteristicNotification(paramBluetoothGattCharacteristic, true);
}
======================================================
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,boolean enabled) {
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
//(很重要)这里注意,虽然这里说明以下操作是针对心率测量的服务而言,但是建议大家在做蓝牙BLE开发时,如果需要远端
//蓝牙设备数据发生变化时得到通知,建议在设置可被通知的characteristic时,将如下描述符设为可被通知。
//这是我在做蓝牙血压计获得的经验,貌似一些蓝牙设备厂商在定制蓝牙服务时,遵循该规范
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}