ユーザーが定義された領域に入ったとき、およびユーザーが領域を終了したときに、ユーザーに通知しようとしています。これは私がこれまでに行ったことです。以前は rangeNotifier メソッド (didBeaconsEnterRange) を使用して、ユーザーがリージョンに入ったときにユーザーに通知していましたが、このメソッドが 1 秒ごとに呼び出されるため、通知ロジックを monitorNotifier クラス (didEnterRegion) メソッドに移動しました。
私のアプリケーション クラスは BootStrapNotifier を拡張し、scanPeriod をデフォルトの 1100l 秒ではなく 2000 秒に設定しています。これは、ビーコンが範囲内にある場合でも、終了通知と開始通知を受け取る速度が速すぎるように思われるためです。以前は、ビーコンがタイムアウト期間内にシグナルを発火しなかった場合に終了を発火させるタイムアウト期間を 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 の場合に使用するデバイス。このシナリオは、キットカット バージョンとロリポップ バージョンの両方で発生します。そして、Wifiがオンになっています。エントリの出口が決定されると、Webサービスの呼び出しが関係するため、オンになっていることを好みます。リアルタイム 、ユーザーに Wi-Fi をオフにするように求めることは推奨されません :(..
私が使用しているライブラリは android-beacon-libraryです。残念ながら 4 月のビーコンが信号を送信する頻度がわかりません。
編集2:
ログ1はここにあります
ログ2はここにあります
編集3
Wi-Fi がオフになったときのログ ビーコンが範囲内にある場合でも終了したことに気付きました。また、ロケーター アプリを開いたところ、ビーコンが存在しないことが示されました (スクリーンショットを参照)。バッテリーを取り外して元に戻すと、ビーコンが表示され、アプリもそうでした。(しかし実際には、バッテリーが改ざんされることはないと確信しています)