Android 信标区和信标区反复呼叫

Android 信标区和信标区反复呼叫,android,bluetooth-lowenergy,ibeacon-android,altbeacon,android-ibeacon,Android,Bluetooth Lowenergy,Ibeacon Android,Altbeacon,Android Ibeacon,我试图在用户进入定义的区域以及用户退出该区域时通知用户。这就是我到目前为止所做的。我曾经使用rangeNotifier方法(DidBeaApproverAge)在用户进入某个区域时通知用户,但是该方法每1秒就会被调用一次,因此我将通知逻辑移动到monitorNotifier类(didEnterRegion)方法 我的应用程序类扩展了BootStrapNotifier,我将扫描周期设置为2000s,而不是默认的1100l秒,因为我似乎接收到退出和进入通知的速度太快,即使信标在范围内。早些时候,我甚

我试图在用户进入定义的区域以及用户退出该区域时通知用户。这就是我到目前为止所做的。我曾经使用rangeNotifier方法(DidBeaApproverAge)在用户进入某个区域时通知用户,但是该方法每1秒就会被调用一次,因此我将通知逻辑移动到monitorNotifier类(didEnterRegion)方法

我的应用程序类扩展了BootStrapNotifier,我将扫描周期设置为2000s,而不是默认的1100l秒,因为我似乎接收到退出和进入通知的速度太快,即使信标在范围内。早些时候,我甚至将超时时间从10000ms增加到20000ms,当信标没有在超时时间内发出信号时,将触发出口

myapplication类的代码段

BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
    beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(LAYOUT_HERE));
    beaconManager.setForegroundScanPeriod(2000l);
    beaconManager.setBackgroundBetweenScanPeriod(1100l);
    //beaconManager.setBackgroundScanPeriod(5000l);
    beaconManager.setDebug(true);

    Log.d(TAG, "setting up background monitoring for beacons and power saving");
    // wake up the app when a beacon is seen
    mRegion = new Region("myRangingUniqueId",
            null, null, null);
    setRegionAgain();
设置区域增益法

if(SharedPrefs.getString(SharedPrefs.iBEACON_ID, "").trim().length() > 0) {
        if(SharedPrefs.getString(SharedPrefs.iBEACON_ID, "").trim().length() > 0 ) {
            try {
                mRegion = new Region("myRangingUniqueId",
                        Identifier.parse(SharedPrefs.getString(SharedPrefs.iBEACON_ID, "")), 
                        null, null);
            }catch(IllegalArgumentException e) {
                e.printStackTrace();
                mRegion = new Region("myRangingUniqueId",
                        null, null, null);
            }
        }
    }

    regionBootstrap = new RegionBootstrap(this, mRegion);

    // simply constructing this class and holding a reference to it in your custom Application
    // class will automatically cause the BeaconLibrary to save battery whenever the application
    // is not visible.  This reduces bluetooth power usage by about 60%
    backgroundPowerSaver = new BackgroundPowerSaver(this);
我有一个做通知工作的后台服务,所以它实现了BeaconConsumer接口。下面的代码片段:

启动方法:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    flagToCheckExit = false;
    mHandler = new Handler();
    beaconManager.bind(this);
    if (beaconManager.isBound(this)) beaconManager.setBackgroundMode(false);
    return Service.START_STICKY;
}
onDestroy方法:

@Override
public void onDestroy() {
    super.onDestroy();
    try {
        beaconManager.stopMonitoringBeaconsInRegion(CommonUtilities.getRegion());
// this region is the one that i use to monitor (singleton types)
    } catch (RemoteException e) {
        e.printStackTrace();
    }

    beaconManager.unbind(this);
}
OnService连接方法:

@Override
public void onBeaconServiceConnect() {
    beaconManager.setMonitorNotifier(new MonitorNotifier() {

        @Override
        public void didExitRegion(final Region region) {
            LogManager.d(TAG, "didExitRegion %s", region);

            if(SharedPrefs.getString(SharedPrefs.USER_ID, "").trim().length() > 0) {
                flagToCheckExit = true;
// i use this flag to prevent random entry and exit notifications
                mHandler.postDelayed(mRunnable, 20000);
// waiting for 20seconds before firing an exit notification, since an entry notification might get fired immediately after the exit
            }
        }

        @Override
        public void didEnterRegion(Region region) {
            Log.e(TAG,"region id1 >>> " + ((region.getId1() == null) ? "null" : region.getId1().toUuidString()));

            LogManager.d(TAG, "didEnterRegion %s ",region);

            if(!flagToCheckExit) {
                if(SharedPrefs.getString(SharedPrefs.USER_ID, "").trim().length() > 0) {
                    if(region.getId1() != null && 
                            region.getId1().toUuidString().equalsIgnoreCase(SharedPrefs.getString(SharedPrefs.iBEACON_ID, ""))) {
                        if(!SharedPrefs.getBoolean(SharedPrefs.IS_ENTRY_LOG_CALLED, false)) {
                            String entryRange = getAppContext().getString(R.string.entered_beacon_region);
                    CommonUtilities.sendNotification(MonitoringAltBeaconService.this,entryRange,1);
                        }
                    }
                }
            }else {
                // invalidate the handler
                // stop all operations of the handler
                // we do this to prevent an exit getting called since entry has been called immediately.
                mHandler.removeCallbacks(mRunnable);
            }
        }

        @Override
        public void didDetermineStateForRegion(int state, Region region) {
            LogManager.d(TAG, "didDetermineStateForRegion %s ",region);
        }
    });

    startMonitoring();
}
开始监测方法:

