4

現在、BLE デバイスに書き込みを行ってビープ音を鳴らすメソッドがあります。私のBluetoothコールバックは次のようになります:

public class ReadWriteCharacteristic extends BluetoothGattCallback {
    public ReadWriteCharacteristic(Context context, String macAddress, UUID service, UUID characteristic, Object tag, Activity activity) {
        mMacAddress = macAddress;
        mService = service;
        mCharacteristic = characteristic;
        mTag = tag;
        mContext = context;
        this.activity =activity;
        final BluetoothManager bluetoothManager =
                (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

    }

    final private static String TAG = "ReadCharacteristic";
    private Object mTag;
    private String mMacAddress;
    private UUID mService;
    private BluetoothManager mBluetoothManager = null;
    private BluetoothAdapter mBtAdapter = null;
    private BluetoothGatt mBluetoothGatt = null;
    private String mBluetoothDeviceAddress ="";
    private UUID mCharacteristic;
    BluetoothDevice device;
    private Activity activity;
    private BluetoothAdapter mBluetoothAdapter;
    private Context mContext;
    ReadWriteCharacteristic rc;

    private int retry = 5;


    public String getMacAddress() {
        return mMacAddress;
    }

    public UUID getService() {
        return mService;
    }

    public UUID getCharacteristic() {
        return mCharacteristic;
    }

    public byte[] getValue() { return mValue; }

    public void onError() {
        Log.w(TAG, "onError");
    }

    public void readCharacteristic(){
        if (retry == 0)
        {
            onError();
            return;
        }
        retry--;


                device = mBluetoothAdapter.getRemoteDevice(getMacAddress());


                mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
                int connectionState = mBluetoothManager.getConnectionState(device,
                        BluetoothProfile.GATT);

                if (device != null) {

                    if (connectionState == BluetoothProfile.STATE_DISCONNECTED)
                    {

                        // Previously connected device. Try to reconnect.
                        if (mBluetoothDeviceAddress != null
                                && getMacAddress().equals(mBluetoothDeviceAddress)
                                && mBluetoothGatt != null) {
                            Log.w(TAG, "Re-use GATT connection");
                            if (mBluetoothGatt.connect()) {
                                Log.w(TAG, "Already connected, discovering services");
                                mBluetoothGatt.discoverServices();
                                //return ;
                            } else {
                                Log.w(TAG, "GATT re-connect failed.");
                                return;
                            }
                        }

                        if (device == null) {
                            Log.w(TAG, "Device not found.  Unable to connect.");
                            return;
                        }
                        Log.w(TAG, "Create a new GATT connection.");
                        rc= ReadWriteCharacteristic.this;
                        Log.w(TAG, "Starting Read [" + getService() + "|" + getCharacteristic() + "]");
                        mBluetoothGatt = device.connectGatt(mContext, false, rc);
                        refreshDeviceCache(mBluetoothGatt);
                        mBluetoothDeviceAddress = getMacAddress();
                    } else {
                        Log.w(TAG, "Attempt to connect in state: " + connectionState);
                        if(mBluetoothGatt!=null)
                            mBluetoothGatt.close();
                        readCharacteristic();
                    }

                }

    }

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);

        Log.w(TAG,"onConnectionStateChange [" + status + "|" + newState + "]");


        if ((newState == 2)&&(status ==0)) {
            gatt.discoverServices();
        }
        else if(status == 133 )
        {
            //gatt.disconnect();
            gatt.close();
            mBluetoothGatt = null;
            try
            {
                Thread.sleep(2000);
            }
            catch(Exception e)
            {

            }
            readCharacteristic();
        }
        else{

            if(mBluetoothGatt!=null)
                mBluetoothGatt.close();

           // gatt.close();

            Log.w(TAG, "[" + status + "]");
            //gatt.disconnect();

            try
            {
                Thread.sleep(2000);
            }
            catch(Exception e)
            {

            }
            mBluetoothGatt = null;
            readCharacteristic();
        }
    }



    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.w(TAG,"onServicesDiscovered [" + status + "]");
        BluetoothGattService bgs = gatt.getService(getService());
        if (bgs != null) {
            BluetoothGattCharacteristic bgc = bgs.getCharacteristic(getCharacteristic());
            gatt.readCharacteristic(bgc);
        }
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic,
                                      int status) {
        Log.w(TAG,"onCharacteristicWrite [" + status + "]");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.w(TAG,"onCharacteristicWrite [" + getDataHex(characteristic.getValue()) + "]");
           // gatt.disconnect();
            if(mBluetoothGatt!=null)
                mBluetoothGatt.close();
          //  gatt.close();
          //  mBluetoothGatt=null;
        }
        else if(status ==133)
        {
            gatt.close();
            try
            {
                Thread.sleep(2000);
            }
            catch(Exception e)
            {

            }

            readCharacteristic();
        }

        else{
            //gatt.disconnect();
            gatt.close();

        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic,
                                     int status) {
        Log.w(TAG,"onCharacteristicRead [" + status + "]");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            mValue = characteristic.getValue();
            // Perform write operations
            gatt.writeCharacteristic(bgc);


        }

        else if(status ==133)
        {
            gatt.close();
            try
            {
                Thread.sleep(2000);
            }
            catch(Exception e)
            {

            }

            readCharacteristic();
        }

        else {
          //  gatt.disconnect();
            gatt.close();
        }
    }

}

