我试图在用户输入定义的区域时以及用户退出该区域时通知用户。这就是我到目前为止所做的。我曾经使用rangeNotifier方法(didBeaconsEnterRange)来通知用户他/她进入一个区域,但是这个方法每隔1秒就被调用一次,所以我将通知逻辑移到了monitorNotifier类(didEnterRegion)方法。
我的应用程序类扩展了BootStrapNotifier,我将scanPeriod设置为2000s而不是默认的1100l秒,因为我似乎收到退出和进入通知的方式太快,即使信标在范围内。早些时候我甚至将超时时间从10000毫秒增加到20000毫秒,当信标在超时时间内没有发出信号时,它会触发出口。
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();
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接口。以下代码段:
OnStart方法:
@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);
}
onServiceConnected方法:
@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();
}
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;
}
};
这有一个奇怪的行为,即使信标设备在范围内,也有多个进入和退出日志,我得到了退出。我尝试绕过退出通知但似乎失败了上面的逻辑(补丁)。
日志:
03-19 18:00:25.866: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:25.867: D/MonitoringAltBeaconService(22795): didExitRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:26.470: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:26.477: D/MonitoringAltBeaconService(22795): didEnterRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:48.076: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:48.076: D/MonitoringAltBeaconService(22795): didExitRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:51.275: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:00:51.282: D/MonitoringAltBeaconService(22795): didEnterRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:01:10.269: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:01:10.269: D/MonitoringAltBeaconService(22795): didExitRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:01:15.876: D/MonitoringAltBeaconService(22795): didDetermineStateForRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-19 18:01:15.883: D/MonitoringAltBeaconService(22795): didEnterRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
我正在使用AprilBeacon。我正在处理的应用程序被搁置,因为信标不会正确生成通知。请协助。
修改
我使用的设备如果是Motorolla g2,这种情况同时发生在kitkat和棒棒糖版本中。 Wifi打开,我更喜欢它,因为当确定一个入口退出时,涉及到web服务调用。实时,不鼓励用户切换他们的wifi :( ..
我使用的库是android-beacon-library here,我恐怕不知道4月信标发出信号的频率。
编辑2:
可以找到日志1 here
可以找到日志2 here
编辑3
log when wifi is switched off 我注意到即使灯塔在范围内,我也确实退出了 我打开了定位应用程序,它显示没有信标(见截图)。我取下了电池并将它们放回去了它的灯塔,我的应用也是如此。 (但在现实生活中,我确信电池不会被篡改)
答案 0 :(得分:1)
您的配置似乎有效但有一点缺陷。你应该设置两个前景扫描配置:
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库版本?
如果您的设备正在运行Lollipop请尝试使用以下行,请与我们分享结果:
BeaconManager.setAndroidLScanningDisabled(true);
另外,如果打开了WiFi,请尝试将其打开,因为在某些设备中它会干扰蓝牙扫描。
顺便说一句,对不起,这更像是评论而不是答案,但也是为了评论:。
答案 1 :(得分:1)
问题是不经常广告信标和自定义背景扫描间隔太短的组合。
似乎信标只是每2秒发布一次,因为这是我在日志中看到的最接近的两个检测时间戳。这种低传输频率是有问题的,并且由于自定义设置而加剧。
为了正确操作库,后台扫描周期必须至少是信标传输周期的5倍。这是因为并非由于无线电噪声而接收到所有蓝牙分组。具有传输周期的5倍的间隔意味着在每个后台扫描周期中有5次机会接收分组,使得库不太可能错过一个。
默认库设置将后台扫描周期设置为10秒,这应该足以提供非常高的概率来检测即使每2秒仅发送一次信标,并且非常罕见地使不正确的区域退出。
<强>建议:强>
将后台扫描周期更改为至少10秒的默认值。为了节省电池,中间扫描周期也可能更长 - 默认值为5分钟是合理的选择,除非你有充分的理由缩短它。如果仍然出现退出事件,请使后台扫描周期更长。
使用可以更频繁地投放广告的不同信标。虽然您应该能够使图书馆使用这些信标,但您不会经常获得更新,而定位等应用会定期显示检测中的丢失。如果您在应用中进行距离估计,则需要以10Hz或更高频率传输的信标。如果你的应用程序没有进行距离估算,你仍然应该使用以1Hz或更高频率传输的信标,否则你将更有可能遇到这样的问题。
我怎么知道这是问题?
从下面的日志摘录中可以看出,在15:50:52发生了错误的区域退出,因为自上一次检测以来已经过了10秒。没有检测到的任何10秒周期将在下次扫描周期停止时导致区域退出事件。因此,您必须非常确定扫描周期足以捕获信标传输。使用自定义设置时,在三个后续扫描周期中丢失检测将导致区域退出。
03-26 15:49:49.533: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:49:55.567: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:01.624: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:08.898: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:11.315: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:17.380: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:21.010: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:26.440: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:30.066: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:33.108: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:36.120: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:39.745: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:41.573: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:52.415: D/MonitorState(28596): We are newly outside the region because the lastSeenTime of 1427365241573 was 10841 seconds ago, and that is over the expiration duration of 10000
03-26 15:50:52.415: D/BeaconService(28596): found a monitor that expired: id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
03-26 15:50:52.415: D/Callback(28596): attempting callback via intent: ComponentInfo{com.credencys.mycarline/org.altbeacon.beacon.BeaconIntentProcessor}
03-26 15:50:54.879: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:50:56.705: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:51:00.940: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:51:03.348: D/BeaconService(28596): beacon detected : id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: 1 id3: 7
03-26 15:51:03.349: D/BeaconService(28596): looking for ranging region matches for this beacon
03-26 15:51:03.842: D/CycledLeScanner(28596): Waiting to stop scan cycle for another 1000 milliseconds
03-26 15:51:04.730: D/MonitoringAltBeaconService(28596): didExitRegion id1: cbb7c628-a321-4cf6-934d-37dbfa335735 id2: null id3: null
答案 2 :(得分:0)
编辑:在查看日志后,我提交了一个不同的答案,更好地回答了问题。请看那个答案。
我从两个发布的日志中注意到,该库报告该应用程序处于后台并使用Android L API。这导致他们使用&#34;低延迟&#34;检测:
03-26 15:47:21.647: D/CycledLeScannerForLollipop(28596): This is Android L. Doing a filtered scan for the background.
低延迟检测可节省电量,但会延迟5秒或更长时间。这适用于后台操作,但它不适用于前台操作,应与默认扫描间隔一起使用。 使用这些Andorid L API时,不应在扫描间隔之间设置非零值,否则您可能会像您描述的那样退出。
如果日志误报您的应用是在后台,那么BackgroundPowerSaver
的设置可能有问题。
您也可以尝试禁用Android L API,并使用旧的4.x扫描API查看是否更适合您的用例。如果你这样做,我也会删除任何特殊的扫描间隔设置,以免使配置过于复杂:
beaconManager.setAndroidLScanningDisabled(true)
在进行任何其他信标处理之前,您需要将该行放在应用程序类的onCreate
中。