このドキュメントでは、クライアントサイド ジオフェンスの概要、使用するタイミング、モバイルアプリのユースケースに適用する方法について説明します。また、Google Navigation SDK を使用して Android でサンプルを実装する方法についても説明します。
多くの場合、企業はモバイル デバイスが特定のエリアに出入りしたときに通知する必要があります。これは、仮想の地理的境界(ジオフェンス)を維持し、デバイスが境界を越えたときにソフトウェアがイベントをトリガーできるようにすることで実現されます。
特定の車両がいつ境界を通るのかを把握することは、次のような複数のユースケースで重要です。
- 顧客エンゲージメント: 企業はジオフェンスを使用して、スペシャル オファー、イベント、新商品に関するプッシュ通知をエンドユーザーに送信できます。
- セキュリティと安全性: 企業はジオフェンスを使用して、データセンターや倉庫などの機密性の高いエリアの周囲に仮想境界を作成し、誰かがそのエリアに出入りした場合にセキュリティ担当者にアラートを送信できます。
- 交通機関: ジオフェンスを使用すると、車両の位置を追跡し、ルートとスケジュールを最適化できます。
したがって、クライアント向けアプリ内でゾーン(ポリゴン)を表現する方法を理解しておくことが重要です。このアプリはデバイスの位置情報を追跡し、特定のジオフェンスに違反しているかどうかを確認する必要があります。
範囲
このドキュメントでは、ジオフェンスのクライアントサイド実装に焦点を当てます。つまり、クライアント アプリには次のものが必要です。
- 侵害の有無をチェックする必要があるポリゴン
- ユーザーのリアルタイムの位置情報
- 現在地がいずれかのポリゴンの内側か外側にあるかを確認するロジック。
このガイドでは Android での例を紹介していますが、iOS でも同様の方法を使用できます。Android 位置情報サービスには、円形のジオフェンスの実装が組み込まれています。詳しくは、こちらをご覧ください。以下のリファレンス コードと説明は、より複雑な実装を行うための出発点となります。
Navigation SDK
Navigation SDK は、ドライバアプリに追加されるネイティブ Android / iOS ライブラリで、以下の処理を行います。
- 実行しているアプリから道路のスナップ位置情報を取得する。Android の FusedLocationProvider(FLP)よりも精度が高くなります。これは、Google の道路ネットワークを使用して、位置を最寄りの道路セグメントにスナップし、ETA やその他の情報を FLP から取得する精度が高いためです。
- ターンバイターン方式のエクスペリエンスにより、ドライバーはリアルタイムの交通状況やその他のルート制限を考慮して、A 地点から B 地点まで効率的に移動できます。
- イベント リスナーと登録済みのコールバックを介したイベントの呼び出し。
リスナー
Navigation SDK には、使用できるリスナーが多数用意されています。たとえば
- RoadSnappedLocation プロバイダ経由での位置情報の変更。
- ReroutingListener を使用してイベントのルートを変更します(ユーザーが U ターンや左折など、推奨ルートから逸脱した場合)。
- ArrivalListener を介した到着イベント(ユーザーが予定された目的地に到着)。
- RemainingTimeOrDistanceChangedListener で利用可能な残りの距離と ETA イベント(ドライバーが目的地に到着する直前に通知を受ける - メーターに基づき、ドライバーが目的地に到着する直前に通知を受ける - 時間に基づく)
このガイドでは、RoadSnappedLocation プロバイダとその LocationListener のみを使用します。
クライアントサイドのジオフェンス ソリューション
次に、クライアント側のジオフェンス機能を構築する手順を見ていきましょう。以下の例では、Navigation SDK がターンバイターン モードで動作し、ジオフェンスを表すルートにポリゴンが定義されています。
- ジオフェンスは BigQuery に保存され、バックエンドによって pull されます。
- バックエンドは定期的にジオフェンスをドライブアプリにプッシュします。
- ドライバーがナビゲーションを行い、ドライバー アプリがジオフェンスのトリガーを定期的にチェックしている。
- ドライバアプリがバックエンドにトリガー イベントを通知し、動作できるようにします。
車両がルート上を移動すると、アプリはポリゴンが侵害されているかどうかを定期的にチェックします。アプリがジオフェンスを越えたことを検出すると、UI に [Geofencerupted] というメッセージが表示されます。
Android-Maps-Utils の依存関係を設定する
このソリューションでは、Android-Maps-Utils を使用します。このオープンソース ライブラリには、Google Maps Android API を使用する幅広いアプリケーションで役立つユーティリティが含まれています。
このライブラリは GitHub で公開およびホストされており、次の URL からアクセスできます。
- 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 ファイルと同期したら、com.google.maps.android.PolyUtil を Java ファイルにインポートできます。
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
}
位置情報の更新をリッスンする
ジオフェンスを定義したら、あとは位置情報の更新リスナーを作成して、デバイスの最新の位置情報を返す前述の RoadSnappedLocationProvider
というイベントを Navigation SDK にサブスクライブするだけです。
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 に出力します。
- バックエンドはこれらの位置情報シグナルを収集します。
- ジオフェンスは、バックエンドによる分析のために BigQuery に保存されます。
- ジオフェンスがトリガーされると、ドライバーアプリにアラートが送信されます。
このアーキテクチャでは、Driver SDK と Fleet Engine を使用します。Fleet Engine は Pub/Sub の更新を出力し、Cloud Logging にログエントリを生成できます。どちらの場合も、車両の位置情報を取得できます。
バックエンドは Pub/Sub キューのモニタリングや、ログの読み取り、車両の更新の監視などを行います。次に、更新が行われるたびに(または、重要度に応じて数秒、数分ごと)、バックエンドは BigQuery GIS 関数を呼び出して、特定の車両がジオフェンスの内側にあるか外側にあるかを判断できます。1 つ以上のジオフェンスが侵害された場合、バックエンドが処理を行い、内部パイプラインやその他の関連ワークフローをトリガーできます。
おわりに
ジオフェンスは、さまざまな目的に使用できる強力なツールです。企業はジオフェンスを使用して、関連性の高い広告やプロモーションでエンドユーザーをターゲットにしたり、位置情報を利用したサービスを提供したり、セキュリティと安全性を高めたりできます。
Navigation SDK には、移動中の多くの重要な瞬間を検出できる便利なイベント リスナーが用意されています。企業は、特定のユースケースのためにカスタムのジオフェンスを必要とすることがよくあります。このドキュメントでは、これを実現する方法について説明しましたが、可能性は無限大です。皆様からのご応募を心よりお待ちしております。
次のアクション
- ウェブセミナー「Google Maps Platform でできることを探り、学び、アイデアを得る」をご覧ください。
関連情報: