Трансляция не запускается при использовании bluetoothLEScanner (). StartScan - PullRequest
1 голос
/ 08 марта 2020

Я пытаюсь разбудить мое приложение, когда устройство входит в область маяков с указанным c UUID.

До сих пор я пытался использовать собственный BluetoothAdapter.getBluetoothLeScanner , предоставляющий PendingIntent для запуска приемника Broadcast.

Я также попробовал RxBleClient , который является удивительной библиотекой, которая работает при выполнении обычного обнаружения.

Я попробовал AltBeacon lib, которая также является очень тщательной и блестящей.

Я также попробовал игровые сервисы Nearis Apis.

Но все не удалось. Все они могут регулярно сканировать радиомаяки, но при попытке регистрации зарегистрируйтесь и дайте устройству сканировать, находясь в bg. Трансляция никогда не запускается.

Я также пробовал все 4 при использовании службы переднего плана. Это тоже не помогло. Я также упомяну, что все это сделано на Android 8. Я просмотрел код в обеих библиотеках, и они оба в конечном итоге используют один и тот же вызов функции из собственного адаптера bluetooth. Так что я предполагаю, что если это не удастся, все остальное тоже не получится Также стоит упомянуть, что при предоставлении функции 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;
}

Это когда я пытаюсь найти этот специфицированный c UUID и major int (и без major 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);
}

Я попытался передать ноль как Фильтры, я пробовал пустой список массивов, и я пробовал реальный фильтр с тем же 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 данных. Просто чтобы убедиться, что он точно такой же.

Все равно не запускает трансляцию: (

1 Ответ

1 голос
/ 09 марта 2020

Если вы хотите настроить фильтр сканирования для поиска UUID маяка, код , подобный этому, не будет работать:

filters.add(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")).build());

Приведенный выше код установит фильтр на ищите устройство BLE, рекламирующее UUID службы GATT, соответствующий E2C56DB5-DFFB-48D2-B060-D0F5A71096E0. UUID службы GATT не имеет абсолютно никакого отношения к UUID близости радиомаяка Bluetooth, хотя оба UUID могут выглядеть внешне одинаково. Другими словами, вы говорите фильтру искать подключаемое устройство Bluetooth, которое объявляет пользовательский сервис, который, как оказалось, совпадает с вашим идентификатором маяка. Это никогда ничего не найдет, потому что такое устройство почти гарантированно не существует.

То, что вы хотите сделать вместо этого, является более сложным - вы хотите настроить фильтр сканирования, который ищет объявление производителя Bluetooth LE (что представляют собой рекламные объявления iBeacon и AltBeacon), которые имеют определенный c код производителя и начинаются с определенной последовательности байтов.

Получить точную байтовую последовательность для фильтра непросто, поскольку она зависит как от идентификатора производителя, так и от схемы маяка (iBeacon или AltBeacon). Это одна из многих сложностей, которые Android Beacon Library обрабатывает для вас.

Если вам действительно нужно сделать это самостоятельно, вы бы сделали что-то подобное для iBeacon (ВНИМАНИЕ: непроверенный код):

byte[] manufacturerData = new byte[] {
            // iBeacon identifier prefix
            0x02, 0x15, 
            // Your Proximity UUID
            0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2, 0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0
            };
int manufacturerId = 0x004c; // Apple
ScanFilter filter =
filters.add(new ScanFilter.Buider().setManufacturerData(manufacturerId, manufacturerData).build());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...