web-dev-qa-db-ja.com

アンドロイド4.3のBluetooth低エネルギー不安定

私は現在、Bluetooth Low Energyを使用するアプリケーションを開発しています(Nexus 4でのテスト)。 Android 4.3で公式のBLE APIを使い始めた後、初めてデバイスを接続した後、そのデバイスまたは他のデバイスに再度正常に接続/通信できなくなることに気付きました。

ガイドに従って ここ 、私は問題なくデバイスに接続し、サービスと特性をスキャンし、そして通知を読み書きすることができます。ただし、切断して再接続した後、サービスや特性をスキャンできない、または読み取り/書き込みを完了できないことがよくあります。これが起こっている理由を示すためにログで何かを見つけることができません。

これが起こったら私はアプリケーションをアンインストールし、Bluetoothを無効にし、そしてそれが再び働き始める前に電話を再起動しなければならない。

デバイスが切断されているときはいつでも、必ずBluetoothGattオブジェクトに対してclose()を呼び出し、それをnullに設定します。何か洞察がありますか?


編集:
ログダンプ:これらのログのために私は私の電話を根付かせて/etc/bluetooth/bt_stack.conf内の関連項目のトレースレベルを上げました

接続成功 - 電話を再起動してアプリをインストールした後の最初の試行。接続し、すべてのサービス/特性を発見し、読み書きすることができます。

Failed Attempt 1 - これは上記の成功した接続から切断した後の次の試行です。特性を発見できたようですが、最初に読み取ろうとするとNULL値が返され、その後すぐに切断されました。

Failed Attempt 2 - サービスや特性を見つけることさえできない例。


編集2:
接続しようとしているデバイスは、TIのCC2541チップに基づいています。私は TI SensorTag (これもCC2541に基づいています)を入手し、TIが昨日SensorTagに対して Androidアプリ をリリースしたことを発見しました。しかし、このアプリは持っています 同じ問題。 私はこれと同じ結果で他の2つのNexus 4でこれをテストしました:SensorTagへの接続は1回目または2回目で成功しますが、(ログによると)その後サービスを発見できず、あらゆる種類のクラッシュを引き起こします。私はそれがこの特定のチップの問題なのか疑問に思い始めていますか?

185
sa.shadow

重要な実装のヒント

(おそらく、Android OSの更新により、これらのヒントの一部はもう必要ありません。)

  1. Android 4.3のNexus 4などの一部のデバイス 既存のgattインスタンスを使用して接続するには45秒以上かかります 。回避策:切断時に常にgattインスタンスを閉じ、接続ごとにgattの新しいインスタンスを作成します。
  2. Android.bluetooth.BluetoothGatt#close()を呼び出すことを忘れないでください
  3. 内部で新しいスレッドを開始しますonLeScan(..)してから接続します。理由:Android 4.3(少なくともビルドJSS15J.I9300XXUGMK6の場合)のSamsung Galaxy S3上の同じスレッドでBluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)内で呼び出された場合、LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)は常に失敗します
  4. ほとんどのデバイスは広告をフィルタリングします
  5. 使用しない方が良いAndroid.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback)特定のサービスUUIDをフィルターするパラメーターこれは、Samsung Galaxy S3でAndroid 4.3を使用して完全に壊れているためです。 128ビットUUIDでは機能しません 一般的には。
  6. Gattは常に一度に1つのコマンドを処理できます。複数のコマンドが次々と呼び出されると、最初のコマンドがキャンセルされます gatt実装の同期性のため
  7. Android 5を搭載した最新のデバイスでも、Wifiがbluetoothを妨害し、その逆も同様であることがよくあります。 最後の手段として、無線LANをオフにしてBluetoothを安定させます。

初心者向けチュートリアル

初心者向けの非常に良いエントリポイントは、次のビデオチュートリアルです。Android http://youtu.be/x1y4tEHDwk

以下で説明する問題と回避策は、OSの更新によりおそらく修正されます。

