2016-05-12 139 views
2

我正在開發一個應用程序,可以連接和斷開連接到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(),但這是我有的最後一個打印,我不明白爲什麼會發生這種情況。爲什麼行爲與第一次不一樣?

感謝您的幫助。

回答

0

你永遠不會打電話給public static void disconnect(int position)

我想你應該在rfduinoReceiver中調用它。類似這樣的:

private final BroadcastReceiver rfduinoReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.d("rfduinoReceiver", "rfduinoReceiver"); 
     if (RFduinoService.ACTION_CONNECTED.equals(action)) { 
       Log.d(TAG, "RFduinoServer connected"); 
      } else if (RFduinoService.ACTION_DISCONNECTED.equals(action)) { 
       Log.d(TAG, "RFduinoServer disconnected"); 
       rfduinoService.disconnect(); 
      } else if (RFduinoService.ACTION_DATA_AVAILABLE.equals(action)) { 
       Log.d(TAG, "RFduinoServer data available"); 
       // Process data from intent.getByteArrayExtra(RFduinoService.EXTRA_DATA) 
      } 
     } 
    } 
};