2

Ich entwickle eine App, die mit einem Bluetooth-Modul (RN4020 von Microchip) kommuniziert. Diese App verwendet einen Dienst, der die Kommunikation mit dem Modul (Verbindung/Lesen/Schreiben) übernimmt. Wenn ich eine Aktivität verwende, gibt es kein Problem. Wenn ich 2 Aktivität verwende, gibt es ein Problem. Das Telefon trennt die Verbindung zum Modul und stürzt ab, wenn ich Daten an das Modul sende. Ich denke das Problem ist der Dienst, es bindet sich nicht in der zweiten Aktivität nach mir. Wie kann ich es lösen?Dienst für mehrere Aktivitäten

Dies ist der Service:

public class BluetoothLeService extends Service { 

private final static String TAG = BluetoothLeService.class.getSimpleName();   //Get name of service to tag debug and warning messages 
private BluetoothManager mBluetoothManager;           //BluetoothManager used to get the BluetoothAdapter 
private BluetoothAdapter mBluetoothAdapter;           //The BluetoothAdapter controls the BLE radio in the phone/tablet 
private BluetoothGatt mBluetoothGatt;            //BluetoothGatt controls the Bluetooth communication link 
private String mBluetoothDeviceAddress;            //Address of the connected BLE device 

public final static String ACTION_GATT_CONNECTED = "com.example.app.ACTION_GATT_CONNECTED"; //Strings representing actions to broadcast to activities 
public final static String ACTION_GATT_DISCONNECTED = "com.example.app.ACTION_GATT_DISCONNECTED"; 
public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.app.ACTION_GATT_SERVICES_DISCOVERED"; 
public final static String ACTION_DATA_AVAILABLE = "com.example.app.ACTION_DATA_AVAILABLE"; 
public final static String ACTION_DATA_WRITTEN = "com.example.app.ACTION_DATA_WRITTEN"; 
public final static String EXTRA_DATA = "com.example.app.EXTRA_DATA"; 

public final static UUID UUID_MLDP_DATA_PRIVATE_CHARACTERISTIC = UUID.fromString(WorkActivity.MLDP_DATA_PRIVATE_CHAR); 
public final static UUID UUID_CHARACTERISTIC_NOTIFICATION_CONFIG = UUID.fromString(WorkActivity.CHARACTERISTIC_NOTIFICATION_CONFIG); 

private final IBinder mBinder = new LocalBinder();         //Binder for Activity that binds to this Service 

// ---------------------------------------------------------------------------------------------------------------- 
// An activity has bound to this service 
@Override 
public IBinder onBind(Intent intent) { 
    return mBinder;                 //Return LocalBinder when an Activity binds to this Service 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// An activity has unbound from this service 
@Override 
public boolean onUnbind(Intent intent) { 
    /*if (mBluetoothGatt != null) {             //Check for existing BluetoothGatt connection 
     mBluetoothGatt.close();              //Close BluetoothGatt coonection for proper cleanup 
     mBluetoothGatt = null;              //No longer have a BluetoothGatt connection 
    }*/ 
    return super.onUnbind(intent); 

} 

// ---------------------------------------------------------------------------------------------------------------- 
// A Binder to return to an activity to let it bind to this service 
public class LocalBinder extends Binder { 
    BluetoothLeService getService() { 
     return BluetoothLeService.this;            //Return this instance of BluetoothLeService so clients can call its public methods 
    } 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Implements callback methods for GATT events that the app cares about. For example: connection change and services discovered. 
// When onConnectionStateChange() is called with newState = STATE_CONNECTED then it calls mBluetoothGatt.discoverServices() 
// resulting in another callback to onServicesDiscovered() 
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { 
    @Override 
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { //Change in connection state 
     if (newState == BluetoothProfile.STATE_CONNECTED) {       //See if we are connected 
      broadcastUpdate(ACTION_GATT_CONNECTED);         //Go broadcast an intent to say we are connected 
      Log.i(TAG, "Connected to GATT server, starting service discovery"); 
      mBluetoothGatt.discoverServices();          //Discover services on connected BLE device 
     } 
     else if (newState == BluetoothProfile.STATE_DISCONNECTED) {     //See if we are not connected 
      broadcastUpdate(ACTION_GATT_DISCONNECTED);        //Go broadcast an intent to say we are disconnected 
      Log.i(TAG, "Disconnected from GATT server."); 
     } 
    } 

    @Override 
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {    //BLE service discovery complete 
     if (status == BluetoothGatt.GATT_SUCCESS) {         //See if the service discovery was successful 
      broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);      //Go broadcast an intent to say we have discovered services 
     } 
     else {                  //Service discovery failed so log a warning 
      Log.w(TAG, "onServicesDiscovered received: " + status); 
     } 
    } 

    //For information only. This application uses Indication to receive updated characteristic data, not Read 
    @Override 
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { //A request to Read has completed 
     if (status == BluetoothGatt.GATT_SUCCESS) {         //See if the read was successful 
      broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);     //Go broadcast an intent with the characteristic data 
     } 
    } 

    //For information only. This application sends small packets infrequently and does not need to know what the previous write completed 
    @Override 
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { //A request to Write has completed 
     if (status == BluetoothGatt.GATT_SUCCESS) {         //See if the write was successful 
      broadcastUpdate(ACTION_DATA_WRITTEN, characteristic);     //Go broadcast an intent to say we have have written data 
     } 
    } 

    @Override 
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { //Indication or notification was received 
     broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);      //Go broadcast an intent with the characteristic data 
    } 
}; 