回避策:アプリを「安定化」することができます...

  1. ユーザーに「Bluetoothを再起動する」設定を提供します。その設定が有効になっている場合、BLEスタックの開始が不安定になることを示すいくつかのポイントでBluetoothを再起動します。例えば。 startScanがfalseを返す場合。良い点は、serviceDiscoveryが失敗した場合でもあります。 Bluetoothをオフにしてからオンにします。
  2. 別の設定「WiFiをオフにする」を提供します。その設定が有効になっている場合、アプリの実行中にアプリがWifiをオフにします(その後、再びオンになります)

この回避策は、次の経験に基づいています...

  • Bluetoothを再起動すると、ほとんどの場合、BLEの問題を解決できます
  • Wifiをオフにすると、BLEスタックはさらに安定します。ただし、wifiがオンになっているほとんどのデバイスでも正常に動作します。
  • Wifiをオフにすると、Bluetoothを再起動すると、ほとんどの場合、デバイスを再起動することなく、BLEスタックが完全に回復します。
176
OneWorld

無線LANをオフにする:

私は、WIFIをオフにすると、特にGoogle Nexus(私はNexus 7を持っています)でBluetooth 4.0をより安定させることを確認できます。

問題

それは私が開発しているアプリケーションですニーズ両方WIFIそして継続的--- Bluetooth LEスキャン。だから無線LANをオフにすることは私のためのオプションではなかった。

さらに、私は継続的なBluetooth LEスキャン実際にはWIFI接続を強制終了にして、WIFIアダプタを再接続できないにすることができます。 BLEスキャンがONになるまで。 (私はモバイルネットワークとモバイルインターネットについてはよくわかりません)。
これは間違いなく次のデバイスで起こりました:

  • ネクサス7
  • モトローラモトG

しかし、WIFIをオンにしたBLEスキャンは、かなり安定しているようです。

  • サムソンS4
  • HTCワン

私の回避策

I BLEをスキャン短時間-4秒次にI スキャンを3-4秒オフにする。それからまたON。

  • BLEデバイスに接続しているときは、明らかにBLEスキャンを常にオフにしています。
  • デバイスから切断したとき、スキャンを再開する前にBLEを再起動し(アダプタをオフにしてからオンにする)、スタックをリセットします。
  • servicesまたはcharacteristicsの検出に失敗した場合も、BLEをリセットします。
  • アプリが接続する必要があるデバイスから広告データを取得すると(接続できなくても500回としましょう - 広告の約5〜10秒かかります)、再びBLEをリセットします。
15
benka

Nexusがデバイスとペアリングされていることを確認してください。通信が正しく機能しているかどうかは確認できませんが、再起動しなくても複数回接続できます。最初の接続はペアリングを必要としていないようですが、その後のすべての試行は必要です。

私はサービスの発見と再起動なしで大容量の読み書き要求をテストする2、3日でこの答えを更新するつもりです。

編集:それはペアにしていない場合は問題を引き起こしていた開発ファームウェアのバージョン(私たちのセンサー)でテストしていたことがわかりました。当社の最新のプロダクションファームウェアビルドは、2540および2541で正常に動作します。

編集:私はネクサス7 2013年に、WiFiがオフになっているときに接続がより安定していることに気づいた。これが他の人に役立つかどうかを知りたいのですが。

編集:私はペアリングと逆にそれを持っていたようだ。ペアになっていないときはすべてうまくいきます。ペアリング後、私はOPとまったく同じ症状を経験しています。これが当社のファームウェアまたはAndroid BLE APIに関連しているかどうかはまだわかりません。これをテストする場合は注意してください。ペアになると、この3bの中で説明されているバグのためにペアリングを解除できない可能性があります post

6
Mikt25

いくつかのモデルでは欠陥があります: https://code.google.com/p/Android/issues/detail?id=18044

一方私の場合は、問題は、onDestroyメソッドで接続が正しく閉じられなかったことです。正しく閉じた後、私のための問題は存在していない、無線LANがオンまたはオフになっていることは関係ありません。

btGatt.disconnect();
btGatt.close();
4
Krystian

私は同様の問題に直面していました。私の修正は

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

切断後にcloseを呼び出します。

0
Sam Reyes