我在 Android 应用程序中使用 AltBeacon 库。
我实现了一个活动,然后是示例,可以检测到信标并成功触发 didEnterRegion。前任
公共类 MonitoringActivity 扩展 Activity 实现 BeaconConsumer {
然后我实现了一个后台应用程序,可以在后台检测信标并触发 didEnterRegion。前任
公共类 BackgroundApplication 扩展应用程序实现 BootstrapNotifier {
但是当我尝试将它们组合在一起时,它不起作用。
我想要做的是:调用 MonitoringActivity 从 BackgroundApplication didEnterRegion() 调用中启动 beaconManager.startMonitoringBeaconsInRegion。
这个想法是:
BackgroundApplication 监视特定的 uuid + major:null + minor:null。当它检测到时,启动实现 beaconConsumer 的活动,并监视具有特定主要和次要 ID 的小型特定区域并执行相关操作,例如通过特定主要/次要 ID 从云中查询数据。
我的测试告诉我:
当我有“regionBootstrap = new RegionBootstrap(this, regionList);” 在 BackgroundApplication onCreate() 中,即使信标在做广告,MonitoringActivity 也不会显示任何内容。删除 regionBootStrap 寄存器后,MonitoringActivity 正确显示信标。
在以前的情况下,使 MonitoringActivity 正确显示信标的另一种方法是:暂停应用程序(转到后台)并再次恢复它(回到前台),然后 MonitoringActivity didEnterRegion 正确触发。
我尝试将 regionBootstrap 寄存器从应用程序启动时间推迟到以后,例如 MonitoringActivity onPause()。在这种情况下,应用启动后,MonitoringActivity 会正确显示信标。当我将它暂停到后台时,调用的 startBeaconMonitoring() 会执行 regionBootstrap 注册。但在这种情况下,后台任务无法检测到信标 didEnterRegion。
我猜这是由 BackgroundApplication 中的一个 beaconManager 和 MonitoringActivity 中的另一个 beaconManager 引起的,它们存在冲突,但我不确定。
这是我的 AndroidManifest.xml
<application
android:name="com.abc.BackgroundApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:launchMode="singleInstance"
android:name="com.abc.MonitoringActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
现在我的临时解决方案又回到了一般用法: 1. 让 monitorActivity 像正常活动一样干净,没有信标监控活动。2.让backgroundApplication在后台监控具有特定uuid/major/minorId的区域。进入区域后,调用并传递major/minorId 到monitorActivity 并执行相关操作。
但是这样一来,我需要在 backgroundApplication 中预先配置所有特定的 uuid/major/minorId 用于区域回调。
我想在 backgroundApplication 中监视一个简单的特定 uuid 和 null major/minorId 区域,并让 monitorActivity 处理不同 major/minorId 的不同区域情况。可能吗?
例如,创建并监控一个区域 xxx/null/null,当 didEnterRegion 被触发时,我们可以得到它是由哪个 major/minorId 触发的。现在我从区域获得的主要/次要 ID 是 null/null,这与我创建的相同。
任何评论表示赞赏。
更新:这是我的第一个想法,与大卫的建议相同。但正如我提到的,MonitorActivity onBeaconServiceConnect 被调用,但 didEnterRegion 不会被回调。但是在 II 将其暂停到后台并再次将其恢复到前台后,didEnterRegion 被正确调用。这就是为什么我试图征求一些建议。
在后台应用程序中:
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "App started up");
BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
//set scan frequency
beaconManager.setBackgroundBetweenScanPeriod(5000);
// wake up the app when any beacon is seen (you can specify specific id filers in the parameters below)
String uuid1 = "e37ba058-c5bd-40f0-b71d-xxxxxxxxxxxx";
Identifier id1 = Identifier.parse(uuid1);
Region region1 = new Region("com.abc.beaconRegion1", id1, null, null);
ArrayList regionList = new ArrayList<Region>();
regionList.add(region1);
regionBootstrap = new RegionBootstrap(this, regionList);
}
@Override
public void didEnterRegion(org.altbeacon.beacon.Region region) {
Log.i(TAG, "Got a didEnterRegion call");
Intent intent = new Intent(this, MonitoringActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
在 MonitorActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitor);
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.bind(this);
//set table layout view
msgList = (TableLayout)findViewById(R.id.msgList);
msgList.setStretchAllColumns(true);
}
@Override
public void onBeaconServiceConnect() {
beaconManager.setMonitorNotifier(new MonitorNotifier() {
@Override
public void didEnterRegion(Region region) {
Log.i(TAG,"didEnterREgion");
if(region.getId1() == null || region.getId2() == null || region.getId3() == null) {
return;
}
Log.i(TAG, "I just saw an beacon for the first time!");
uuid = region.getId1().toString();
majorId = region.getId2().toInt();
minorId = region.getId3().toInt();
}
@Override
public void didExitRegion(Region region) {
}
@Override
public void didDetermineStateForRegion(int state, Region region) {
}
});
try {
String uuid = "e37ba058-c5bd-40f0-b71d-xxxxxxxxxxxx";
Identifier uuidId1 = Identifier.parse(uuid);
Identifier majorId1 = Identifier.fromInt(21617);
Identifier minorId1 = Identifier.fromInt(515);
Identifier minorId2 = Identifier.fromInt(545);
Region region1 = new Region("com.abc.beaconRegion1", uuidId1, majorId1, minorId1);
beaconManager.startMonitoringBeaconsInRegion(region1);
Region region2 = new Region("com.abc.beaconRegion2", uuidId2, majorId1, minorId2);
beaconManager.startMonitoringBeaconsInRegion(region2);
Log.i(TAG,"beaconManager start monitor beacons in region");
} catch (RemoteException e) {
Log.e("log_tag", e.toString());
}
}