【问题标题】:It takes some minutes to start scanning on background mode (Using AltBeacons)在后台模式下开始扫描需要几分钟(使用 AltBeacons)
【发布时间】:2015-11-23 11:10:43
【问题描述】:

我正在尝试在后台和前台模式下监控信标,方法是仅分配第一个 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) {    }
}

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

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

【问题讨论】:

    标签: android ibeacon-android altbeacon android-ibeacon


    【解决方案1】:

    您说得对,用户使用Android Beacon Library 杀死应用程序后最多需要五分钟才能重新开始扫描。无法配置此间隔,但可以根据您的用例在代码中进行更改。

    了解当您使用任务切换器终止应用程序时,操作系统将停止与该应用程序关联的所有进程,包括库用于扫描信标的后台服务。该库使用两种不同的技术重新启动此扫描服务:

    1. 通过监听电源连接/断开事件。

    2. 如果自上次激活以来已过去五分钟,则使用 AlarmManager 重新启动。

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

    选择五分钟的时间间隔仅仅是因为它是一个合理的时间间隔,可以预期内存不足的情况会被清除。

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

    【讨论】:

    • 非常感谢您的解释!
    【解决方案2】:

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

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

    我是这样做的:

    /**
     * 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");
        }
    }
    

    享受信标。

    【讨论】:

    • 我使用了你的代码。在联想设备中杀死后仍然无法工作
    • 您是否也检查过其他设备?
    • 在其他设备上它运行良好。但对联想设备有什么建议吗?我还检查了我的应用的设置和无法优化电池。
    • 这是特定于设备的问题。您也可以检查设备/电池优化设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    • 1970-01-01
    • 2015-12-13
    • 2018-09-09
    • 2020-05-06
    • 1970-01-01
    • 2013-09-11
    相关资源
    最近更新 更多