Отсутствует мониторинг и изменение периода сканирования в службе, использующей библиотеку altbeacon android

Я начинающий Android и тестирую некоторые Estimote-Beacons на Android. Мой проект работал с библиотекой Estimote, но теперь я хочу попробовать более открытую библиотеку altbeacon, но у меня есть несколько проблем.

Функция моего приложения должна быть такой: при запуске приложения BeaconApplication должно запускать BeaconsMonitoringService. Два региона должны контролироваться. Если введен регион, служба должна отправить намерение с помощью диспетчера вещания. С информацией о намерении флажок должен быть отмечен / снят в основной деятельности. Служба также запускается, когда приложение было убито или изменилось состояние Bluetooth.

Проблемы:

  • Регион не обнаружен
  • Периоды сканирования не установлены

Отображаются все журналы отладки, кроме "Введено" и "Слева" из onBeaconServiceConnect. Любая помощь будет оценена. Надеюсь, это просто глупая ошибка / новичок, и она работает в целом.:)

Вот мой код приложения-маяка:

package de.mcd.presencealtbeacon;

import android.app.Application;
import android.content.Intent;

import org.altbeacon.beacon.BeaconManager;

public class BeaconApplication extends Application {

    private BeaconManager beaconManager = null;

    @Override
    public void onCreate() {
        super.onCreate();
        beaconManager = BeaconManager.getInstanceForApplication(this);
        startService(new Intent(getApplicationContext(), BeaconsMonitoringService.class));
    }

    public BeaconManager getBeaconManager() {
        if (beaconManager == null) {
            beaconManager = BeaconManager.getInstanceForApplication(this);
        }
        return beaconManager;
    }
}

Вот код службы BeaconsMonitoringService:

package de.mcd.presencealtbeacon;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.BeaconParser;


public class BeaconsMonitoringService  extends Service implements BeaconConsumer {
    private static final String UUID = "1234567-1234-1234-1234-123456789012";
    private static final Region Room = new Region("mcd", Identifier.parse(UUID), Identifier.fromInt(1), null);
    private static final Region Kitchen = new Region("mcd", Identifier.parse(UUID), Identifier.fromInt(2), null);
    private static final String TAG = "BEACON";
    private BeaconManager beaconManager;


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        Log.d(TAG, "Beacons monitoring service started");
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "Beacons monitoring service destroyed");
    }

    public void onBeaconServiceConnect(){

        beaconManager.setMonitorNotifier(new MonitorNotifier() {
            @Override
            public void didEnterRegion(Region region) {
                Log.d(TAG, "Entered");
                if (region.getId2() == Identifier.fromInt(1)) {
                    postNotification("Room", "Entered");
                    intent("1-1");
                } else {
                    postNotification("Kitchen", "Entered");
                    intent("2-1");

                }
            }

            @Override
            public void didExitRegion(Region region) {
                Log.d(TAG, "Left");
                if (region.getId2() == Identifier.fromInt(1)) {
                    postNotification("Room", "Left");
                    intent("1-2");
                } else {
                    postNotification("Kitchen", "Left");
                    intent("2-2");
                }

            }

            @Override
            public void didDetermineStateForRegion(int state, Region region) {
                Log.d(TAG, "Don't know what it's useful for" + state);
            }
        });

        try {
            Log.d(TAG, "Service ready");
            beaconManager.startMonitoringBeaconsInRegion(Room);
            beaconManager.startMonitoringBeaconsInRegion(Kitchen);
        } catch (RemoteException e) {
            Log.e(TAG, "Cannot start ranging", e);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStart Start");
        BeaconApplication app = (BeaconApplication)getApplication();
        beaconManager = app.getBeaconManager();

        beaconManager.setBackgroundScanPeriod(1100l);
        beaconManager.setBackgroundBetweenScanPeriod(10000l);

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

        Log.d(TAG, "onStart End");

        Notification noti = new Notification.Builder(this)
                .setContentTitle("Started")
                .setContentText("Here we go")
                .setSmallIcon(R.mipmap.ic_launcher)
                .build();

        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(2);
        mNotificationManager.notify(1, noti);


        return START_STICKY;
    }


    private void postNotification(String room, String action) {
        Intent notificationIntent = new Intent(BeaconsMonitoringService.this, MyActivity.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent intent = PendingIntent.getActivity(BeaconsMonitoringService.this, 0,
                notificationIntent, 0);

        Notification noti = new Notification.Builder(BeaconsMonitoringService.this)
                .setContentTitle(room)
                .setContentText(action)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(intent)
                .build();


        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.cancel(2);
        mNotificationManager.notify(1, noti);
    }


    private void intent (String code){
        Intent intent = new Intent("statechanged");
        intent.putExtra("info", code);
        LocalBroadcastManager.getInstance(BeaconsMonitoringService.this).sendBroadcast(intent);
    }
}

1 ответ

Решение

Одна проблема заключается в том, что первый параметр Region Конструктор - это уникальная строка для идентификации региона в библиотеке. Каждый регион должен иметь уникальную строку, в противном случае он заменит другой регион с тем же идентификатором при запуске измерения или мониторинга. Код ниже использует один и тот же идентификатор для двух регионов:

private static final Region Room = new Region("mcd", Identifier.parse(UUID), Identifier.fromInt(1), null);
private static final Region Kitchen = new Region("mcd", Identifier.parse(UUID), Identifier.fromInt(2), null);

Это приводит к тому, что вторая отслеживаемая область заменяет первую в приведенном ниже коде:

beaconManager.startMonitoringBeaconsInRegion(Room);
beaconManager.startMonitoringBeaconsInRegion(Kitchen);

Чтобы это исправить, измените настройки региона на:

private static final Region Room = new Region("mcd1", Identifier.parse(UUID), Identifier.fromInt(1), null);
private static final Region Kitchen = new Region("mcd2", Identifier.parse(UUID), Identifier.fromInt(2), null);

На более фундаментальном уровне создание фонового сервиса, который автоматически запускается в фоновом режиме, является довольно сложной задачей для начинающего, который себя описывает. Вероятно, есть много других проблем, которые не очевидны при взгляде на код. Библиотека маяков Android уже предназначена для автоматического запуска в фоновом режиме и сканирования маяков с интервалами сканирования, которые меняются соответствующим образом при изменении приложения с переднего плана на фоновый.

Вы можете увидеть простой пример этого в классе Application в справочном приложении здесь.

Я бы порекомендовал вместо того, чтобы использовать ваш BeaconMoinitoringService Вы копируете код из класса Application справочного приложения в свой BeaconApplication учебный класс. Затем вы можете переместить свой код в didEnterRegion а также didExitRegion методы BeaconApplication класс от вашего BeaconMonitoringService учебный класс.

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

Другие вопросы по тегам