【问题标题】:Questions about android-beacon-library's scan-period关于android-beacon-library的scan-period的问题
【发布时间】:2016-03-10 18:37:03
【问题描述】:

当我使用android-beacon-library 时,我遇到了关于扫描周期的问题。这是我的问题:

我有三个主要类:MainActivityBaseServiceBeaconService

  • MainActivity:只需进行startForegroundstopForeground 操作即可。
  • BaseService:做一些参数初始化,BeaconManager等等。
  • BeaconService:信标操作。

我先描述我的问题。我正在使用前台服务进行扫描操作,backgroundScanPeriod 为 20l。而且我还有一个带有两个按钮的 MainActivity,startService 和 stopService。当我第一次打开应用程序并单击 startService 时,扫描周期为 10 秒。

然后我单击 HOME 并终止此应用程序,服务运行正常,扫描周期也是 10 秒。但是当我通过单击图片上的通知重新打开MainActivity 时。

扫描周期将变为 1s。对我来说很快。但是如果我再次单击 HOME,扫描周期将变得正常。这意味着,除了我第一次打开 MainActivity 之外,每次扫描周期都会变得非常快。

我想知道为什么。下面是我的重要代码:

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

希望你们能帮助我。提前致谢。

【问题讨论】:

  • 我非常感谢 @davidgyoung 的帮助。如果您遇到与我相同的问题,您可以看到他的答案:D

标签: ibeacon android-bluetooth ibeacon-android altbeacon beacon


【解决方案1】:

几点:

  • 使用 Android 信标库的扫描周期有两组不同的设置,前景和背景。如代码所示使用BackgroundPowerSaver时,Android Beacon Library会自动在前台扫描周期和后台扫描周期之间来回切换。

  • 使用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);

【讨论】:

  • 非常感谢@davidgyoung。你的方法解决了我的问题。但是上次我 setBackgroundBetweenScanPeriod(20l) 就像我在 BaseService 中发布的一样。扫描周期为 10 秒,您能告诉我这是为什么吗?
  • 我无法解释。我确实在日志中看到了这一点,但根据显示的代码,这不应该发生。是否有可能执行了问题中未显示的任何其他代码?
  • 我已经发布了所有与信标操作相关的代码。所以我会重新检查我的代码,非常感谢大卫! :D
  • @davidgyoung 默认的前台和后台扫描周期以及扫描周期之间是什么?
  • 扫描周期为 10000 毫秒(10 秒),扫描周期为 300000 毫秒(5 分钟)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多