web-dev-qa-db-ja.com

Android BluetoothGatt-ステータス133-コールバックの登録

まず最初に 解決しよう:GATTコールバックは登録に失敗します を読み、その投稿で提案された手順を実行して、この問題を解決しましたが、成功しませんでした。まだ読んでいない場合は、メインスレッドから直接またはハンドラーを使用してすべてのBLE呼び出しを行うことをお勧めします。

私はこれらのタスクを実行するサービス(10秒ごとにアクティビティから呼び出される)を実行したいBLEアプリで作業しています:

1)Gets list of our products available to connect to (done, works)

2)For each available device:

          2a)connect to device
          2b)discover services
          2c)read 5 characteristics in this fashion:
             2c1)read characteristic
             2c2)onCharacteristicRead parse data
             2c3)when finished with data read next characteristic
             2c4)repeat until all are read (this is done using a state var and switch statement)
         2d)disconnect from device
         2e)connect to next device
         2f)repeat until all devices are read from
         2g)stopSelf()

だから問題...すべてが少しうまくいく。サービスの開始全体を実行できます{startService(...); mainActivity}で終了{stopSelf();サービス中}6回。

7回目に、コールバックの登録に失敗したBluetoothGattを取得します。なぜ6回正常に実行できて、7回目に失敗するのかはわかりません。

メインスレッドからすべてのBLE呼び出しを行っていることに注意してください。これは、複数の場所からのログ猫で確認されています。

コードの概要は次のとおりです。

SERVICE.Java

private Handler handler = new Handler();
private BluetoothGatt cGatt = null;
private int unitIndex = 0; // keep track of currently connected unit
private int state = 0; //used to keep track of which characteristic to read next

public int onStartCommand(Intent intent, int flags, int startId) 
{
    Log.i(TAG, "Service Started...");
    //get ArrayList of units

    if(units.size > 0)
        handler.post(connectNextRunnable); //calls connectNextDevice()
    else
        stopSelf();   
}

private Runnable discoverServices = new Runnable()
{
    public void run()
    {
        cGatt.discoverServices();
    }
}

private Runnable readNextValue = new Runnable()
{
    public void run()
    {
        BluetoothGattCharacteristic c = null;
        switch(state)
        {
            //set c to appropriate characteristic
        default: // all characteristics read
            unitIndex++;
            handler.post(connectNextRunnable)
            return
        }

        cGatt.readCharacteristic(c);
    }
}

private void connectNextDevice()
{
    if(unitIndex == 0)
        store System.nanoTime in variable

    if(unitIndex >= units.size) //finished will all units
        stopSelf();

    if(unitIndex < units.size)
        cGatt.disconnect //if null
        cGatt.connectGatt(this, false, gattCallback)
}

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() 
{
    public void onConnectionStateChange() 
    {
        handler.post(discoverServices);
    }

    public void onServicesDeiscovered() 
    {
        handler.post(readNextValue);
    }

    public void onCharacteristicRead() 
    {
        ParseData();
    }

    private void ParseData()
    {
        //do stuff with data
        handler.post(readNextValue);
    }
}

だから、私が言ったように、すべてのBLEのものはメインスレッドからハンドラーを通して呼び出されます。サービスは、開始から終了まで6回正常に実行されます。 7回目に、私はその愚かなコールバックの登録に失敗しました。

関連性があると思われる場合は、より多くのlogcat情報を提供できます。受け取ったデータを確認するために多くの情報を出力しているなどの理由で、元の投稿には含まれていません.

以下の情報は、サービスの最初から最後までの7回目の実行のlogcat情報です。

