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 7

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");
    }
}
  1. Реализовать метод 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();
            }
        }
    }