このコードは、Kitkat 以前を実行しているデバイスで完全に機能します。ただし、Lollipop を実行しているデバイスでは、このコードは最初のインスタンスで問題なく動作します。しかし、次のインスタンスから、接続を切断するか閉じて再試行するかに関係なく、機能しません。onConnectionStateChange メソッドでステータス コード 257 が表示され続けます。私の知る限り、Bluetooth GATT メソッドは、kitkat デバイスと Lollipop デバイスの両方で同じです。

驚いたことに、古い BLE API、つまり startLeScan (たとえば - mBluetoothAdapter.startLeScan(mLeScanCallback);) を使用すると、このコードは Lollipop デバイスで正常に動作します。この問題は、新しい BLE API、つまり BluetoothLeScanner ( ) を使用した場合にのみ発生します scanner.startScan(filters, settings, new scancallback());。古い BLE API を使用している Lollipop デバイスではスキャン速度が非常に遅く、使用できません。この問題の解決方法がわかりません。同じ問題に直面して解決策を見つけた人はいますか? どんな助けでも大歓迎です。

4

1 に答える 1

4

ここで変更することがかなりあります。プライベート文字列の heartRate など、特性から読み取りたいデータのクラス変数を作成します。

1) readCharacteristic() メソッドは必要ありません。代わりに、デバイスが正しく接続されたら、onConnectionStateChange で mBluetoothGatt.discoverServices() を呼び出します。次に、onServicesDiscovered() メソッドで gatt.getServices() を呼び出します。次に、foreach ループを使用して、返されたサービスをループし、関心のあるサービスが見つかるまでサービスの UUID を比較します。次に、heartRate == null の場合は、service.getCharacteristic(HeartRateUUID) を呼び出して特性を読み取ります。onCharacteristicRead() で、UUID が心拍数特性と等しいかどうかを確認します。そうである場合、特徴の値を heartRate 変数に割り当てます。興味があれば、メソッドを入力するか、疑似コードを提供できます。

2) gatt.connect() の後に gatt.discoverServices() を呼び出しません。gatt.connect() は、デバイスからのアドバタイズ パケットを確認するとすぐに、現在のデバイスに再接続します。gatt.connect() を呼び出してから、onConnectedStateChange() メソッドで gatt.discoverServices() を呼び出します。

3) onConnectedStateChange メソッドでは、gatt 変数を使用しないでください。代わりに mBluetoothGatt を使用してください。mBluetoothGatt.disconnect() は、現在接続されているデバイスから切断します。mBluetoothGatt.close() は gatt インスタンスを終了します。mBluetoothGatt.Close() を呼び出した後に mBluetoothGatt.connect() を呼び出すことはできません。これは必要ないかもしれませんが、デバイスが接続されている場合は、mBluetoothGatt.disconnect() に続いて mBluetoothGatt.close() を呼び出します。

4) 特性測定値を連鎖させることもできます。onCharacteristicRead() では、heartRate の値を取得した後、すぐに character.getService().getCharacteristic(UUIDTemperature) を呼び出して、その特性を読み取ることができます。OnCharacteristicRead メソッドを再度呼び出します。

何か明確にしたいことがあれば教えてください。安っぽい Surface Pro 3 キーボードで入力しています。:)

于 2015-06-25T01:45:52.500 に答える