短縮版:
Android 5.0 Lollipopを使用したテストでは、 _Android.bluetooth.le.BluetoothLeScanner
_ Android 4.4 KitKat。なぜこれがあり、代替手段がありますか?
ロングバージョン:
Bluetooth Low Energy(BLE)デバイスの検出に焦点を当てた、特にNexus 7タブレット用のAndroidアプリケーションを開発しています。このアプリは、ビーコンのRSSI値に主に関心を持っています。タブレットに近接しているため、デバイスが検出されるとRSSI値がスキャンコールバックに渡されるため、BLEデバイスに接続する必要はありません。
Android 4.4 KitKatで、BluetoothAdapter.startLeScan(LeScanCallback)
を呼び出すと、検出されたすべてのBLEデバイスに対して1回だけコールバックが呼び出されます。 いくつかの議論 この動作はデバイスごとに異なる可能性があると主張します)ただし、私は絶えず変化するRSSI値に興味があるので、現在推奨されている方法は、設定された間隔(私の場合は250ms)でstartLeScanとstopLeScanを継続的に行うことです:
_public class TheOldWay {
private static final int SCAN_INTERVAL_MS = 250;
private Handler scanHandler = new Handler();
private boolean isScanning = false;
public void beginScanning() {
scanHandler.post(scanRunnable);
}
private Runnable scanRunnable = new Runnable() {
@Override
public void run() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (isScanning) {
adapter.stopLeScan(leScanCallback);
} else if (!adapter.startLeScan(leScanCallback)) {
// an error occurred during startLeScan
}
isScanning = !isScanning;
scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
}
};
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// use the RSSI value
}
};
}
_
基本的に、これにより必要な結果が得られますが、このプロセスはリソースを大量に消費し、最終的には応答しないbluetoothアダプターにつながります。
これらの理由から、Nexus 7をAndroid 5.0 Lollipopにアップグレードして、BLEの問題が修正されるかどうかを確認しました。Lollipopでは、BluetoothAdapter.startLeScan(LeScanCallback)は廃止され、 a新しいAPI これにより、スキャンプロセスをさらに制御できます。最初のテストから、RSSI値が変更されたときにstartScanがコールバック(Nexus 7で)を継続的に呼び出さないため、startScanを使用する必要があります/ stopScanの実装:
_@TargetApi(21)
public class TheNewWay {
private static final int SCAN_INTERVAL_MS = 250;
private Handler scanHandler = new Handler();
private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>();
private ScanSettings scanSettings;
private boolean isScanning = false;
public void beginScanning() {
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
scanSettings = scanSettingsBuilder.build();
scanHandler.post(scanRunnable);
}
private Runnable scanRunnable = new Runnable() {
@Override
public void run() {
BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
if (isScanning) {
scanner.stopScan(scanCallback);
} else {
scanner.startScan(scanFilters, scanSettings, scanCallback);
}
isScanning = !isScanning;
scanHandler.postDelayed(this, SCAN_INTERVAL_MS);
}
};
private ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
int rssi = result.getRssi();
// do something with RSSI value
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
// a scan error occurred
}
};
}
_
ご覧のとおり、ScanSettingsクラスを使用してスキャナーを構成しました。これにより、scanMode
を設定できます。 _ScanSettings.SCAN_MODE_LOW_LATENCY
_を使用します。このドキュメントには、「最高デューティサイクルでスキャンします。このモードは、アプリケーションがフォアグラウンドで実行されている場合にのみ使用することをお勧めします。」私が望むものとまったく同じように聞こえますが、残念なことに、15〜30秒ごとにビーコンを検出するだけです。このスキャン間隔では、キットカットバージョンでは1〜2秒ごとに同じビーコンが表示されます。
この違いの理由は何でしょうか?私は何か、おそらくいくつかの新しい設定が不足していますか?上記を行う別の方法はありますか?
事前に感謝します!
アベル
PS:使用したリソースへのリンクをもっと追加したかったのですが、まだその担当者がいません。
Nexus 5で新しいAndroid 5.0スキャニングAPIを実行しています。SCAN_MODE_LOW_LATENCYを使用すると、BLEビーコンが10Hzで送信される100msごとにほぼリアルタイムでBLEパケットが検出されました。 。
ここで完全な結果を読むことができます:
http://developer.radiusnetworks.com/2014/10/28/Android-5.0-scanning.html
これらのテストは、オープンソースAndroid Beacon Library 2.0の実験的なAndroid-l-apisブランチ here の実行に基づいています。
テスト結果の違いは明らかではありませんが、スキャンの開始と停止によって結果が変わる可能性があります。
EDIT:ハードウェアが異なる可能性があります。 Nexus 4で同様のタイミングのレポートを参照してください。 https://github.com/AltBeacon/Android-beacon-library/issues/59#issuecomment-64281446
私はまだコメントに対する評判がありませんので、ご了承ください。このコメントは回答の形をとるでしょう。あなたのコードでは、この部分はすべきではありません:
if (isScanning) { scanner.startScan(...)
代わりにこれを:
if (!isScanning) {
scanner.startScan(...)
コードに従うため、スキャンを開始する前にstopScan()を呼び出しています。 stopScan()メソッドがべき等/安全である場合、結果に直接影響しない場合があります。ただし、コードをわかりやすくするために、質問を編集する必要があります。そして、あなたのコードにも同じことをしてください。時にはビザンチン的なものが働いています;)
SCAN_INTERVAL_MSの値を大きくしましたか?はいの場合、どのくらいの大きさですか?
キットカットとロリポップの両方で、Nexus 4で非常によく似た結果を経験しました。
KitKatでは、Bluetoothアダプターも最終的に応答しなくなりました。最初は短いスキャン間隔(200ms)に関連している可能性がありましたが、その数を1秒に増やしても助けにはなりませんでした。残念ながら、常に機能するとは言えません。
この問題を解決することを強く望んでいたLollipopで、あなたが説明したのと同じ動作を経験しました。また、startScan/stopScan実装を使用して、検出時間に関して同様の結果を得なければなりませんでした。残念ながら、より迅速に結果を得るための回避策は見つかりませんでした。
Nexus 7とNexus 4は異なるメーカー(AsusとLG)のものですが、説明内容に基づいて、ハードウェアの問題である可能性があります。
私はあなたが何かを見逃しているというあなたの質問に答えようとする以外に、ここではあまり助けを提供していないことを知っています。そうは思いませんが、問題はハードウェアやbluetooth APIのようなもので、それでも異なるデバイス間で正常に動作しないと思います。
API 21を超えてAndroidはデフォルトでSCAN_MODE_LOW_POWERを使用します。 SCAN_MODE_LOW_POWER
SCAN_MODE_BALANCEDを試して、改善するかどうかを確認してください。
SCAN_MODE_BALANCED
googleでBW13_DayOne_Session1 Bluetooth Advanced
を検索すると、検出の設定(8ページを参照)に基づいてデバイスのレイテンシを提供するPDFドキュメントが見つかります。あなたの問題はこれらのタイミングに関係していると思います。テストしているデバイスの広告構成(Adv Int、Duty Cycle)を把握することで確認でき、スキャン間隔などを構成するためにAPI設定が何を行っているかを把握できます。これらを取得したら、そのテーブルを使用できます期待する結果が得られるかどうかを確認するために補間します。
私はこれがソフトウェアサイトであることを知っていますが、多くの場合、ハードウェアとインターフェースをとるときにはプロトコルを知る必要があります。