私はAndroid BLE(Bluetooth Low Energy)を使用しています。使用しているBLEデバイスのスキャンに問題があります。startLeScan(UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback)
メソッド
_startLeScan(BluetoothAdapter.LeScanCallback callback)
が正常に動作している間。
フィルターを使用して特定のserviceUUIDをスキャンすると、コールバックが実行されません。私はsamsung galaxy s6でテストしています。
この問題がデバイス固有のものか、スキャン機能にバグがあるかどうかを知りたいです。
私はそれがデバイス固有ではないと確信しています。まず第一に、IshArtが述べたように、Android 5.0以降のstartScanを使用する必要があります。
startScan(List<ScanFilter> filters, ScanSettings settings, ScanCallback callback)
私の経験では、MACアドレスを取得する場合、Scanfiltersの実装は正常に機能しますが、他のフィルターセットアップパラメーターは問題があります。
ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(deviceMacAddress).build();
filters.add(filter);
それが選択肢にならない場合は、独自のフィルターを実装することもできます。 startScan()のフィルターリストを空のままにすると、すべてのフィルタリングが無視され、すべてが受信されます。次に、コールバックで独自のメソッドを記述して、結果が要件を満たしているかどうかを確認できます。
これは、Samsung Galaxy S6で見つかった特定の問題です。私は新しいスキャナーAPIを使用し、Android 5.0+。 S6に問題がある理由を知ってください。
回避策は、残念ながら、デバイスが検出された後、MACアドレスを手動でフィルタリングすることです。
更新
これにより、Galaxy S6で発生していた上記の問題が修正されました。
以前は、次のように2つの条件を同じScanFilter
に追加していました(Kotlin)。
ScanFilter.Builder()
.setServiceUuid(BluetoothBlind.Service.ParcelUUID)
.setDeviceAddress(macAddress)
.build()
条件を複数のフィルターに分割するように変更すると、修正されます。
ScanFilter.Builder()
.setDeviceAddress(macAddress)
.build()
ScanFilter.Builder()
.setServiceUuid(BluetoothBlind.Service.ParcelUUID)
.build()
BLEフィルタースキャンの問題は既知の問題です。この問題およびその他のBLEの問題については、 https://github.com/iDevicesInc/SweetBlue/wiki/Android-BLE-Issues を参照してください。結論は簡単です。「すべてのデバイスをスキャンして、自分でフィルタリングする必要があります。」
2つのスキャン方法があります:
//Device scan callback Lollipop and above
private ScanCallback generateScanCallback(){
if(apiVersion> Build.VERSION_CODES.KitKat) {
ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
final BluetoothDevice device = result.getDevice();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e(TAG, "running scan " + device.getAddress());
if (device.getAddress().equals(mDeviceAddress)) {
Log.e(TAG, "device founded, trying to connect");
scanLeDevice(false);
Intent gattServiceIntent = new Intent(mContext, BluetoothLeService.class);
mContext.bindService(gattServiceIntent, mServiceConnection, mContext.BIND_AUTO_CREATE);
mIndicationText.setText(mContext.getString(R.string.waiting));
}
}
});
}
};
return mScanCallback;
}
return null;
}
// Device scan callback KitKat and below.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e(TAG,"running scan "+device.getType());
if(device.getAddress().equals(mDeviceAddress)){
Log.e(TAG, "device founded, trying to connect");
scanLeDevice(false);
Intent gattServiceIntent = new Intent(mContext, BluetoothLeService.class);
mContext.bindService(gattServiceIntent, mServiceConnection, mContext.BIND_AUTO_CREATE);
mIndicationText.setText(mContext.getString(R.string.waiting));
}
}
});
}
};
そしてより:
if(apiVersion> Build.VERSION_CODES.KitKat) {
scanner = mBluetoothAdapter.getBluetoothLeScanner();
// Device scan callback Lollipop
scanner.startScan(generateScanCallback());
} else {
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
必要に応じてスキャン方法をカスタマイズできますが、1つのAndroid 5
以上ともう1つのAndroid
OS
の2つのスキャン方法があることを知っておく必要があります。