Вопросы о периоде сканирования android-beacon-library

У меня проблема с периодом сканирования, когда я использую android-beacon-library. И вот моя проблема:

У меня есть три основных класса: MainActivity, BaseService и BeaconService.

  • MainActivity: Просто выполните операции startForeground и stopForeground.
  • BaseService: Выполнить инициализацию некоторых параметров, BeaconManager и т.д.
  • BeaconService: Работа маяка.

Сначала описываю свои проблемы. Я использую службу переднего плана для выполнения операции сканирования, а backgroundScanPeriod составляет 20l. И у меня также есть MainActivity с двумя кнопками, startService и stopService. Период сканирования составляет 10 секунд, когда я впервые открываю приложение и нажимаю startService.< a href="https://i.stack.imgur.com/FnNIj.png" rel="nofollow noreferrer">10s-период сканирования

Затем я нажимаю ДОМОЙ и закрываю это приложение, служба работает нормально, а период сканирования также составляет 10 секунд. Но когда я снова открываю MainActivity, щелкнув уведомление на картинке.

Период сканирования станет равным 1 с. Это быстро для меня. Но период сканирования станет нормальным, если я снова нажму ДОМОЙ. Это означает, что период сканирования будет очень быстрым каждый раз, кроме первого раза, когда я открываю MainActivity.

1с

Я хочу знать, почему. И вот мой важный код ниже:

MainActivity.class

@OnClick(R.id.start_service)
void start_Service() {
    if (Utils.isServiceRunning(MainActivity.this, Constants.CLASSNAME)) {
        Toast.makeText(this, "service is running, don't start again", Toast.LENGTH_SHORT).show();
    } else {
        Intent intent = new Intent(MainActivity.this, BeaconService.class);
        intent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
        startService(intent);
        setInfo();
    }
}

@OnClick(R.id.stop_service)
void stop_Service() {
    if (Utils.isServiceRunning(MainActivity.this, Constants.CLASSNAME)) {
        Intent intent = new Intent(MainActivity.this, BeaconService.class);
        intent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
        startService(intent);
        setInfo();
    } else {
        Toast.makeText(this, "service is dead, don't kill again", Toast.LENGTH_SHORT).show();
    }
}

BaseService.class

private void setBeaconManager() {
    beaconManager.setBackgroundBetweenScanPeriod(20l);
    beaconManager.setBackgroundMode(true);
    beaconManager.getBeaconParsers().clear();
    beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(Constants.BEACON_LAYOUT.COMMON_LAYOUT));
}

BeaconService.class

public class BeaconService extends BaseService implements BootstrapNotifier, BeaconConsumer {
private static final int NOTIFICATION = R.string.notify_service_started;
private static final String TAG = "BeaconService";

private int size = -1;

private RegionBootstrap regionBootstrap;

private BackgroundPowerSaver backgroundPowerSaver;

private Beacon beacon;

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

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate");

    regionBootstrap = new RegionBootstrap(this, region);

    beaconManager.bind(this);

    backgroundPowerSaver = new BackgroundPowerSaver(getApplicationContext());
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (intent != null && intent.getAction() != null) {
        switch (intent.getAction()) {
            case Constants.ACTION.STARTFOREGROUND_ACTION:
                startForeground(NOTIFICATION, getNotification());
                break;
            case Constants.ACTION.STOPFOREGROUND_ACTION:
                Log.d(TAG, "Received stop foreground request");
                stopForeground(true);
                stopSelf();
                break;
        }
    }

    return START_STICKY;
}

@Override
public void onDestroy() {
    beaconManager.unbind(this);
    regionBootstrap.disable();
    Log.d(TAG, "service onDestroy");
}

/**
 * Called when at least one beacon in a Region is visible.
 *
 * @param region region
 */
@Override
public void didEnterRegion(Region region) {
    // TODO: 3/8/16 reload all the resource
    Log.d(TAG, "didEnterRegion called");
    L.object(region);
    try {
        beaconManager.startRangingBeaconsInRegion(region);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

/**
 * Called when no beacons in a Region are visible.
 *
 * @param region region
 */
@Override
public void didExitRegion(Region region) {
    // TODO: 3/8/16 close all the resource
    Log.d(TAG, "didExitRegion called");
    try {
        beaconManager.stopRangingBeaconsInRegion(region);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    beaconManager.unbind(this);
    regionBootstrap.disable();
    L.object(region);
}

/**
 * Called with a state value of MonitorNotifier.INSIDE when at least one beacon in a Region is visible
 *
 * @param region region
 */
@Override
public void didDetermineStateForRegion(int i, Region region) {
    Log.d(TAG, "switch from seeing/not seeing beacons");
    L.object(region);
}

@Override
public void onBeaconServiceConnect() {
    Log.d(TAG, "onBeaconServiceConnect");
    if (null == beaconManager.getRangingNotifier()) {
        beaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
                Log.d(TAG, "beacons.size():" + beacons.size() + "," + this);
                if (beacons.size() != 0) {
                    Iterator<Beacon> iterator = beacons.iterator();
                    if (beacons.size() != size) {
                        saveBeacon(iterator);
                        size = beacons.size();
                    }
                }
            }
        });
    }
}

