从第二个活动绑定到服务

时间:2018-09-23 07:38:06

标签: java android android-intent service binding

我的理解是,可以一次绑定多个活动中的同一服务。但是,尝试从MainActivity.java之外的第二个活动(使用startService启动服务)绑定到服务时,经常遇到问题。

在这里,我尝试从新活动(SensorDataDisplay.java)绑定到服务(BluetoothLeService.java)。该服务最初是在我的MainActivity.java活动中启动的,然后绑定在MainActivity中。

我已经编写了一些代码来检查绑定是否成功,并不断返回false。

与第二个活动绑定时,有什么需要做不同的事情吗?

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 :(得分:0)

由于您在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");
}

我建议您学习使用Android中的Log类进行调试,这在Android开发人员中会更好(也是一种标准)。