08-15 12:00:10.746: I/PMIQ BTS(32027): Service Started...
08-15 12:00:10.746: I/PMIQ BTS(32027): Units: 1
08-15 12:00:10.746: D/AbsListView(32027): unregisterIRListener() is called 
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 0
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to pmIQ-IQ130_D93A
08-15 12:00:10.766: I/System.out(32027): main
08-15 12:00:10.766: D/BluetoothGatt(32027): connect() - device: 00:1E:C0:19:D9:3A, auto: false
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp()
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp() - UUID=e9d10870-4b09-451c-a9fa-c6b5f3594a77
08-15 12:00:10.766: I/BluetoothGatt(32027): Client registered, waiting for callback
08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0
08-15 12:00:10.766: I/PMIQ BTS(32027): CONECTION STATE CHANGED...Binder_2
**08-15 12:00:10.766: E/BluetoothGatt(32027): Failed to register callback**
08-15 12:00:10.766: I/PMIQ BTS(32027): Could not connect to null ... 257
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 1
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.766: I/PMIQ BTS(32027): Start Time: 4360642409647
08-15 12:00:10.766: I/PMIQ BTS(32027): End Time: 4360648970925
08-15 12:00:10.766: I/PMIQ BTS(32027): Difference: 6561278
08-15 12:00:10.766: I/PMIQ BTS(32027): Time to complete: 6
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.876: I/PMIQ BTS(32027): ...Service Destroyed

あなたがここでそれを作ったなら、ありがとう! status = 133の意味に関する情報が見つかりませんでした!?コールバックが失敗したときにのみ発生します。 1回おきにstatus = 0です。

08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0

誰もがこれに答えることさえできれば..それは私を大いに助けるかもしれません。または、なぜ6回しか実行されないのかを誰かが教えてくれれば。どんな洞察や予感も役に立つかもしれません!

みんな、ありがとう!

37
ck1221

わかった。この問題は、主にBluetoothGattのドキュメントを読んでいたときに見落としていました。 .disconnect()を呼び出していましたが、.close()を呼び出していませんでした。 Galaxy s4は一度に6つの接続しか処理できないため、私のサービスは6回しか実行されませんでした。 .close()をコードに追加すると、接続を適切にシャットダウンし、使用済みの接続を解放できました。

ドキュメントをより注意深く読み直したソース!

同じデバイスに繰り返し接続する場合は、BluetoothGattオブジェクトで.close()を使用することを忘れないでください!!

55
ck1221

数ヶ月の研究と私の髪の毛を抜いた後、私は通常話されていない解決策を見つけました。

通常の接続要求は次のようになります。

cGatt.connectGatt(this, false, gattCallback);

4番目のパラメーターを持つconnectGattコマンドの別のバージョンがあります。このパラメーターは、接続するBluetoothデバイスのタイプを指定します。 「2」を追加して、Bluetooth LE経由で接続していることを指定します。 (「トランスポート」と呼ばれ、説明が間違っていても許してくれますが、すべての問題を解決しました)

これを試して:

cGatt.connectGatt(this, false, gattCallback, 2);

そして、BAM、私の#133悪夢は終わりました(私は祈ります)!

13
btmcmahan

Android OS <6.0:

mBluetoothDevice.connectGatt(context, false, callback);

Android OS> = 6.0:

mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);

最終的に、この問題を完全に解決するにはハードウェア機器が必要です。

4
郑松岚
  • 一部のデバイスでは、mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);で修正されました

  • samsung S7、A8などの一部のデバイスでは、ScanSettings.Builder()。setReportDelay(400)//または500msの問題でした。 1000msのように0以上にしないでください。 ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_BALANCED) .setReportDelay(400) .build();

0
user1278366

次の回避策を使用してみてください。

private static boolean gatt_status_133 = false;

final Handler handler = new Handler();

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

    if (newState == BluetoothProfile.STATE_CONNECTED) {
        mConnectionState = STATE_CONNECTED;
        Log.i(TAG, "Connected to GATT server.");
        // Attempts to discover services after successful connection.
        Log.i(TAG, "Attempting to start service discovery:" +
                mBluetoothGatt.discoverServices());

    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        if(status == 133)
        {
            gatt_status_133=true;
        }
        else{
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server."); 
        }
    }
}


@RequiresApi(api = Build.VERSION_CODES.M)
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;
    }

    mBluetoothGatt= device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
    Log.d(TAG, "Trying to create a new connection.");
    mBluetoothDeviceAddress = address;
    mConnectionState = STATE_CONNECTING;

    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(gatt_status_133)
            {
                Log.d(TAG, "Catch issue");
                connect(address);
                gatt_status_133=false;
            }
        }
    }, 4000);

    return true;
}
0
Artem Kabakov