Ранжирование фоновой службы Android AltBeacon

Я работаю над приложением Bluetooth, используя библиотеку AltBeacon. Кажется, что для каждого приложения разрешен только экземпляр BeaconManager. Проблема, с которой я столкнулся, заключается в следующем: мне нужна постоянно работающая фоновая служба, которая постоянно выполняет поиск по Bluetooth и отправляет уведомления. Если я открываю свое приложение (выношу его на передний план), я должен был приостановить ранжирование. Затем действие переднего плана выполнит ранжирование и отобразит контент на экране.

Проблема в том, что менеджер маяков (из BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);) в действии и сервисе - это один и тот же экземпляр. Поэтому, когда действие закрывается, вызывается beaconManager.unbind(this);, и средство уведомления о диапазоне в службе больше не срабатывает.

Можно ли получить два отдельных экземпляра beacon manager? Если нет, как мне выполнить ранжирование в непрерывно работающей службе и деятельности?

Ранжирование

@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);
    }
}

person mashrur    schedule 28.10.2014    source источник


Ответы (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

person davidgyoung    schedule 28.10.2014
comment
Привет, Дэвидгён, я хочу сканировать маяки в фоновой службе, даже если пользовательский интерфейс приложения не отображается. Не могли бы вы посоветовать мне и поделиться фрагментом кода для достижения этой цели. заранее спасибо - person Dayanand Fagare; 08.04.2015
comment
См. Пример здесь: altbeacon.github.io/android-beacon-library/samples. html в разделе "Запуск приложения в фоновом режиме". Вам не нужна собственная услуга, поскольку ее предоставляет библиотека. Просто реализуйте обратные вызовы в пользовательском классе приложения. - person davidgyoung; 08.04.2015
comment
Большое вам спасибо .. Я пробовал это, но сканирование остановится, как только вы выйдете из приложения. например. если вы перейдете на главный экран. Я хочу добиться непрерывного сканирования. пожалуйста, помогите мне. - person Dayanand Fagare; 08.04.2015
comment
Нет, сканирование будет продолжаться в фоновом режиме с пониженной скоростью. (По умолчанию каждые 5 минут.) Ознакомьтесь со справочным приложением, которое является рабочим приложением, которое делает это на основе приведенного выше примера. github.com/AltBeacon/android-beacon-library-reference См. здесь тоже altbeacon.github.io/android-beacon-library/battery_manager.html < / а> - person davidgyoung; 08.04.2015
comment
Большое спасибо..я поняла .. :) - person Dayanand Fagare; 13.04.2015
comment
@davidgyoung Как уменьшить скорость сканирования .. как вы упомянули 5 минут по умолчанию в предыдущем комментарии .. Итак, как уменьшить это до 1 минуты - person cryptic; 01.03.2016
comment
beaconManager.setBackgroundBetweenScanPeriod(60000l) сообщает библиотеке делать паузу на 60 секунд между каждым сканированием фона вместо 5 минут. - person davidgyoung; 01.03.2016
comment
Я также могу подтвердить, что установка BackgroundBetweenScanPeriod в классе приложения также, похоже, не выполняет ничего, что работает с кодом в Nexus 5 с Android 6.0. - person Steve; 13.04.2016
comment
Вам также необходимо позвонить beaconManager.updateScanPeriods();, чтобы подтвердить изменения в службе сканирования, если вы вносите изменения после того, как она уже запущена. Если вы вносите изменения сразу после получения ссылки на BeaconManager при запуске приложения, вам не нужно этого делать. - person davidgyoung; 13.04.2016
comment
привет @davidgyoung, я реализую Altbeacon в приложении Titanium, используя этот модуль github.com/dwk5123/ модуль-android-altbeacon. Он работает неплохо, но я не могу переопределить созданный Titanium класс Application для реализации интерфейса BootstrapNotifier. Есть ли другой способ получить событие didDetermineStateForRegion, когда приложение убито (удалено из диспетчера задач)? Большое спасибо за вашу работу над SO, видел, как вы были активны здесь во многих вопросах Altbeacon =) - person Carlos Zinato; 09.08.2016
comment
Это, наверное, заслуживает отдельного вопроса. - person davidgyoung; 09.08.2016
comment
Привет, @davidgyoung, я разместил свой вопрос: stackoverflow.com/questions/38855595/ Вы можете мне в этом помочь? Спасибо =) - person Carlos Zinato; 09.08.2016

Вам следует расширить класс 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();
            }
        }
    }
    
person Ivo Stoyanov    schedule 17.12.2015
comment
Не могли бы вы поделиться образцом класса приложения с RangeNotifier? - person Majid Hojati; 09.10.2016
comment
зачем вам отключать маяки для измерения дальности? - person Diego Rivera; 21.10.2020
comment
@DiegoRivera, вам нужно отключить маяки для определения расстояния, чтобы сэкономить заряд батареи. - person Ivo Stoyanov; 21.10.2020