安卓读取蓝牙BLE设备信息
简介
目前,许多项目都会涉及与BLE设备进行交互的功能,接下来说一下读取BLE设备信息的具体实现流程。安卓BLE相关接口介绍详见官网链接:
https://developer.android.google.cn/guide/topics/connectivity/bluetooth-le
轮询方式代码实现
这里实现的示例代码,每60秒通过bluetoothManager查询当前是否有已连接的BLE设备,如果有,则与该设备建立GATT连接,读取设备信息,读完之后断开GATT连接。
package com.komect.gatttest2;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import java.util.List;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private String TAG = "BLE";
private BluetoothGatt mBluetoothGatt;
private BluetoothGattCharacteristic mGattCharacteristic;
private BluetoothGattService mGattService;
private boolean alreadyConnected = false;
//service的UUID
public static final UUID DEVICE_INFO_SERVICE_UUID = UUID.fromString("0000180A-0000-1000-8000-00805f9b34fb");
//characteristic的UUID
public static final UUID MANUFACTURER_Name_UUID = UUID.fromString("00002A29-0000-1000-8000-00805f9b34fb");
public static final UUID SN_UUID = UUID.fromString("00002A25-0000-1000-8000-00805f9b34fb");
public static final UUID MODEL_NAME_UUID = UUID.fromString("00002A24-0000-1000-8000-00805f9b34fb");
public static final UUID SOFTWARE_VERSION_UUID = UUID.fromString("00002A27-0000-1000-8000-00805f9b34fb");
public static final UUID FIRMWARE_VERSION_UUID = UUID.fromString("00002A26-0000-1000-8000-00805f9b34fb");
public static final UUID MAC_UUID = UUID.fromString("00002A23-0000-1000-8000-00805f9b34fb");
private final static UUID[] characteristicUUIDList = {
MANUFACTURER_Name_UUID,
SN_UUID,
MODEL_NAME_UUID,
SOFTWARE_VERSION_UUID,
FIRMWARE_VERSION_UUID
};
private int index = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
while(true) {
if(alreadyConnected == false) {
findGattDevice();
}
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//GATT连接回调接口
BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
//GATT连接成功
Log.i(TAG, "GATT connect success");
alreadyConnected = true;
if(gatt != null) {
gatt.discoverServices();
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//GATT连接断开
Log.i(TAG, "GATT disconnect");
closeGatt();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
Log.i(TAG, "onServicesDiscovered status:" + status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//根据uuid获取指定的service
mGattService = gatt.getService(DEVICE_INFO_SERVICE_UUID);
if (mGattService == null) {
Log.i(TAG, "service is null, disconnect GATT");
closeGatt();
return;
} else {
Log.i(TAG, "find service!");
}
//根据uuid获取指定的characteristic
mGattCharacteristic = mGattService.getCharacteristic(characteristicUUIDList[0]);
if (mGattCharacteristic == null) {
Log.i(TAG, "characteristic is null");
closeGatt();
return;
} else {
//读取蓝牙特征值
Log.i(TAG, "start read characteristic");
mBluetoothGatt.readCharacteristic(mGattCharacteristic);
}
} else {
Log.i(TAG, "onServicesDiscovered status false");
closeGatt();
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
String value = new String(characteristic.getValue()).trim().replace(" ", "");
Log.i(TAG, "read data:" + value);
if(mGattService == null) {
Log.i(TAG, "service is null, disconnect GATT");
closeGatt();
return;
}
index ++;
if(index < characteristicUUIDList.length) {
mGattCharacteristic = mGattService.getCharacteristic(characteristicUUIDList[index]);
} else {
closeGatt();
return;
}
if (mGattCharacteristic == null) {
Log.i(TAG, "characteristic is null");
closeGatt();
return;
} else {
//读取蓝牙特征值
Log.i(TAG, "start read characteristic");
mBluetoothGatt.readCharacteristic(mGattCharacteristic);
}
} else {
Log.i(TAG, "onCharacteristicRead status false");
closeGatt();
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.i(TAG, "onCharacteristicWrite:" + characteristic.getUuid().toString());
}
};
//查找是否有已连接的BLE设备
private void findGattDevice() {
Log.i(TAG, "findGattDevice start");
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> connectedList = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
if(connectedList == null) {
Log.i(TAG, "connectedList is null");
return;
}
int i = 0;
Log.i(TAG, "connectedList size:" + connectedList.size());
while(connectedList.size() > i) {
BluetoothDevice bluetoothDevice = connectedList.get(i);
if(bluetoothDevice != null) {
Log.i(TAG, "find device:" + bluetoothDevice.getName());
try {
//建立GATT连接
mBluetoothGatt = bluetoothDevice.connectGatt(this, false, mGattCallback);
} catch (Exception e) {
Log.i(TAG, "findGattDevice e:" + e.getMessage());
}
}
i++;
}
}
//关闭GATT连接
private void closeGatt() {
Log.i(TAG, "closeGatt start");
alreadyConnected = false;
mGattService = null;
mGattCharacteristic = null;
index = 0;
if(mBluetoothGatt != null) {
Log.i(TAG, "closeGatt do close");
try {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
} catch (Exception e) {
Log.i(TAG, "closeGatt e:" + e.getMessage());
}
mBluetoothGatt = null;
}
}
}
在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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
监听广播方式代码实现
todo