このドキュメントでは、クライアントサイドのジオフェンシングの概要、使用するタイミング、モバイル アプリケーションのユースケースに適用する方法について説明します。また、Google Navigation SDK を使用して Android で例を実装する方法も示します。

企業では、モバイル デバイスが特定のエリアに出入りしたタイミングを把握する必要があることがよくあります。これは、仮想的な地理的境界(ジオフェンス)を維持することで実現されます。ソフトウェアは、デバイスが境界を越えたときにイベントをトリガーできます。
特定の車両が境界を通過したタイミングを把握することは、次のような複数のユースケースで重要です。
- 顧客エンゲージメント: 企業はジオフェンシングを使用して、特別なオファー、イベント、新製品に関するプッシュ通知をエンドユーザーに送信できます。
- セキュリティと安全性: 企業は、ジオフェンシングを使用して、データセンターや倉庫などの機密性の高いエリアの周囲に仮想境界を作成し、エリアに出入りする人がいた場合にセキュリティ担当者にアラートを送信できます。
- 運輸: 企業はジオフェンシングを使用して車両の位置を追跡し、ルートとスケジュールを最適化できます。
そのため、クライアント向けアプリ内でゾーン(ポリゴン)を表現する方法を知っておくことが重要です。このアプリは、デバイスの位置情報を追跡し、特定のジオフェンスを越えたかどうかを確認する必要があります。
範囲
このドキュメントでは、ジオフェンシングのクライアントサイドの実装に焦点を当てます。つまり、クライアント アプリには次のものが必要です。
- 違反がないか確認する必要があるポリゴン。
- ユーザーのリアルタイムの位置情報
- 現在の位置がポリゴンの内側か外側かをチェックするロジック。
このガイドには Android の例が含まれていますが、iOS でも同様の方法で実現できます。Android 位置情報サービスには、円形ジオフェンスの組み込み実装があります。詳しくは、こちらをご覧ください。以下のリファレンス コードと説明は、より複雑な実装の出発点となります。
Navigation SDK
Navigation 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 の依存関係を構成する
このソリューションでは、Google Maps Android API を使用する幅広いアプリケーションで役立つユーティリティを含むオープンソース ライブラリである Android-Maps-Utils を使用します。
このライブラリは一般公開されており、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 にログエントリを生成できます。どちらの場合も、車両の位置情報を取得できます。
バックエンドは、PubSub キューをモニタリングするか、ログを読み取って車両のアップデートを監視します。その後、更新が発生するたびに(または数秒ごと、数分ごと。重要度によって異なります)、バックエンドは BigQuery GIS 関数を呼び出して、特定の車両がジオフェンスの内側にあるか外側にあるかを判断できます。1 つ以上のジオフェンスが違反された場合、バックエンドは内部パイプラインやその他の関連するワークフローをトリガーできます。
まとめ
ジオフェンシングは、さまざまな目的に使用できる強力なツールです。企業はジオフェンシングを使用して、関連性の高い広告やプロモーションでエンドユーザーをターゲットにしたり、位置情報に基づくサービスを提供したり、セキュリティと安全性を強化したりできます。
Navigation SDK には、移動中の重要な瞬間を検出できる便利なイベント リスナーが用意されています。企業は、特定のユースケースでカスタム ジオフェンスを必要とすることがよくあります。このドキュメントでは、これを実現する方法を示しましたが、可能性は無限大です。皆様の作品を楽しみにしております。
次のアクション
- Google Maps Platform でできることの探索、学習、インスピレーションを得るウェビナーをご覧ください。
おすすめの参考資料: