このドキュメントでは、クライアント側ジオフェンシングとは何か、いつ使用するのか、モバイル アプリケーションのユースケースにどのように適用するのかについて説明します。また、Google Navigation SDK を使用して Android に例を実装する方法も示します。
企業では、多くの場合、モバイル デバイスが特定のエリアに入ったり出たりしたかどうかを知る必要があります。これは、仮想の地理的境界、つまりジオフェンスを維持することで実現され、デバイスが境界を越えたときにソフトウェアがイベントをトリガーできるようになります。
特定の車両が境界を通過するタイミングを把握することは、次のような複数のユースケースで重要です。
- 顧客エンゲージメント: 企業はジオフェンシングを使用して、特別オファー、イベント、新製品に関するプッシュ通知をエンドユーザーに送信できます。
- セキュリティと安全性: 企業はジオフェンシングを使用して、データセンターや倉庫などの機密エリアの周囲に仮想境界を作成し、誰かがそのエリアに出入りした場合にセキュリティ担当者に警告することができます。
- 交通機関: 企業はジオフェンシングを使用して車両の位置を追跡し、ルートやスケジュールを最適化できます。
そのため、クライアント向けアプリ内でこれらのゾーン(ポリゴン)をどのように表現するかを理解することが重要になります。このアプリはデバイスの位置を追跡し、特定のジオフェンスを侵害したかどうかを確認する必要があります。
範囲
このドキュメントでは、ジオフェンシングのクライアント側の実装に焦点を当てています。つまり、クライアント アプリには次のものが必要です。
- 違反をチェックする必要があるポリゴン。
- ユーザーのリアルタイムの位置情報
- 現在の位置がポリゴンの内側か外側かをチェックするロジック。
このガイドには Android の例が含まれていますが、iOS でも同様の方法で実現できます。Android 位置情報サービスには円形ジオフェンスの実装が組み込まれており、こちらで確認できます。以下の参照コードと説明は、より複雑な実装の開始点となります。
Navigation SDK
ナビゲーション SDK は、ドライバーアプリに追加されるネイティブ Android / iOS ライブラリです。以下の機能を提供します。
- 実行中のアプリから道路にスナップされた位置情報を取得します。これは、Google の道路ネットワークを使用して位置情報を最も近い道路セグメントにスナップし、到着予定時刻をより正確に算出するほか、FLP からの他の情報も使用するため、Android の FusedLocationProvider(FLP)よりも正確です。
- リアルタイムの交通状況やその他のルート制限を考慮して、ドライバーが A 地点から B 地点まで効率的に移動できるターンバイターンのルート案内。
- イベント リスナーと登録されたコールバックを介してイベントを発生させます。
リスナー
Navigation SDK には、使用できるリスナーが多数あります。たとえば
- RoadSnappedLocation プロバイダによる位置情報の変更。
- ReroutingListener を介してイベントを再ルーティングします(ユーザーが U ターンや左折を逃し、推奨ルートから外れた場合など)。
- ArrivalListener を介した到着イベント(ユーザーが予定の目的地に到着)。
- 残り距離と到着予定時刻のイベント(メートル単位で、ドライバーが目的地に到着する直前に通知を受け取る、時間単位で、ドライバーが目的地に到着する直前に通知を受け取る)は、どちらも .RemainingTimeOrDistanceChangedListener で利用できます。
このガイドでは、RoadSnappedLocationProvider とその LocationListener のみが使用されます。
クライアントサイドのジオフェンシング ソリューション
では、クライアントサイドのジオフェンシング機能を構築する手順を見ていきましょう。次の例では、Navigation SDK がターンバイターン モードで動作しており、ルートで定義されたポリゴンがジオフェンスを表しています。
- ジオフェンスは BigQuery に保存され、バックエンドによって取得されます。
- バックエンドは、定期的にジオフェンスをドライブ アプリにプッシュします。
- ドライバーがナビゲーションを行い、ドライバー アプリが定期的にジオフェンスをチェックしてトリガーを探します。
- ドライバー アプリは、トリガー イベントをバックエンドに通知して、バックエンドが対応できるようにします。
車両がルートに沿って移動すると、アプリはポリゴンが侵害されていないかどうかを定期的に確認します。アプリがジオフェンスを越えたことを検出すると、UI に「ジオフェンス違反」というメッセージが表示されます。
Android-Maps-Utils の依存関係を構成する
このソリューションでは、Android-Maps-Utils を使用します。これは、Google Maps Android API を使用する幅広いアプリケーションで役立つユーティリティを含むオープンソース ライブラリです。
このライブラリは一般公開されており、Github でホストされています。次の場所からアクセスできます。
- Android: https://github.com/googlemaps/android-maps-utils
- iOS: https://github.com/googlemaps/google-maps-ios-utils
このライブラリを Android アプリ(このドキュメントの範囲)に含めるには、build.gradle ファイルを変更して含める必要があります。この build.gradle ファイルは、プロジェクト レベルではなく、ビルドするモジュール(アプリ)用です。
dependencies {
...
// Utilities for Maps SDK for Android (requires Google Play Services)
implementation 'com.google.maps.android:android-maps-utils:2.3.0'
}
Gradle を最新の build.gradle ファイルと同期したら、Java ファイルで com.google.maps.android.PolyUtil をインポートできます。
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.maps.android.PolyUtil;
ジオフェンスを定義する
ここでも PolygonOptions がインポートされていることに注意してください。ポリゴンを表すために使用されているのは次のためです。
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
上の図のように、ここでは事前に設定された座標(緯度と経度のペア)を使用して固定ポリゴンを定義しています。ただし、実際のシナリオでは、これらの座標とポリゴンの定義はバックエンド エンドポイントから取得されることが多く、リモートで取得される可能性があります。つまり、アプリがその場でポリゴンを作成する必要があります。
PolygonOptions で指定できる内容について詳しくは、こちらをご覧ください。
ポリゴンは、フラグメントまたはアクティビティの作成時に定義する必要があります。次に例を示します。
protected void onCreate(Bundle savedInstanceState) {
...
mPolygonOptions = new PolygonOptions()
.add(new LatLng(29.4264525,-98.4948758))
.add(new LatLng(29.4267029,-98.4948758))
.add(new LatLng(29.4273742,-98.4945822))
.add(new LatLng(29.4264562,-98.4943592))
.fillColor(0x0000ff36)
.strokePattern(Arrays.asList(new Dash(45.0f), new Gap(10.0f)))
.strokeColor(Color.BLUE)
.strokeWidth(5);
...// more code here
}
位置情報の更新をリッスンする
ジオフェンスを定義したら、位置情報の更新リスナーを作成して、Navigation SDK の RoadSnappedLocationProvider という前述のイベントに登録するだけで、デバイスの最新の位置情報が返されます。
mLocListener = new RoadSnappedLocationProvider.LocationListener() {
@Override
public void onLocationChanged(Location snapped) {
LatLng snappedL = new LatLng(snapped.getLatitude(), snapped.getLongitude());
if(PolyUtil.containsLocation(snappedL, mPolygonOptions.getPoints(), true) && !mGeofenceBreached){
Log.d("Geofence", "Vehicle has breached the polygon");
}
}
@Override
public void onRawLocationUpdate(Location location) {
}
};
Android-Maps-Utils を使用すると、PolyUtil.containsLocation を使用して、受信した位置情報が事前定義されたポリゴン内にあるかどうかを確認できます。以下の例では、ジオフェンスを表す事前定義されたポリゴンが使用されていますが、実際には複数のポリゴンを使用する可能性があり、ループが必要になります。
別の方法
このドキュメントでは、カスタム ジオフェンス(ポリゴン)の違反をチェックするクライアント向けアプリケーションについて説明します。ただし、バックエンドでこのようなチェックを行う必要があるシナリオもあります。
つまり、アプリは位置情報の更新をバックエンドに報告し、バックエンドは車両が特定のポリゴンを侵害したかどうかを確認します。そのため、検証をクライアント アプリに依存する必要はありません。
考えられる解決策は次のとおりです。
[実行環境] サーバーサイドのジオフェンシング アーキテクチャ
ジオフェンシングのサーバーサイド アプローチを示すアーキテクチャの例。
- Driver SDK を使用するドライバー アプリは、位置情報の更新を Fleet Engine に送信します。位置情報の更新とアプリ内ナビゲーションは、Navigation SDK を介して行われます。
- Fleet Engine はこれらの更新を Cloud Logging または Pub/Sub に出力します。
- バックエンドはこれらの位置情報シグナルを収集します。
- ジオフェンスは Big Query に保存され、バックエンドで分析されます。
- ジオフェンスがトリガーされると、アラートがドライバー アプリに送信されます。
このアーキテクチャでは、Driver SDK と Fleet Engine が使用されます。Fleet Engine は、PubSub の更新を発行し、Cloud Logging にログエントリを生成できます。どちらの場合も、車両の位置情報を取得できます。
バックエンドは、Pub/Sub キューをモニタリングするか、ログを読み取って車両の更新を監視します。その後、更新が発生するたびに(または更新の重要度に応じて数秒、数分ごとに)、バックエンドは BigQuery GIS 関数を呼び出して、特定の車両がジオフェンスの内側にあるか外側にあるかを判断できます。1 つ以上のジオフェンスが侵害された場合、バックエンドが動作して、内部パイプラインまたはその他の関連ワークフローをトリガーできます。
まとめ
ジオフェンシングは、さまざまな目的に使用できる強力なツールです。企業はジオフェンシングを使用して、関連性の高い広告やプロモーションをエンドユーザーに配信したり、位置情報に基づくサービスを提供したり、セキュリティと安全性を強化したりできます。
Navigation SDK には、移動中の重要な瞬間を検出できる便利なイベント リスナーが用意されています。企業は、特定のユースケースでカスタム ジオフェンスを必要とすることがよくあります。このドキュメントでは、これを実現する方法を示しましたが、可能性は無限大です。皆様の作品を楽しみにしています。
次のアクション
おすすめの参考資料: