我正在開發一個應用程序,可以連接和斷開連接到BLE設備。 我可以連接到設備並從該設備斷開連接。 但是,當我嘗試重新連接到相同的設備,它不再工作。無法重新連接到藍牙設備後BluetoothGatt.disconnect()android
我使用兩個類,MainActivity和從服務擴展的第二個類。
我的第二個活動:
public class RFduinoService extends Service {
private final static String TAG = RFduinoService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private BluetoothGattService mBluetoothGattService;
public final static String ACTION_CONNECTED =
"com.rfduino.ACTION_CONNECTED";
public final static String ACTION_DISCONNECTED =
"com.rfduino.ACTION_DISCONNECTED";
public final static String ACTION_DATA_AVAILABLE =
"com.rfduino.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.rfduino.EXTRA_DATA";
public final static UUID UUID_SERVICE = BluetoothHelper.sixteenBitUuid(0x2220);
public final static UUID UUID_RECEIVE = BluetoothHelper.sixteenBitUuid(0x2221);
public final static UUID UUID_SEND = BluetoothHelper.sixteenBitUuid(0x2222);
public final static UUID UUID_DISCONNECT = BluetoothHelper.sixteenBitUuid(0x2223);
public final static UUID UUID_CLIENT_CONFIGURATION = BluetoothHelper.sixteenBitUuid(0x2902);
// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to RFduino.");
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from RFduino.");
broadcastUpdate(ACTION_DISCONNECTED);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
mBluetoothGattService = gatt.getService(UUID_SERVICE);
if (mBluetoothGattService == null) {
Log.e(TAG, "RFduino GATT service not found!");
return;
}
BluetoothGattCharacteristic receiveCharacteristic =
mBluetoothGattService.getCharacteristic(UUID_RECEIVE);
if (receiveCharacteristic != null) {
BluetoothGattDescriptor receiveConfigDescriptor =
receiveCharacteristic.getDescriptor(UUID_CLIENT_CONFIGURATION);
if (receiveConfigDescriptor != null) {
gatt.setCharacteristicNotification(receiveCharacteristic, true);
receiveConfigDescriptor.setValue(
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(receiveConfigDescriptor);
} else {
Log.e(TAG, "RFduino receive config descriptor not found!");
}
} else {
Log.e(TAG, "RFduino receive characteristic not found!");
}
broadcastUpdate(ACTION_CONNECTED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent, Manifest.permission.BLUETOOTH);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
if (UUID_RECEIVE.equals(characteristic.getUuid())) {
final Intent intent = new Intent(action);
intent.putExtra(EXTRA_DATA, characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0));
sendBroadcast(intent, Manifest.permission.BLUETOOTH);
}
}
public class LocalBinder extends Binder {
RFduinoService getService() {
return RFduinoService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
return mBluetoothGatt.connect();
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}
public void read() {
if (mBluetoothGatt == null || mBluetoothGattService == null) {
Log.w(TAG, "BluetoothGatt not initialized");
return;
}
BluetoothGattCharacteristic characteristic =
mBluetoothGattService.getCharacteristic(UUID_RECEIVE);
mBluetoothGatt.readCharacteristic(characteristic);
}
public boolean send(byte[] data) {
if (mBluetoothGatt == null || mBluetoothGattService == null) {
Log.w(TAG, "BluetoothGatt not initialized");
return false;
}
BluetoothGattCharacteristic characteristic =
mBluetoothGattService.getCharacteristic(UUID_SEND);
if (characteristic == null) {
Log.w(TAG, "Send characteristic not found");
return false;
}
characteristic.setValue(data);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
return mBluetoothGatt.writeCharacteristic(characteristic);
}
public static IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_CONNECTED);
filter.addAction(ACTION_DISCONNECTED);
filter.addAction(ACTION_DATA_AVAILABLE);
return filter;
}
}
我的MainActivity:
public class MainActivity extends Activity implements BluetoothAdapter.LeScanCallback {
@Override
protected void onStart() {
Log.d("ONSTART", "ONSTART");
super.onStart();
registerReceiver(scanModeReceiver, new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
registerReceiver(bluetoothStateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
registerReceiver(rfduinoReceiver, RFduinoService.getIntentFilter());
}
@Override
public void onLeScan(BluetoothDevice device, final int rssi, final byte[] scanRecord) {
scanLeDevice(false);
bluetoothDevice = device;
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("ONLESCAN", "ONLESCAN");
/*obtain the name of the device based on the scanRecord*/
BleAdvertisedData badata = BleUtil.parseAdertisedData(scanRecord);
ListView list = discoveredDevicesDialog.getListView();
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
indexListClicked = position;
Intent rfduinoIntent = new Intent(MainActivity.this, RFduinoService.class);
bindService(rfduinoIntent, rfduinoServiceConnection, BIND_AUTO_CREATE);
}
});
createNotification();
}
});
}
@Override
public void onBackPressed() {
Log.d("CDA", "onBackPressed Called");
if(!DisplayDiapers.getShowButton()) {
unregisterReceiver(scanModeReceiver);
unregisterReceiver(bluetoothStateReceiver);
unregisterReceiver(rfduinoReceiver);
finish();
}else {
moveTaskToBack(true);
}
}
private void scanLeDevice(boolean scan){
if(bluetoothAdapter.isEnabled()) {
if (scan) {
loadLoadingScanDialog(true);
bluetoothAdapter.startLeScan(
new UUID[]{RFduinoService.UUID_SERVICE},
MainActivity.this);
} else {
bluetoothAdapter.stopLeScan(this);
}
}
}
public static void disconnect(int position){
rfduinoService.disconnect();
}
private final BroadcastReceiver bluetoothStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("bluetoothStateReceiver", "bluetoothStateReceiver");
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
if (state == BluetoothAdapter.STATE_ON) {
Log.d("STATE_DISCONNECTED", "STATE_DISCONNECTED");
} else if (state == BluetoothAdapter.STATE_OFF) {
Log.d("STATE_BLUETOOTH_OFF", "STATE_BLUETOOTH_OFF");
}
}
};
private final BroadcastReceiver scanModeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("scanModeReceiver", "scanModeReceiver");
}
};
private final ServiceConnection rfduinoServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("rfduinoServiceConnec", "rfduinoServiceConnection_onServiceConnected");
rfduinoService = ((RFduinoService.LocalBinder) service).getService();
if (rfduinoService.initialize()) {
if (rfduinoService.connect(bluetoothDevice.getAddress())) {
Log.d("STATE_CONNECTING", "STATE_CONNECTING");
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("rfduinoServiceConnec", "rfduinoServiceConnection_onServiceDisconnected");
}
};
private final BroadcastReceiver rfduinoReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("rfduinoReceiver", "rfduinoReceiver");
final String action = intent.getAction();
if (RFduinoService.ACTION_CONNECTED.equals(action)) {
showToast("Connected to " + diapersNames.get(indexListClicked));
}
}
};
}
在這時候,我可以掃描設備,並找到我的設備,但第二次時我點擊了我要連接的設備,但我無法執行該操作。
流程如下:在onLeScan()
我點擊我想連接的設備,比代碼去onServiceConnected()
,並調用我的第二類的方法。當我想斷開disconnect(int)
將被調用,但代碼不會輸入onServiceDisconnected()
。第二次onLeScan()
不會做任何事情,我知道代碼輸入在onLeScan()
,但這是我有的最後一個打印,我不明白爲什麼會發生這種情況。爲什麼行爲與第一次不一樣?
感謝您的幫助。