/**
 * Save beacon p-o-j-o to SQLite.
 */
private void saveBeacon(Iterator<Beacon> iterator) {
    while (iterator.hasNext()) {
        beacon = iterator.next();
        L.object(beacon);
        entity.setId(null);
        entity.setUuid(beacon.getId1().toString());
        entity.setMajor(beacon.getId2().toString());
        entity.setMinor(beacon.getId3().toString());
        entity.setTxpower(beacon.getTxPower());
        entity.setTime(Utils.getCurrentTime());

        dbHelper.provideNinjaDao().insert(entity);
        Log.d(TAG, "sql save success");
    }
}

private Notification getNotification() {
    CharSequence text = getText(R.string.notify_service_started);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
    Notification notification = new Notification.Builder(this)
            .setSmallIcon(R.mipmap.ninja_turtle)
            .setTicker(text)
            .setWhen(System.currentTimeMillis())
            .setContentTitle(getText(R.string.info_service))
            .setContentText(text)
            .setContentIntent(contentIntent)
            .build();

    return notification;
}
}

Надеюсь, вы, ребята, можете мне помочь. Заранее спасибо.


person L.Meng    schedule 08.03.2016    source источник
comment
Я очень благодарен за помощь @davidgyoung. Вы можете увидеть его ответ, если столкнетесь с той же проблемой, что и моя: D   -  person L.Meng    schedule 09.03.2016


Ответы (1)


Несколько моментов:

  • Существует два разных набора настроек для периода сканирования с использованием библиотеки Android Beacon: передний план и фон. При использовании BackgroundPowerSaver, как показано в коде, библиотека Android Beacon автоматически переключается между периодом сканирования переднего плана и периодом фонового сканирования.

  • При использовании BackgroundPowerSaver ручная настройка beaconManager.setBackgroundMode(true) будет действовать только до следующего раза, когда приложение переключится на передний план — BackgroundPowerSaver автоматически изменит значение этого параметра.

  • Единицы периодов сканирования — миллисекунды. Таким образом, параметр beaconManager.setBackgroundBetweenScanPeriod(20l); устанавливает период сканирования равным 20 миллисекундам. Это слишком мало, чтобы надежно ловить маяки. Я рекомендую минимальный период сканирования 1100 мс. Чем больше период, тем выше вероятность обнаружения маяка, но тем больше расходуется батарея.

  • Если вы хотите подождать 10 секунд между сканированиями, вы должны установить: beaconManager.setBackgroundBetweenScanPeriod(10000l); // 10000 ms = 10.0 secs

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

 beaconManager.setBackgroundBetweenScanPeriod(10000l);
 beaconManager.setForegroundBetweenScanPeriod(10000l);
 beaconManager.setBackgroundScanPeriod(1100l);
 beaconManager.setForegroundScanPeriod(1100l);
person davidgyoung    schedule 08.03.2016
comment
Большое спасибо @davidgyoung. Ваш метод решил мои проблемы. Но в прошлый раз я установилBackgroundBetweenScanPeriod(20l), как и в BaseService. Период сканирования будет 10 секунд, не могли бы вы сказать мне, почему это было? - person L.Meng; 09.03.2016
comment
Я не могу это объяснить. Я видел это в журналах, но, судя по показанному коду, этого не должно происходить. Возможно ли, что выполняется какой-либо другой код, который не был показан в вопросе? - person davidgyoung; 09.03.2016
comment
Я уже разместил весь код, связанный с работой маяка. Так что я перепроверю свой код и большое спасибо, Дэвид! :D - person L.Meng; 09.03.2016
comment
@davidgyoung, каков период сканирования переднего плана и фона по умолчанию, а также между периодами сканирования? - person imsrgadich; 27.09.2017
comment
период сканирования составляет 10000 мс (10 секунд), а период между сканированиями составляет 300000 мс (5 минут). - person davidgyoung; 27.09.2017