我开发了一个 android 应用程序来扫描 ble 设备,并在应用程序处于用户交互时完成了 gatt 特性的读取和写入。我想保持与特定 ble 设备的连接,并希望在应用程序处于前台和后台时读写 gatt 特性。这是我的 BluetoothLeService 类。
public class BluetoothLeService extends Service
{
public static final String ACTION_DATA_AVAILABLE = "com.example.tracker.service.ACTION_DATA_AVAILABLE";
public static final String ACTION_GATT_CONNECTED = "com.example.tracker.service.ACTION_GATT_CONNECTED";
public static final String ACTION_GATT_DISCONNECTED = "com.example.tracker.service.ACTION_GATT_DISCONNECTED";
public static final String ACTION_GATT_RSSI_UPDATE = "com.example.tracker.service.ACTION_GATT_RSSI_UPDATE";
public static final String ACTION_GATT_SERVICES_DISCOVERED = "com.example.tracker.service.ACTION_GATT_SERVICES_DISCOVERED";
public static final String ACTION_GATT_WRITE_FAILED = "com.example.tracker.service.ACTION_GATT_WRITE_FAILED";
protected static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public static final String CHARACTERISTIC_UUID = "com.example.tracker.service.CHARACTERISTIC_UUID";
public static final String EXTRA_DATA = "com.example.tracker.service.EXTRA_DATA";
public static final String SIGNAL = "SIGNAL";
private static final String TAG = BluetoothLeService.class.getSimpleName();
private final IBinder mBinder = new LocalBinder();
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private BluetoothManager mBluetoothManager;
private BluetoothGattCharacteristic mFocusedCharacteristic;
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == 2) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_CONNECTED);
Log.i(BluetoothLeService.TAG, "Connected to GATT server.");
Log.i("MyActivity", "Connected to GATT server.");
Log.i("MyActivity", "Attempting to start service discovery:" + BluetoothLeService.this.mBluetoothGatt.discoverServices());
} else if (newState == 0) {
String intentAction = BluetoothLeService.ACTION_GATT_DISCONNECTED;
Log.i("MyActivity", "Disconnected from GATT server.");
BluetoothLeService.this.broadcastUpdate(intentAction);
}
}
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w("MyActivity", "onServicesDiscovered received: " + status);
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
Log.i("MyActivity", "Characteristic flags " + characteristic.getProperties());
BluetoothLeService.this.mFocusedCharacteristic = characteristic;
}
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
if ((characteristic.getProperties() & 2) > 0) {
BluetoothLeService.this.readCharacteristic();
Log.i("MyActivity", "Characteristic permits read");
}
Log.i("MyActivity", "Characteristic was written");
return;
}
Log.i("MyActivity", "Failed to write characteristic");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
}
public void onReadRemoteRssi(BluetoothGatt gatt, int Rssi, int status) {
if (status == 0) {
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_GATT_RSSI_UPDATE, Rssi);
}
}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i("MyActivity", "Characteristic has changed");
BluetoothLeService.this.broadcastUpdate(BluetoothLeService.ACTION_DATA_AVAILABLE, characteristic);
}
};
public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
private void broadcastUpdate(String action) {
sendBroadcast(new Intent(action));
}
private void broadcastUpdate(String action, int Rssi) {
Intent intent = new Intent(action);
intent.putExtra(EXTRA_DATA, Rssi);
sendBroadcast(intent);
}
private void broadcastUpdate(String action, BluetoothGattCharacteristic characteristic) {
Intent intent = new Intent(action);
byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
StringBuilder stringBuilder = new StringBuilder(data.length);
int length = data.length;
for (int i = 0; i < length; i++) {
stringBuilder.append(String.format("%02X ", new Object[]{Byte.valueOf(data[i])}));
}
intent.putExtra(EXTRA_DATA, new StringBuilder(String.valueOf(new String(data))).append(" [ ").append(stringBuilder.toString()).toString());
intent.putExtra(CHARACTERISTIC_UUID, characteristic.getUuid().toString());
}
sendBroadcast(intent);
}
public IBinder onBind(Intent intent) {
return this.mBinder;
}
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
public boolean initialize() {
if (this.mBluetoothManager == null) {
this.mBluetoothManager = (BluetoothManager) getSystemService("bluetooth");
if (this.mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
this.mBluetoothAdapter = this.mBluetoothManager.getAdapter();
if (this.mBluetoothAdapter != null) {
return true;
}
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
public boolean connect(String address) {
if (this.mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
} else if (this.mBluetoothDeviceAddress == null || !address.equals(this.mBluetoothDeviceAddress) || this.mBluetoothGatt == null) {
BluetoothDevice device = this.mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "LocalDevice not found. Unable to connect.");
return false;
}
this.mBluetoothGatt = device.connectGatt(this, false, this.mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
this.mBluetoothDeviceAddress = address;
return true;
} else {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (this.mBluetoothGatt.connect()) {
return true;
}
return false;
}
}
public void disconnect() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.disconnect();
}
}
public void readRemoteRssi() {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readRemoteRssi();
}
}
public BluetoothGattCharacteristic CurrentCharacteristic() {
return this.mFocusedCharacteristic;
}
public String getCurrentCharacteristicUuid() {
return this.mFocusedCharacteristic.getUuid().toString();
}
public void writeCharacteristic(byte[] c) {
mFocusedCharacteristic.setValue(c);
if (mBluetoothGatt!=null && mFocusedCharacteristic!=null){
mBluetoothGatt.writeCharacteristic(mFocusedCharacteristic);
}
}
public void readCharacteristic() {
Log.i("MyActivity", "Read Characteristic");
this.mBluetoothGatt.readCharacteristic(this.mFocusedCharacteristic);
}
public void notifyCharacteristic() {
Log.i("MyActivity", "Notify Characteristic");
setCharacteristicNotification(this.mFocusedCharacteristic, true);
}
public void setCurrentCharacteristic(BluetoothGattCharacteristic characteristic) {
this.mFocusedCharacteristic = characteristic;
}
public void close() {
if (this.mBluetoothGatt != null) {
this.mBluetoothGatt.close();
this.mBluetoothGatt = null;
}
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (this.mBluetoothAdapter == null || this.mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
} else {
this.mBluetoothGatt.readCharacteristic(characteristic);
}
}
public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enable) {
Log.i("MyActivity", "setCharacteristicNotification");
this.mBluetoothGatt.setCharacteristicNotification(characteristic, enable);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : new byte[2]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
SystemClock.sleep(200);
return this.mBluetoothGatt.writeDescriptor(descriptor);
}
public List<BluetoothGattService> getSupportedGattServices() {
if (this.mBluetoothGatt == null) {
return null;
}
return this.mBluetoothGatt.getServices();
}
}