private void startMonitoring() {
    try {
        if(SharedPrefs.getString(SharedPrefs.iBEACON_ID, "").trim().length() > 0 ) {
            try {
                beaconManager.startMonitoringBeaconsInRegion(CommonUtilities.getRegion());
            }catch(IllegalArgumentException e) {
                e.printStackTrace();

                beaconManager.startMonitoringBeaconsInRegion(CommonUtilities.getRegion());
            }
        }
    } catch (RemoteException e) {   }
}
可运行线程:

Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        SharedPrefs.putBoolean(SharedPrefs.IS_ENTRY_LOG_CALLED, false);
        SharedPrefs.putBoolean(SharedPrefs.IS_EXIT_LOG_CALLED, true);

        String exitedRange = getAppContext().getString(R.string.exited_beacon_region);
        CommonUtilities.sendNotification(MonitoringAltBeaconService.this,exitedRange,2);
        LogManager.d(TAG, "exit called");
        flagToCheckExit = false;
    }
};
这有一个奇怪的行为,有多个进入和退出日志,即使信标设备在范围内,我也会得到退出。我试着绕过退出通知,但是上面的逻辑(补丁)似乎失败了

日志:

我用的是AprilBeacon。我正在使用的应用程序被挂起,因为信标无法正确生成通知。请帮忙

编辑:

我使用的设备如果Motorolla g2,这种情况在kitkat和棒棒糖版本中都会发生。而且Wifi是开着的,我更喜欢它是开着的,因为在确定入口和出口时,会涉及到网络服务呼叫。实时,不鼓励要求用户关闭wifi:(

我使用的是android信标库,我不知道四月信标发出信号的频率

编辑2:

可以找到日志1

可以找到日志2

编辑3

我注意到,即使信标在射程内,我也有一个出口 我打开了定位应用程序,它显示没有信标(见屏幕截图)。我取出电池并将其放回,它得到了信标,我的应用程序也是如此。(但在现实生活中,我相信电池不会被篡改)


您的配置似乎有效,但存在一个小缺陷。您应该设置两个前台扫描配置:

beaconManager.setForegroundScanPeriod(2000l);
beaconManager.setForegroundBetweenScanPeriod(1100l);
//Update default time with the new one
beaconManager.updateScanPeriods();
beaconManager.setBackgroundScanPeriod(2000l);
beaconManager.setBackgroundBetweenScanPeriod(1100l);
//Update default time with the new one
beaconManager.updateScanPeriods();
或/和后台扫描配置:

beaconManager.setForegroundScanPeriod(2000l);
beaconManager.setForegroundBetweenScanPeriod(1100l);
//Update default time with the new one
beaconManager.updateScanPeriods();
beaconManager.setBackgroundScanPeriod(2000l);
beaconManager.setBackgroundBetweenScanPeriod(1100l);
//Update default time with the new one
beaconManager.updateScanPeriods();
另外,你们知道信标的广告频率吗?你们说过你们已经将扫描周期增加到20秒,并没有任何改变,静止频率将有助于我们帮助你们

顺便说一句,你还可以分享AltBeacon的logcat输出吗?还有,你的设备和型号是什么?它运行的是哪个Android版本?你使用的是哪个AltBeacon库版本

如果您的设备正在运行棒棒糖,请尝试以下命令,并与我们共享结果:

BeaconManager.setAndroidLScanningDisabled(true);
此外,如果WiFi打开,请尝试打开WiFi,因为在某些设备中,它会干扰蓝牙扫描


顺便说一句,很抱歉,这更像是一个评论而不是一个答案,但它也渴望一个评论:)。

编辑:在查看日志后,我提交了一个不同的答案,更好地回答了这个问题。请查看答案。

我从两个发布的日志中注意到,该库报告该应用程序位于后台并使用Android L API。这导致他们使用“低延迟”检测:

03-26 15:47:21.647: D/CycledLeScannerForLollipop(28596): This is Android L. Doing a filtered scan for the background.
低延迟检测可节省电源,但会延迟5秒或更长时间。这适用于后台操作,但不适用于前台操作,应与默认扫描间隔一起使用。在使用这些ANDROID L API时,千万不要将扫描间隔设置为非零,否则可能会出现您描述的退出

如果日志误报您的应用程序在后台,则
BackgroundPowerSaver
的设置可能有问题

您还可以尝试禁用AndroidL API,并使用较旧的4.x扫描API,看看这是否更适合您的用例。如果您这样做,我还将删除任何特殊的扫描间隔设置,以免使您的配置过于复杂:

beaconManager.setAndroidLScanningDisabled(true)

在执行任何其他信标处理之前,您需要将该行放入应用程序类的
onCreate

问题是不经常出现的广告信标和自定义背景扫描间隔太短的组合

看来,信标每2秒只发布一次广告,因为这是我在日志中看到的最接近的两个后续检测时间戳。这是因为低传输频率是有问题的,并且由于自定义设置而加剧

为使库正常运行,背景扫描周期必须至少为信标传输周期的5倍。这是因为并非所有蓝牙数据包都是由于无线电噪声而被接收到的。间隔为传输周期的5倍意味着在每个后台扫描周期中有5次机会接收数据包,这使得库不太可能错过一次

默认的库设置将背景扫描周期设置为10秒,这应该足以提供非常高的概率,即使信标每2秒仅发送一次,并且使不正确的区域退出非常非常罕见

建议:

  • 将背景扫描时间至少更改为默认的10秒。为了节省电池,扫描间隔时间可能也应该更长——默认的5分钟是一个合理的选择,除非您有一个好的理由