Я пытаюсь разбудить свое приложение, когда устройство входит в область маяков с определенным UUID.
До сих пор я пробовал использовать собственный BluetoothAdapter.getBluetoothLeScanner, предоставляя PendingIntent для запуска радиоприемника.
Я также попробовал RxBleClient, замечательную библиотеку, которая работает при регулярном обнаружении.
Я попробовал библиотеку AltBeacon, которая также является очень полной и блестящей библиотекой.
Еще пробовал играть в сервисы Nearby Apis.
Но все провалилось. Все они могут регулярно сканировать маяки, но, в основном, при попытке зарегистрироваться и позволить устройству сканировать, находясь в режиме bg. Трансляция никогда не запускается.
Я также пробовал все 4 при использовании службы переднего плана. Это тоже не помогло. Я также упомяну, что все это делается на Android 8. Я просмотрел код в обеих библиотеках, и в конечном итоге они оба используют один и тот же вызов функции из собственного bluetoothadapter. Итак, я предполагаю, что если это не удастся, все остальное тоже потерпит неудачу. Я также упомяну, что при предоставлении функции startScan CallBack вместо PendingIntent, обратный вызов постоянно запускается для всех просканированных устройств BT. Если я добавлю ScanFilter для фильтрации только моего UUID, это не сработает. Что мне не хватает?
Кстати, когда я реализовал это на iOS, он работал безупречно. Приложение просыпается, как если бы я использовал триггер входа / выхода Geofence.
Почему это не работает в Android? Есть предположения?
РЕДАКТИРОВАТЬ: вот как я использовал код из библиотеки AltBeacon. По сути, это копипаст из учебника DOCS. Единственная разница в том, что я инкапсулировал его в отдельный класс:
public void init(AppCompatActivity context) {
if (isRegistered) {
return;
}
BluetoothManager bluetoothManager = (BluetoothManager) context.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivityForResult(enableBtIntent, 1002);
} else {
register(context);
}
}
}
public void register(AppCompatActivity context) {
if (isRegistered) {
return;
}
executorService.execute(new Runnable() {
@Override
public void run() {
Region region = new Region("com.sample.WakeOnDiscovery", Identifier.parse("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), Identifier.fromInt(11180), null);
bootstrapRegion = new RegionBootstrap(new BootstrapNotifier() {
@Override
public Context getApplicationContext() {
return Application.getContextFromApplicationClass();
}
@Override
public void didEnterRegion(Region region) {
Logger.log(TAG, "didEnterRegion: " + region.toString());
}
@Override
public void didExitRegion(Region region) {
Logger.log(TAG, "didExitRegion: " + region.toString());
}
@Override
public void didDetermineStateForRegion(int i, Region region) {
Logger.log(TAG, "didDetermineStateForRegion: " + region.toString() + "|" + i);
}
}, region);
}
});
isRegistered = true;
}
Это когда я пытаюсь сканировать этот конкретный UUID и основной int (и без основного int). Как только я думаю, срабатывает только didDetermineStateForRegion. С int i = 0 или 1.
Что касается UUID, я пробовал 2 разных UUID. Первый - это то, что я создаю в образце приложения, написанном на IOS. Приложение ios позиционирует себя как маяк. Я вижу это в другом приложении, которое использует обычную функцию обнаружения. Но onEnterRegion не срабатывает.
Я также попробовал UUID от устройства iBeacon, которое я регулярно использую в течение многих лет. По-прежнему нет игральных костей.
Когда я пытаюсь использовать собственный сканер Android BLE, я использую это:
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
filters.add(new ScanFilter.Builder()/*.setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"))*/.build());
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));
и:
private PendingIntent getPendingIntent(Context context) {
return PendingIntent.getBroadcast(context, 0, new Intent(context, BTDiscoveryBroadcast.class), PendingIntent.FLAG_UPDATE_CURRENT);
}
Я пробовал передавать null в качестве фильтров, пробовал пустой список массивов и пробовал реальный фильтр с тем же UUID.
По-прежнему ничего не работает.
то, что я случайно увидел в logcat, - это сообщение об ошибке:
E/NearbyDirect: Could not start scan. [CONTEXT service_id=49 ]
java.lang.IllegalStateException: Receiver com.google.location.nearby.direct.bluetooth.state.FastPairScanner$4@535d6ea registered with differing handler (was Handler (adxv) {8fab16a} now Handler (android.app.ActivityThread$H) {e4e0078})
Я думаю, что это происходит и при использовании библиотеки AltBeacon. Могу только предположить, что это связано с моей проблемой.
ИЗМЕНИТЬ 2: Я пробовал это:
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).build();
List<ScanFilter> filters = new ArrayList<>(); // Make a scan filter matching the beacons I care about
byte[] manufacturerData = new byte[] {
// iBeacon identifier prefix
0x02, 0x15,
// Your Proximity UUID
(byte) 0xE2, (byte) 0xC5, 0x6D, (byte) 0xB5, (byte) 0xDF, (byte) 0xFB, 0x48, (byte) 0xD2, (byte) 0xB0, 0x60, (byte) 0xD0, (byte) 0xF5, (byte) 0xA7, 0x10, (byte) 0x96, (byte) 0xE0,
0x3, 0x20, 0x3, 0x20, (byte) 0xC5
};
int manufacturerId = 0x004c; // Apple
filters.add(new ScanFilter.Builder().setManufacturerData(manufacturerId, manufacturerData).build());
bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, getPendingIntent(context));
Данные в байтах, которые я получил после выполнения обычного сканирования .startDiscovery, обнаружения моего устройства bt и извлечения данных из ScanResult. Просто чтобы убедиться, что он такой же.
По-прежнему не запускает трансляцию :(