AltBeacon: ранжирование не работает должным образом

Я создаю приложение для Android, которое должно запускать действия в фоновом режиме, когда пользователь входит или выходит из "зоны Bluetooth", которую пользователь может определить. Как геозоны от Google.

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

«Зоны Bluetooth» настраиваются пользователем путем сканирования устройств Bluetooth, выбора устройства и добавления к нему радиуса. Это работает, как и ожидалось. Затем эта «зона Bluetooth» сохраняется и ранжируется BeaconManager как регион в собственной активности:

    BeaconManager mBeaconManager = BeaconManager.getInstanceForApplication(this);
    Region singleBeaconRegion = new Region(mRegion.getText().toString(), listB);
    try {
        mBeaconManager.startRangingBeaconsInRegion(singleBeaconRegion);
    } catch (RemoteException e) {   } 

Также у меня есть приложение, которое выглядит так:

    public class BtZoneApplication extends Application implements BootstrapNotifier, RangeNotifier{
private static final String TAG = "BeaconReferenceAppl";
private BeaconManager mBeaconManager;
private Region mAllBeaconsRegion;
private BackgroundPowerSaver mBackgroundPowerSaver;
private RegionBootstrap mRegionBootstrap;
private Worker worker;
private final static String ALLBEACONSREGION = "##AllBeaconsRegion##";
DbServerHelper datasourceServer;
DbZoneHelper datasource;

@Override
public void onCreate() {
    mAllBeaconsRegion = new Region(ALLBEACONSREGION, null, null, null);
    mBeaconManager = BeaconManager.getInstanceForApplication(this);
    mBackgroundPowerSaver = new BackgroundPowerSaver(this);
    mBeaconManager.setBackgroundBetweenScanPeriod(30000L);
    mBeaconManager.setBackgroundScanPeriod(2100L);
   // wake up the app when a beacon is seen
    mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
    mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
}

@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
    // Start actions
    if (region.getUniqueId().equals(ALLBEACONSREGION)){
        return;
    }
    if (beacons.size() > 0) {
        for (Beacon beacon: beacons) {
            Log.d(TAG, "Beacon "+beacon.toString() + " is about " + beacon.getDistance() + " meters away, with Rssi: " + beacon.getRssi());
            // 
            if (beacon.getDistance() < radius && !status) {
                // set status to true
                // start action at entering zone
            }
            // radius * 2 for testing
            if (beacon.getDistance() > radius * 2 && status) {
                // set status to false
                // start action at exiting zone
            }
        }
    }
}

@Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
   // do nothing
}

@Override
public void didEnterRegion(Region region) {
    Log.d(TAG, "entered region.  starting ranging");
    setRegionsAtBoot();
    mBeaconManager.setRangeNotifier(this);
}

@Override
public void didExitRegion(Region region) {
   // do nothing. Ranging should work further
}

// Set regions to monitor at boot/startup
private void setRegionsAtBoot(){
    ...
    for (Iterator<SimpleBeacon> iterator = beacons.iterator(); iterator.hasNext();) {
        ...
        try {
            mBeaconManager.startRangingBeaconsInRegion(new Region(simpleBeacon.getId(), listB));
        } catch (RemoteException e) {
        }
    }
}

Моя проблема в том, что он не начинает ранжировать при запуске приложения, хотя BluetoothLeScanner видит устройство. Потом иногда это начинается внезапно. Это странное поведение.

Когда он запускается, о входе/выходе сообщается несколько раз, даже если устройство не движется, и часто о входе/выходе не сообщается (во времени?) в фоновом режиме. Я что-то пропустил?


person egmontr    schedule 11.11.2015    source источник


Ответы (1)


Несколько проблем в коде Application:

  • Нет необходимости реализовывать BeaconConsumer или явно вызывать bind при использовании RegionBootstrap, так как привязка происходит автоматически внутри RegionBootstrap.

  • Я бы перенес звонок с setRegionsAtBoot на didEnterRegion.

Не совсем понятно, почему могут возникнуть симптомы, которые вы описываете, но вышеперечисленное может быть причиной.

Вы также можете использовать готовый сканер, такой как Locate Beacon, чтобы убедиться, что ваши маяки могут быть надежно определены. Это поможет устранить аппаратную проблему.

Наконец, сначала заставьте его работать на переднем плане, а затем сосредоточьтесь на фоновых операциях.

person davidgyoung    schedule 11.11.2015
comment
Я протестировал маяк с помощью приложения Locate, и оно его нашло. Поэтому я искал больше, и в конце концов это была моя вина. У меня была ошибка при чтении из базы данных, поэтому построенные регионы были неправильными. Извиняюсь! Я также обновил код, как вы предложили. Спасибо. Теперь он работает на переднем плане, но в фоновом режиме требуется много времени, чтобы распознать диапазон. Я установил время фонового сканирования, например: mBeaconManager.setBackgroundBetweenScanPeriod(30000L); mBeaconManager.setBackgroundScanPeriod(2100L); ` Я что-то пропустил? - person egmontr; 11.11.2015
comment
На устройствах Android 5+ обнаружение происходит намного быстрее в фоновом режиме. Но в более ранних версиях ОС вам приходилось ограничивать фоновое сканирование для экономии заряда батареи, если только у вас нет специализированного приложения, в котором фоновое использование с высоким зарядом батареи допустимо. Вы должны выбрать баланс между медленным фоновым обнаружением и экономией заряда батареи в зависимости от потребностей вашего варианта использования. - person davidgyoung; 11.11.2015
comment
как вы предложили, я перенес инициализацию маяков из базы данных в didEnterRegion: setRegionsAtBoot в didEnterRegion. Проблема, которую я увидел сейчас, заключается в том, что didEnterRegion вызывается часто, а затем регионы регистрируются несколько раз в rangedRegions ArrayList в startRangingBeaconsInRegion BeaconManager. Кроме того, когда я делаю stopRangingBeaconsInRegion для одного региона, он удаляет только один из дубликатов. Не лучше ли было бы использовать другой список, избегающий повторяющихся элементов? - person egmontr; 13.11.2015
comment
Вы можете просто вызвать stopRangingBeaconsInRegion перед вызовом startRangingBeaconsInRegion. И сохраняйте свой уникальный идентификатор постоянным. - person davidgyoung; 13.11.2015