Android AltBeacon Фоновая Служба Ранжирования
Я работаю над приложением bluetooth, используя библиотеку AltBeacon. Похоже, что только на экземпляре BeaconManager
разрешено одно приложение. Проблема, с которой я сталкиваюсь, заключается в следующем: Я хочу постоянно работающую фоновую службу, которая постоянно делает Bluetooth-диапазон и отправляет уведомления. Если я открываю свое приложение (выношу его на передний план), я был сервисом для приостановки ранжирования. Затем действие на переднем плане будет выполнять ранжирование и отображать содержимое на экране.
Проблема в том, что менеджер маяков (от BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
) в деятельности и служении-это один и тот же экземпляр. Поэтому, когда действие закрывается, вызывается beaconManager.unbind(this);
, и уведомитель диапазона в службе больше не срабатывает.
Можно ли получить два отдельных экземпляра beacon manager? Если нет, то как я могу сделать ранжирование в непрерывно работающей службе и деятельности?
RangingActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
...
regionEstimote = new Region("estimote", null, null, null);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.bind(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
notificationManager.cancel(NOTIFICATION_ID);
//beaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
....
});
try {
beaconManager.startRangingBeaconsInRegion(regionEstimote);
} catch (RemoteException e) {
Log.e(TAG, "RangingActivity", e);
}
}
BeaconService.java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(beaconHistory == null)
beaconHistory = new HashMap<Integer, Date>();
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBeaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
beaconHistory = null;
mBeaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
mBeaconManager.setRangeNotifier(new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if(ActivityBase.isActivityVisible()) { //don't do ranging logic if any activity from my app is in the foreground
return;
}
...
}
});
try {
mBeaconManager.startRangingBeaconsInRegion(regionMint);
} catch (RemoteException e) {
Log.e(TAG, "BeaconService", e);
}
}
2 ответа:
Это случай, когда пользовательский класс
android.app.Application
очень полезен.BeaconManager
является синглетом, поэтому одновременно может существовать только один. Аналогично, классApplication
имеет один экземпляр для каждого активного приложения Android. Если вы хотите сделать обнаружение маяка вActivity
иService
Одновременно, используйте централизованный классApplication
для выполнения привязки кBeaconManager
, а затем переадресуйте обратные вызовы как к вашемуActivity
, так и к вашемуService
.Вы можете увидеть пример привязки к
BeaconManager
вApplication
класс и затем передача обратных вызовов вActivity
в справочном приложении здесь: https://github.com/AltBeacon/android-beacon-library-reference/blob/master/app/src/main/java/org/altbeacon/beaconreference/BeaconReferenceApplication.java
Вы должны расширить класс Applicaton и запустить фоновый мониторинг региона, как это описано здесь (см. "запуск приложения в фоновом режиме").
Чтобы сделать ранжирование, в том же классе реализуем RangeNotifier:
public class AndroidApp extends Application implements BootstrapNotifier, RangeNotifier {...
Начните ранжирование в didEnterRegion:
@Override public void didEnterRegion(Region region) { try { mBeaconManager.startRangingBeaconsInRegion(region); } catch (RemoteException e) { if (BuildConfig.DEBUG) Log.d(Const.TAG, "Can't start ranging"); } }
Реализовать метод didRangeBeaconsInRegion:
@Override public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) { if (beacons.size() > 0) { Beacon firstBeacon = beacons.iterator().next(); if (BuildConfig.DEBUG) Log.d(Const.TAG, "Beacon ranged: UUID: " + firstBeacon.getId1().toString() + " Major: " + firstBeacon.getId2().toString() + " Minor: " + firstBeacon.getId3().toString()); // Do something with the result // Stop ranging try { mBeaconManager.stopRangingBeaconsInRegion(region); } catch (RemoteException e) { e.printStackTrace(); } } }