在后台模式下开始扫描需要几分钟时间(使用 AltBeacons)

It takes some minutes to start scanning on background mode (Using AltBeacons)

我正在尝试通过仅分配第一个 ID 然后获取检测到的信标的完整 UUID,在后台和前台模式下监视信标。

使用 didEnterRegion 方法,该区域的第二个 ID 为空,所以我所做的是在我进入一个区域时开始测距信标以检测哪个是第二个 ID。

public class BeaconListener extends Application implements BootstrapNotifier {
private static final String TAG = "BEACON TEST";
private RegionBootstrap regionBootstrap;
private MonitoringActivity monitoringActivity = null;
private Region mRegion;
private BeaconManager beaconManager;
private String UUID;
public void onCreate() {
    super.onCreate();
    beaconManager = BeaconManager.getInstanceForApplication(this);
    beaconManager.getBeaconParsers().add(new BeaconParser().
            setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
    beaconManager.setBackgroundScanPeriod(1100);
    beaconManager.setBackgroundBetweenScanPeriod(0);
    beaconManager.setAndroidLScanningDisabled(true);

    beaconManager.setBackgroundMode(true);

    mRegion = new Region("Beacon", Identifier.parse("0xffffffffffffffffffff"), null, null);

    regionBootstrap = new RegionBootstrap(this, mRegion);

}

@Override
public void didEnterRegion(Region arg0) {
    // In this example, this class sends a notification to the user whenever a Beacon
    // matching a Region (defined above) are first seen.

    try {
        beaconManager.startRangingBeaconsInRegion(mRegion);
        beaconManager.setRangeNotifier(new RangeNotifier() {
            @Override
            public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region arg0) {
                try {
                    for (Beacon beacon : beacons) {
                          beaconManager.stopRangingBeaconsInRegion(mRegion);
                          sendNotification();
                    }
                } catch (Exception e) {
                    Log.i(TAG, e.getMessage());
                }
            }
        });

        beaconManager.startRangingBeaconsInRegion(mRegion);
        beaconManager.setBackgroundScanPeriod(1100);
        beaconManager.setBackgroundBetweenScanPeriod(0);
        beaconManager.setAndroidLScanningDisabled(true);
    } catch (RemoteException e) {    }
}

这工作正常,我可以获得检测到的 beacon/s 的完整 UUID,但是,当我终止应用程序或将其置于后台模式时,需要几分钟(大约 5 分钟)才能重启监控服务。有没有办法在进入后台或杀死应用程序后立即重新启动服务?当我将设备连接到充电器时,它会重新启动服务并再次快速找到信标。

PS:当我谈论第一个 ID 和第二个 ID 时,我假设 UUID = ID1 + ID2

您是正确的,在用户使用 Android Beacon Library 终止应用程序后最多需要五分钟才能重新开始扫描。无法配置此间隔,但如果适合您的用例,可以在代码中进行更改。

请注意,当您使用任务切换器终止应用程序时,OS 将停止与该应用程序关联的所有进程,包括后台服务,例如库用于扫描信标的服务。图书馆使用两种不同的技术重新启动此扫描服务:

  1. 通过监听 power connect/disconnect 事件。

  2. 通过使用 AlarmManager 在上次活动后五分钟后重新启动。

第二种方法既适用于应用程序因内存不足而被任务切换器终止的情况,也适用于操作系统终止的情况。在后一种情况下,立即重启是不合适的,因为前台应用程序可能需要驱逐其他应用程序才能使用所有系统内存一段时间。 Google 地图应用在平移和缩放时经常会导致此问题。

之所以选择五分钟的时间间隔,是因为这是一个合理的时间间隔,可以清除内存不足的情况。

虽然五分钟默认值在库中不可配置,但由于它是开源的,如果您愿意,您可以编译一个修改版本以将其设置为更短的间隔。要更改的代码是 here。但是请理解,这可能会对占用大量内存的前台应用程序产生负面影响。

在前景、背景、终止状态下检测信标完全没有延迟。

只在Applicationclass中编写代码,不需要后台服务来监控信标。

我这样做过:

/**
 * Created by Hiren Patel on 3/25/2017.
 */
public class MyApplication extends Application implements BootstrapNotifier {

    private BeaconManager iBeaconManager;
    private RegionBootstrap regionBootstrap;


    @Override
    public void onCreate() {
        super.onCreate();

        stopBeaconMonitoring();
        startBeaconMonitoring();

    }

    public void stopBeaconMonitoring() {
        Log.i("Application", "stopBeaconMonitoring");
        if (iBeaconManager != null) {
            iBeaconManager.removeAllMonitorNotifiers();
            iBeaconManager.removeAllRangeNotifiers();
            iBeaconManager = null;
        }
    }

    private void startBeaconMonitoring() {

        iBeaconManager = BeaconManager.getInstanceForApplication(this);
        iBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
        iBeaconManager.setBackgroundBetweenScanPeriod(5000l);
        iBeaconManager.setBackgroundScanPeriod(1000l);
        iBeaconManager.setDebug(true);

        //Start the Services that will keep checking for beacons in the background, even if the application is closed (swiped away from the app-switcher).
        Intent startServiceIntent = new Intent(this.getApplicationContext(), BeaconService.class);
        this.getApplicationContext().startService(startServiceIntent);
        startServiceIntent = new Intent(this.getApplicationContext(), BeaconIntentProcessor.class);
        this.getApplicationContext().startService(startServiceIntent);

        List<BeaconEntity> beaconEntityList = YourBeaconListHere;
        if (beaconEntityList != null) {
            for (BeaconEntity beaconEntity : beaconEntityList) {
                Region region = new Region(beaconEntity.Name, Identifier.parse(beaconEntity.UUID), Identifier.parse(String.valueOf(beaconEntity.Major)), Identifier.parse(String.valueOf(beaconEntity.Minor)));
                regionBootstrap = new RegionBootstrap(this, region);
                Log.i("Beacons List", beaconEntity.Name + "-" + beaconEntity.UUID + "-" + String.valueOf(beaconEntity.Major) + "-" + String.valueOf(beaconEntity.Minor));
            }
        }else{
            Log.i("Beacons List", "null");
        }
    }

    @Override
    public void didEnterRegion(Region region) {
        // You entered in Region(beacon range)
        Log.i("Application", "didEnterRegion called");
    }

    @Override
    public void didExitRegion(Region region) {
        // You exited from Region(beacon range)
        Log.i("Application", "didExitRegion called");
    }

    @Override
    public void didDetermineStateForRegion(int i, Region region) {
        // Region state changed, just ignore it
        Log.i("Application", "didDetermineStateForRegion called");
    }
}

享受信标。