在安卓上进行BLE开发时,就不必像理解BLE协议栈那样复杂了。因为安卓的BLE包为我们提供了十分丰富的API、各类常量、各类连接通信情况下的回调API等。
具体流程
一、声明权限
二、获取Adapter适配器
三、开启蓝牙
四、BLE扫描与停止
五、连接设备
六、枚举特征值及其属性
七、利用特征值通讯
八、关闭蓝牙
一、声明权限
在AndroidManifest.xml文件中声明应用需要的特性及权限。
<!-- 声明App使用条件为支持BLE -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<!-- 声明蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 安卓6.0开始需要此权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
二、获取Adapter适配器
final BluetoothManager mBluetoothManager =(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
三、开启蓝牙
if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(intent, BLE_ENABLE);
}
四、BLE扫描与停止
private boolean mScanning;//是否正在搜索
private Handler mHandler = new Handler();
// 预设15秒扫描时间
private static final int SCAN_PERIOD = 15000;private void scanLeDevice(final boolean enable) {if (enable) {// 控制BLE扫描时间mHandler.postDelayed(new Runnable() {@Overridepublic void run() {mBluetoothAdapter.stopLeScan(mLeScanCallback);}}, SCAN_PERIOD);mScanning = true;// 开始扫描mBluetoothAdapter.startLeScan(mLeScanCallback);} else {mScanning = false;// 停止扫描mBluetoothAdapter.stopLeScan(mLeScanCallback);}
}
在BLE扫描回调函数中保存设备对应的BlueToothDevice对象,rssi信号强度等。
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {@Overridepublic void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {// 保存device及相关信息,也可以通知UI线程显示信息}};
五、连接设备
使用扫描结果中保存的BluetoothDevice对象调用connectGatt进行通讯。
BluetoothGatt mBluetoothGatt;
// 参数一:context上下文
// 参数二:是否自动重连
// 参数三: 连接回调
mBluetoothGatt = mBluetoothDevice.connectGatt(context, false, mGattCallback);
连接回调函数实现如下,开发时在此处处理各类可能遇到的情况。
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {// 连接状态改变的回调@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {// 具体处理见后文第八项};// 发现服务回调@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {// 具体处理见后文第六项};@Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {// 由mBluetoothGatt.readRemoteRssi()调用得到,可不停刷新rssi信号强度Log.e(TAG, "信号强度RSSI:" + rssi);}// 写描述信息回调@Overridepublic void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptordescriptor, int status) {};// 写操作回调@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.e(TAG, "写入成功:" + characteristic.getValue());}};// 读操作回调@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {Log.e(TAG, "读取成功:" + characteristic.getValue());}}// 数据改变回调(接收BLE设备发送的数据)@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {};};
}
六、枚举特征值及其属性
@Override
// 发现服务回调,即调用了mBluetoothGatt.discoverServices()执行的回调
public void onServicesDiscovered(BluetoothGatt gatt, int status) {if (status == BluetoothGatt.GATT_SUCCESS) {// 获取ServiceList<BluetoothGattService> mGattServices = gatt.getServices();// 获取Service的Characteristicsfor (BluetoothGattService gattService : mGattServices) {List<BluetoothGattCharacteristic> mGattCharacteristics = gattService.getCharacteristics();for (BluetoothGattCharacteristic gattCharacteristic :mGattCharacteristics) {int charaProp = gattCharacteristic.getProperties();// 所有Characteristics按属性分类if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" + gattCharacteristic.getUuid());Log.e(TAG, "gattCharacteristic的属性为:可读");readUuids.add(gattCharacteristic.getUuid());}if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" + gattCharacteristic.getUuid());Log.e(TAG, "gattCharacteristic的属性为:可写");writeUuids.add(gattCharacteristic.getUuid());}if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {Log.e(TAG, "gattCharacteristic的UUID为:" + gattCharacteristic.getUuid() + gattCharacteristic);Log.e(TAG, "gattCharacteristic的属性为:具备通知属性");notifyUuids.add(gattCharacteristic.getUuid());}}}} else {Log.e(TAG, "onServicesDiscovered 失败,status:" + status);}
}
七、利用特征值通讯
1、写数据
public void writeChara(byte) {BluetoothGattCharacteristic mGattCharacteristic = mBluetoothGatt.getCharacteristic(writeUuid);mGattCharacteristic.setValue(sendValue);mBluetoothGatt.writeCharacteristic(mGattCharacteristic);
}
2、读数据
public void readChara() {// 读取数据BluetoothGattCharacteristic mGattCharacteristic = mBluetoothGatt.getCharacteristic(readUuid);mBluetoothGatt.readCharacteristic(mGattCharacteristic);
}
3、监听通知属性的数据
mBluetoothGatt.setCharacteristicNotification(mGattCharacteristic, enabled);
BluetoothGattDescriptor mGattDescriptor = mGattCharacteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
mGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(mGattDescriptor);
八、关闭蓝牙
合理的关闭步骤为,先调用BluetoothGatt#disconnect进行断开连接,此时会在BluetoothGattCallback#onConnectionStateChange接收到断开成功的回调,然后在回调中调用BluetoothGatt#close释放相关资源。
// 首先执行该disconnect操作,然后等待回调通知
mBluetoothGatt.disconnect();
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {if (newState != BluetoothGatt.GATT_SUCCESS) {// 连接失败直接在此处理即可,因此时调用disconnect无法进入下面条件Log.e(TAG, "连接失败, status:" + status);gatt.close();return;}if (newState == BluetoothGatt.STATE_DISCONNECTED) {// 连接断开Log.e(TAG, "连接断开");mBluetoothGatt.close();} else if (newState == BluetoothProfile.STATE_CONNECTED) {// 连接成功后启动服务发现Log.e(TAG, "连接成功");mBluetoothGatt.discoverServices();}
};