Geofencingに関して調べたメモ

はじめに

id:sakura_bird1 さんに言及されていたGeofensingに関して調べて見た挙動メモ

試した環境は

状況的な記載

プッシュ通知 (Android) : 位置情報連動配信 | ニフティクラウド mobile backend

あたり参考にしてみているんですが、

  • 登録している PendingIntentが中々着火しない
  • GeofencingEventの値が微妙
    • getTriggeringLocation が nullでくることが多
    • getGeofenceTransition の値が正常に取得できない

一応 id:okazuki さんのサイトに言及がある FakeGPSアプリ*1 を入れて入れて検証した感じだと

  • イベントは着火するようになるが
    • getTriggeringLocation が null
    • //★を通過してしまう。。
GeofencingEvent e = GeofencingEvent.fromIntent(intent);
if (e == null || e.hasError()){
   //エラー処理
   return;
} 

//====ココまでは通過====

int result = e.getGeofenceTransition();
Location location = e.getTriggeringLocation();


if(result==Geofence.GEOFENCE_TRANSITION_ENTER){

}
else if (result == Geofence.GEOFENCE_TRANSITION_EXIT){

}
else if(result == Geofence.GEOFENCE_TRANSITION_DWELL){

}
else{
   //★
}

結論として

  • イベント着火自体はGeofence APIまかせにする

  • Intent.putExtra でGeofence対象のデータを送る

    • ただこの手のデータ1MBを超えるとPraceable型でも unmarshalling エラーが出るので
    • idだけ渡して、PendingIntentのトリガー先でRealm等からデータを引っ張ってきたほうが良いかも

  • Location.distanceBetween で現在座標と対象座標より距離を計算
    • 計算距離が範囲内かどうか判定

あたりの処理になってしまうかと


 Geofencingの制限/気づいたこと

登録処理自体

  • ログを見る限り、GeoLookout.apk というシステムapkでうごかしている
  • 登録されたGeofenceIdが順次実行される
    • 量が増えるとやはりPendingIntentのレスポンス挙動は微妙になるようだ
  • テスト時に増えてしまったId登録
    • ココらへんの出力ログのIdを removeGeofences Api に投げてやる必要があり
    • 対象Googleアプリのデータ消去みたいな仕組みはないんだろうか??

イベントトリガー

公式記載の

setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
            Geofence.GEOFENCE_TRANSITION_EXIT)

はPendingIntentのイベントが着火しづらいよう

setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
            Geofence.GEOFENCE_TRANSITION_DWELL)

のほうが反応しやすい気がする

  • PendingIntentイベント自体は、
    • しばらく来なかったり
    • まとめでドバっと連続できたり

な挙動。これはAlarmManagerあたりでも起きている気がするので

G様のPendingIntentのタスク管理が微妙なだけの気もする*2

登録個数

  • Androidだと、端末内の アプリ単位で100個までらしい
    • ただログに出力されるIdが多いと、イベント反応は微妙になりそう
  • iOSだと端末内の アプリ単位で20個までらしい

フェンスの大きさ

  • Androidだと、半径100mが最小値?
    • 10mぐらいにしていしていても、100mぐらいの座標をFakeGpsで座標設定するとイベント反応してしまう
    • PRIORITY_BALANCED_POWER_ACCURACY 辺りの精度で取っている位置情報を使っているからという話も?*3
  • iOSだと半径10mでも可能らしいが。。

登録するGeofenceIdに関して

  • 日本語でもOK
    • 内部ではエンコードされて登録されるよう*4
    • 検証した限りはIdの長さに制限はないようだ
  • setExpirationDuration(Geofence.NEVER_EXPIRE) を指定してしまうとremoveGeofences するまでずっと残ってしまう
    • removeする処理を入れていても、setRequestId が残ってしまう

*1:なんかFakeGPSで ググるpokemon-go の座標偽装の記事がすごく引っかかるw

*2:ある程度の間隔を開ければ問題はないが。。

*3:GooglePlay開発者サービスがロケーション履歴等を作るときの精度がコレくらいなのかもしれない。。

*4:GeoLookout.apkのログを見る限り