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