// ---------------------------------------------------------------------------------------------------------------- 
// Broadcast an intent with a string representing an action 
private void broadcastUpdate(final String action) { 
    final Intent intent = new Intent(action);          //Create new intent to broadcast the action 
    sendBroadcast(intent);               //Broadcast the intent 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Broadcast an intent with a string representing an action an extra string with the data 
// Modify this code for data that is not in a string format 
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { 
    final Intent intent = new Intent(action);          //Create new intent to broadcast the action 
    if(action.equals(ACTION_DATA_AVAILABLE)) {          //See if we need to send data 
     if (UUID_MLDP_DATA_PRIVATE_CHARACTERISTIC.equals(characteristic.getUuid())) { //See if this is the correct characteristic 
      String dataValue = characteristic.getStringValue(0);     //Get the data (in this case it is a string) 
      intent.putExtra(EXTRA_DATA, dataValue);         //Add the data string to the intent 
     } 
    } 
    else {                   //Did not get an action string we expect 
     Log.d(TAG, "Action: " + action); 
    } 
    sendBroadcast(intent);               //Broadcast the intent 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Initialize by getting the BluetoothManager and BluetoothAdapter 
public boolean initialize() { 
    if (mBluetoothManager == null) {            //See if we do not already have the BluetoothManager 
     mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); //Get the BluetoothManager 
     if (mBluetoothManager == null) {           //See if we failed 
      Log.e(TAG, "Unable to initialize BluetoothManager."); 
      return false;               //Report the error 
     } 
    } 

    mBluetoothAdapter = mBluetoothManager.getAdapter();        //Ask the BluetoothManager to get the BluetoothAdapter 
    if (mBluetoothAdapter == null) {            //See if we failed 
     Log.e(TAG, "Unable to obtain a BluetoothAdapter."); 
     return false;                //Report the error 
    } 

    return true;                 //Success, we have a BluetoothAdapter to control the radio 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Open a BluetoothGatt connection to a BLE device given its address 
public boolean connect(final String address) { 
    if (mBluetoothAdapter == null || address == null) {        //Check that we have a Bluetooth adappter and device address 
     Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");  //Log a warning that something went wrong 
     return false;                //Failed to connect 
    } 

    // Previously connected device. Try to reconnect. 
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { //See if there was previous connection to the device 
     Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); 
     if (mBluetoothGatt.connect()) {            //See if we can connect with the existing BluetoothGatt to connect 
      return true;               //Success 
     } 
     else { 
      return false;               //Were not able to connect 
     } 
    } 

    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);  //No previous device so get the Bluetooth device by referencing its address 
    if (device == null) {               //Check whether a device was returned 
     Log.w(TAG, "Device not found. Unable to connect.");      //Warn that something went wrong 
     return false;                //Failed to find the device 
    } 

    mBluetoothGatt = device.connectGatt(this, false, mGattCallback);    //Directly connect to the device so autoConnect is false 
    Log.d(TAG, "Trying to create a new connection."); 
    mBluetoothDeviceAddress = address;            //Record the address in case we bneed to reconnect with the existing BluetoothGatt 
    return true; 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Retrieve and return a list of supported GATT services on the connected device 
public List<BluetoothGattService> getSupportedGattServices() { 
    if (mBluetoothGatt == null) {             //Check that we have a valid GATT connection 
     return null; 
    } 
    return mBluetoothGatt.getServices();           //Get the list of services 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Disconnects an existing connection or cancel a pending connection 
// BluetoothGattCallback.onConnectionStateChange() will get the result 
public void disconnect() { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {      //Check that we have a GATT connection to disconnect 
     Log.w(TAG, "BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.disconnect();             //Disconnect GATT connection 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Request a read of a given BluetoothGattCharacteristic. The Read result is reported asynchronously through the 
// BluetoothGattCallback onCharacteristicRead callback method. 
// For information only. This application uses Indication to receive updated characteristic data, not Read 
public void readCharacteristic(BluetoothGattCharacteristic characteristic) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {      //Check that we have access to a Bluetooth radio 
     Log.w(TAG, "BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.readCharacteristic(characteristic);        //Request the BluetoothGatt to Read the characteristic 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Write to a given characteristic. The completion of the write is reported asynchronously through the 
// BluetoothGattCallback onCharacteristicWrire callback method. 
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {      //Check that we have access to a Bluetooth radio 
     Log.w(TAG, "BluetoothAdapter not initialized"); 
     return; 
    } 
    int test = characteristic.getProperties();          //Get the properties of the characteristic 
    if ((test & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 && (test & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) { //Check that the property is writable 
     return; 
    } 

    if (mBluetoothGatt.writeCharacteristic(characteristic)) {      //Request the BluetoothGatt to do the Write 
     Log.d(TAG, "writeCharacteristic successful");        //The request was accepted, this does not mean the write completed 
    } 
    else { 
     Log.d(TAG, "writeCharacteristic failed");         //Write request was not accepted by the BluetoothGatt 
    } 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Enable notification on a characteristic 
// For information only. This application uses Indication, not Notification 
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {      //Check that we have a GATT connection 
     Log.w(TAG, "BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);   //Enable notification and indication for the characteristic 
//  if (UUID_MLDP_DATA_PRIVATE_CHARACTERISTIC.equals(characteristic.getUuid())) { 
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID_CHARACTERISTIC_NOTIFICATION_CONFIG); //Get the descripter that enables notification on the server 
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);   //Set the value of the descriptor to enable notification 
    mBluetoothGatt.writeDescriptor(descriptor);          //Write the descriptor 
//  } 
} 

// ---------------------------------------------------------------------------------------------------------------- 
// Enable indication on a characteristic 
public void setCharacteristicIndication(BluetoothGattCharacteristic characteristic, boolean enabled) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {      //Check that we have a GATT connection 
     Log.w(TAG, "BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);   //Enable notification and indication for the characteristic 

    // This is specific to our custom profile 
//  if (UUID_MLDP_DATA_PRIVATE_CHARACTERISTIC.equals(characteristic.getUuid())) { 
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID_CHARACTERISTIC_NOTIFICATION_CONFIG); //Get the descripter that enables indication on the server 
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);   //Set the value of the descriptor to enable indication 
    mBluetoothGatt.writeDescriptor(descriptor);          //Write the descriptor 
//  } 
} 

} 

In der ersten Aktivität im onCreate() Ich nenne:

Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); 
startService(gattServiceIntent); 
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); 

Und in onPause():

super.onPause(); 
unregisterReceiver(mGattUpdateReceiver); 
unbindService(mServiceConnection); 
mBluetoothLeService = null; 

In der zweite Aktivität in der onCreate() Ich rufe an:

Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); 
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); 

Vielen Dank im Voraus und sorry für mein schlechtes Englisch

ich diese Frage mit Hilfe von @pskink

+0

den Dienst machen begann, bevor 'bindService' Aufruf, mehr [hier] (https://developer.android.com/guide/components/bound-services.html), Typ^F 'Binden an einen gestarteten Dienst' – pskink

+0

Ich empfahl Ihnen Dependency Injection, aber, wie uns @pslink erinnerte, Dienste sind Singleton standardmäßig, so dass es Ihr Problem nicht lösen würde. Sorry :( –

+0

@pskink Ich habe versucht, den Dienst vor dem Aufruf von bindService zu starten, aber ist das gleiche – Damien

Antwort

0

Es gibt zwei Arten von Dienstleistungen im Android bearbeiten: Gestartet und Bound . Du benutzt den zweiten, Gebunden. Dieser Typ hat mehr mit dem Lebenszyklus der Komponente zu tun, die ihn gestartet hat.

In Ihrem Szenario, würde ich vorschlagen Gestartet Android Service zu nutzen und rufen:

startService(intent); 

in Ihren onCreate() Rückruf Aktivitäten zu starten. Schließlich können Sie es auch in der Application-Java-Datei hinzufügen.

Mehr Infos unter: https://developer.android.com/guide/components/services.html

+0

die dritte Art ist: „gestartet und gebunden‘, mein Kommentar siehe oben – pskink

+1

Dank für Ihre Antwort danken, ich stimme Ihnen zu, dass besser zu bedienen ‚Gestartet‘ anstelle von ‚Bound‘ Aber. Wie muss ich meinen Service ändern, um ihn an "Started" anzupassen? – Damien

Verwandte Themen