Привязка к сервису из второго вида деятельности - PullRequest
0 голосов
/ 23 сентября 2018

Насколько я понимаю, можно привязать к одному и тому же сервису сразу несколько действий.Тем не менее у меня возникла повторяющаяся проблема при попытке привязки к службе из другого действия, отличного от MainActivity.java, откуда я запустил службу с помощью startService.

Здесь я попытался привязаться к сервису (BluetoothLeService.java) из своей новой деятельности (SensorDataDisplay.java).Первоначально эта служба была запущена в моей деятельности MainActivity.java, а затем связана с MainActivity.

Я написал некоторый код для проверки успешности привязки, и он постоянно возвращает false.

IsЕсть ли что-то, что нужно сделать по-другому при связывании со вторым действием?

SensorDataDisplay.java (второе действие)

package com.august.customtisensortagclient;

import android.bluetooth.BluetoothGatt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class SensorDataDisplay extends AppCompatActivity {

    private static final String TAG = "SensorDataDisplay";
    TextView tester;
    BluetoothLeServiceForLeft mBluetoothLeServiceForLeft;
    boolean mBoundLeft = false;
    BluetoothLeServiceForRight mBluetoothLeServiceForRight;
    boolean mBoundRight;
    BluetoothGatt bluetoothGattLeft;
    BluetoothGatt bluetoothGattRight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor_data_display);

        Intent intent = getIntent(); //From MainActivity.java
        String value = intent.getStringExtra("key");//if it's a string you stored.


        // Checker code (to see if successful bind)
        tester = (TextView) findViewById(R.id.textView2);
        tester.append(value);

        if (mBoundLeft) {
            tester.append("TRUEEEEE");
        } else if (!mBoundLeft)
            tester.append("FALSEEEEE");

    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intentLeft = new Intent(this, BluetoothLeServiceForLeft.class);
        bindService(intentLeft, mServiceConnectionLeft, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(mServiceConnectionLeft);
        mBoundLeft = false;
    }


    private ServiceConnection mServiceConnectionLeft = new ServiceConnection() {
        // Called when the connection with the service is established
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // Because we have bound to an explicit
            // service that is running in our own process, we can
            // cast its IBinder to a concrete class and directly access it.
            BluetoothLeServiceForLeft.LocalBinder binder = (BluetoothLeServiceForLeft.LocalBinder) service;
            mBluetoothLeServiceForLeft = binder.getService();
            mBoundLeft = true;
        }

        // Called when the connection with the service disconnects unexpectedly
        @Override
        public void onServiceDisconnected(ComponentName className) {
            Log.e(TAG, "onServiceDisconnected");
            mBoundLeft = false;
        }
    };
}

BluetoothLeServiceForLeft.java (Пожалуйста, извините за длину. Я просто хотелвключите это в случае, если кто-то захочет проверить мое использование метода LocalBinder.

package com.august.customtisensortagclient;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import java.util.UUID;

public class BluetoothLeServiceForLeft extends Service {

    private final static String TAG = BluetoothLeServiceForLeft.class.getSimpleName();

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private String mBluetoothDeviceAddress;
    private BluetoothGatt mBluetoothGatt;
    private int mConnectionState = STATE_DISCONNECTED;

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;

    public final static String ACTION_GATT_CONNECTED_LEFT =
            "com.example.bluetooth.le.ACTION_GATT_CONNECTED_LEFT";
    public final static String ACTION_GATT_DISCONNECTED_LEFT =
            "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED_LEFT";
    public final static String ACTION_GATT_SERVICES_DISCOVERED_LEFT =
            "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED_LEFT";
    public final static String ACTION_DATA_AVAILABLE_LEFT =
            "com.example.bluetooth.le.ACTION_DATA_AVAILABLE_LEFT";
    public final static String EXTRA_DATA_LEFT =
            "com.example.bluetooth.le.EXTRA_DATA_LEFT";


    // Various callback methods defined by the BLE API.
    private final BluetoothGattCallback mGattCallback =
            new BluetoothGattCallback() {
                @Override
                public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                                    int newState) {
                    String intentAction;
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        intentAction = ACTION_GATT_CONNECTED_LEFT;
                        mConnectionState = STATE_CONNECTED;
                        broadcastUpdate(intentAction);
                        Log.i(TAG, "Connected to GATT server.");
                        Log.i(TAG, "Attempting to start service discovery:" +
                                mBluetoothGatt.discoverServices());

                    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                        intentAction = ACTION_GATT_DISCONNECTED_LEFT;
                        mConnectionState = STATE_DISCONNECTED;
                        close();
                        Log.i(TAG, "Disconnected from GATT server and closed.");
                        broadcastUpdate(intentAction);
                    }
                }

                @Override
                // New services discovered
                public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED_LEFT);
                        Log.w(TAG, "GATT services discovered.");
                    } else {
                        Log.w(TAG, "onServicesDiscovered received: " + status);
                    }
                }

                @Override
                // Result of a characteristic read operation
                public void onCharacteristicRead(BluetoothGatt gatt,
                                                 BluetoothGattCharacteristic characteristic,
                                                 int status) {
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        broadcastUpdate(ACTION_DATA_AVAILABLE_LEFT, characteristic);
                    }
                }
            };

    /**
     * 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;
    }

    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    private void broadcastUpdate(final String action,
                                 final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    public class LocalBinder extends Binder {
        BluetoothLeServiceForLeft getService() {
            return BluetoothLeServiceForLeft.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);
    }

    public void close() {
        if (mBluetoothGatt == null) {
            return;
        }
        mBluetoothGatt.close();
        mBluetoothGatt = null;
    }

    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.");
            if (mBluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // 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;
        mConnectionState = STATE_CONNECTING;
        return true;
    }

    public boolean disconnect(final String address) {
        if (mBluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        mBluetoothGatt.disconnect();
        Log.w(TAG, "Bluetooth device disconnected from GATT");
        return true;

    }

    public BluetoothGatt getBluetoothGatt() {
        return mBluetoothGatt;
    }

    private final IBinder mBinder = new LocalBinder();
}

1 Ответ

0 голосов
/ 23 сентября 2018

Поскольку вы тестируете mBoundLeft в методе onCreate() и связываете службу в onStart() и отменяете привязку в onStop() (также вы не сохраняете переходное состояние на случай, если ваше приложение будет убито), вы будетеникогда не проверяйте, истинно ли mBoundLeft (проверьте жизненный цикл активности).Вам следует проверить, была ли служба привязана внутри onServiceConnected(), например, log.d.Вы должны сделать что-то вроде этого:

public void onServiceConnected(ComponentName className, IBinder service) {
    // Because we have bound to an explicit
    // service that is running in our own process, we can
    // cast its IBinder to a concrete class and directly access it.
    BluetoothLeServiceForLeft.LocalBinder binder = 
             (BluetoothLeServiceForLeft.LocalBinder) service;
    mBluetoothLeServiceForLeft = binder.getService();
    mBoundLeft = true;
    Log.d("ServiceConnection", "Service is connected");
}

Я рекомендую вам научиться использовать класс Log в Android для отладки, это намного лучше (и стандарт) в Android dev.

...