Я создаю приложение для 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 видит устройство. Потом иногда это начинается внезапно. Это странное поведение.
Когда он запускается, о входе/выходе сообщается несколько раз, даже если устройство не движется, и часто о входе/выходе не сообщается (во времени?) в фоновом режиме. Я что-то пропустил?