証明済み簡単登録の実装ガイド

概要

ウェブ iOS API

Google Maps Platform は、ウェブ(JS、TS)、Android、iOS で使用できます。Google Maps Platform では、場所、ルート、距離に関する情報を取得するためのウェブサービス用 API も提供されています。このガイドのサンプルでは、1 つのプラットフォームが使用されています。他のプラットフォームでの実装方法については、ドキュメントのリンクからご確認ください。

作成を開始

Google Cloud Console の Quick Builder では、JavaScript コードを生成するインタラクティブな UI を使って、住所フォームのオートコンプリート機能を構築できます。

現代のユーザーは、利便性、スピード、セキュリティが最低要件のデジタルの世界で生活し、仕事をすることに慣れています。クレジット カードや銀行口座、ローンなどの手続きを行う際は、すばやく簡単に済ませたいと考えています。

ユーザーが同じデータを何度も入力する必要があるような状態では、その分顧客維持率は低下します。すばやく簡単に登録手続きを済ませられるようになっていれば、ユーザー エクスペリエンスが向上し、サイトのアクセス数を維持できるようになります。

住所を手動で入力する形式では、コンバージョンが減ったり、CRM データに誤りが生じたり、コストのかかる配送ミスが生じたりする恐れがあります。証明済み簡単登録を導入すると、登録手続きを高速化できます。タップ数回で候補となる住所が瞬時に表示され、入力された住所を視覚的に確認することもできるので、ユーザーが正しい住所を入力する助けになります。また、ユーザーの現在地を使用してその住所を確認するため、不正行為を防止し、商品やサービスに対するユーザーの信頼度を高めることもできます。ネット銀行やクレジット カードにも、迅速かつ安全に対応できます。

この実装ガイドでは、Google Maps Platform で証明済み簡単登録を導入する方法を解説します。ユーザーはモバイル デバイスで登録する可能性が高いため、このページの実装例のほとんどは Android を対象としています(詳細はサンプルのソースデータをご覧ください)。iOS SDK でも同様の実装が可能です。

次の図には、このソリューションの構築に関連する主要 API がまとめられています(クリックして拡大)。

API の有効化

上記のソリューションを実装するには、次の API を Google Cloud Console で有効にします。

設定について詳しくは、Google Maps Platform スタートガイドをご確認ください。

ベスト プラクティスのセクション

以下は、このページで取り上げるベスト プラクティスとカスタマイズです。

  • チェックマーク アイコンの項目は、主なベスト プラクティスです。
  • スターアイコンの項目は、ソリューションを強化するもので、省略可能ですがおすすめのカスタマイズです。
入力フィールドにオートコンプリート機能を設定する 住所フォームがオートコンプリートされます。入力途中に予測が行われる機能をすべてのプラットフォームで設定し、最小限のキー操作で正確に住所を入力できるようにすることで、ユーザー エクスペリエンスが向上します。
住所を視覚的に確認できるようにする ユーザーが、入力した住所を地図上で視覚的に確認できるようにします。
ユーザーが入力した住所とデバイスの位置情報を比較する ユーザーが選択または入力した住所を、現在のデバイスの位置情報と比較することで、指定された住所にユーザーがいるか確認できます(これを行うためには、ユーザーは登録時に自宅にいる必要があります)。
証明済み簡単登録を強化するためのヒント オートコンプリート ウィジェットのデザインをカスタマイズしたり、ユーザーが会社やランドマークの名前を住所として選択できるようにするなどの機能を追加して、住所入力の利便性をさらに高めることができます。

入力フィールドにオートコンプリート機能を設定する

この例で使用する API または SDK: Places SDK for Android その他: iOS | JavaScript

プレイス オートコンプリートを使うとアプリケーションでの住所入力がシンプルになり、利用者の購入手続きがスムーズになるため、コンバージョン率が向上します。オートコンプリートの「予測入力」機能により、単一の入力フィールドに住所予測がすばやく入力されるため、登録フォームに自動的に住所を入力できます。オートコンプリート フローにプレイス オートコンプリートを組み込むことで、次のようなメリットが得られます。

  • 住所の入力ミスが減る
  • 登録プロセスの手順が減る
  • モバイル デバイスとウェアラブル デバイスでの住所入力が簡単になる
  • キー入力と登録にかかる合計時間を大幅に削減できる

ユーザーがオートコンプリート入力ボックスを選択して入力を始めると、住所の予測リストが表示されます。

ユーザーが予測リストから住所を選択すると、そのレスポンスを使って住所の検証と位置情報の取得が行われ、以下の図のように、住所が住所入力フォームの各フィールドに適切に自動入力されます。

動画: プレイス オートコンプリートで住所フォームを強化

住所フォーム

Android

iOS

ウェブ

Google Maps Platform では、モバイル プラットフォームとウェブ用のプレイス オートコンプリート ウィジェットを利用できます。上の図のウィジェットには、組み込みのオートコンプリート機能を備えた検索ダイアログが表示されています。このダイアログをさらに最適化し、特定の地域に絞った検索機能を提供することもできます。

このセクションでは、証明済み簡単登録用にプレイス オートコンプリートを実装する方法を説明します。

プレイス オートコンプリート ウィジェットを追加する

Android では、オートコンプリート インテントを使用して、オートコンプリート ウィジェットを追加できます。ユーザーが住所 1 の入力フィールドで入力を開始したときに、プレイス オートコンプリートを起動するウィジェットです。ユーザーは入力を開始すると、オートコンプリートの予測リストから住所を選択できます。

まず、ActivityResultLauncher を使用して、開始されたアクティビティの結果をリッスンするアクティビティ ランチャーを作成します。結果のコールバックには、ユーザーがオートコンプリートの予測リストから選択した住所に対応するプレイス オブジェクトが含まれます。

    private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            (ActivityResultCallback<ActivityResult>) result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent intent = result.getData();
                    if (intent != null) {
                        Place place = Autocomplete.getPlaceFromIntent(intent);

                        // Write a method to read the address components from the Place
                        // and populate the form with the address components
                        Log.d(TAG, "Place: " + place.getAddressComponents());
                        fillInAddress(place);
                    }
                } else if (result.getResultCode() == Activity.RESULT_CANCELED) {
                    // The user canceled the operation.
                    Log.i(TAG, "User canceled autocomplete");
                }
            });

次に、プレイス オートコンプリート インテントのフィールド、位置情報、タイプのプロパティを定義し、Autocomplete.IntentBuilder を使用してビルドします。最後に、前述のコードサンプルで定義されている ActivityResultLauncher を使用して、インテントを起動します。

    private void startAutocompleteIntent() {

        // Set the fields to specify which types of place data to
        // return after the user has made a selection.
        List<Place.Field> fields = Arrays.asList(Place.Field.ADDRESS_COMPONENTS,
                Place.Field.LAT_LNG, Place.Field.VIEWPORT);

        // Build the autocomplete intent with field, country, and type filters applied
        Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields)
                .setCountry("US")
                .setTypeFilter(TypeFilter.ADDRESS)
                .build(this);
        startAutocomplete.launch(intent);
    }

プレイス オートコンプリートから返される住所を処理する

前述の ActivityResultLauncher の定義により、コールバックでアクティビティの結果が返されたときに行う処理も定義されます。ユーザーが予測を選択すると、結果オブジェクトに含まれるインテントで提供されます。インテントは Autocomplete.IntentBuilder によってビルドされているため、Autocomplete.getPlaceFromIntent() メソッドによってプレイス オブジェクトを抽出できます。

    private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            (ActivityResultCallback<ActivityResult>) result -> {
                if (result.getResultCode() == Activity.RESULT_OK) {
                    Intent intent = result.getData();
                    if (intent != null) {
                        Place place = Autocomplete.getPlaceFromIntent(intent);

                        // Write a method to read the address components from the Place
                        // and populate the form with the address components
                        Log.d(TAG, "Place: " + place.getAddressComponents());
                        fillInAddress(place);
                    }
                } else if (result.getResultCode() == Activity.RESULT_CANCELED) {
                    // The user canceled the operation.
                    Log.i(TAG, "User canceled autocomplete");
                }
            });

その後、Place.getAddressComponents() を呼び出し、各住所コンポーネントを、住所フォーム内の対応する入力フィールドと照合して、ユーザーが選択した場所の値をそのフィールドに入力します。

手動入力された住所ではなく、予測リストの住所データを取得することで、住所の正確性を保つことができます。実際に存在していて、商品を配送できる住所であることが保証されるほか、ユーザーの入力操作を減らすこともできます。

プレイス オートコンプリート実装時のポイント

プレイス オートコンプリートをウィジェット以上の用途で使用できるよう、柔軟な実装を可能にする多くのオプションがあります。各種サービスを組み合わせることで、場所を適切にマッチさせるために必要なものが的確に得られます。

  • 住所フォームでは、types パラメータを address に設定して、完全な住所にのみマッチするように制限します。詳しくは、プレイス オートコンプリート リクエストに対応しているタイプをご確認ください。

  • 世界全体で検索する必要がない場合、適切な制限とバイアスを設定します。特定の場所にマッチをバイアスしたり制限したりするために使用できるさまざまなパラメータがあります。

    • RectangularBounds を使うと、長方形で指定した範囲に地域を制限できます。setLocationRestriction() を使うと、特定の地域の住所だけが返されます。

    • setCountries() を使うと、一定の国々にレスポンスを制限できます。

  • マッチしなかった場合に必要に応じて住所を更新できるよう、フィールドは編集可能にしておきます。プレイス オートコンプリートで返されるほとんどの住所には、マンション、アパート、団地などの棟番号が含まれていません。このサンプルでは、カーソルを住所 2 に移動させ、必要に応じて情報を入力するようユーザーに促すことができます。

住所を視覚的に確認できるようにする

この例で使用する SDK または API: Maps SDK for Android その他: iOS | JavaScript

住所入力支援の一環として、住所を地図上で視覚的に確認できるようにします。これにより、ユーザーは住所が正しいことを確認できます。

次の図は、入力された住所の位置にピンを付けた地図です。

次の例は、Android でマップを追加する基本的な手順に即しています。詳しくはドキュメントをご覧ください。

SupportMapFragment の追加

まず、SupportMapFragment フラグメントをレイアウト XML ファイルに追加します。

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/confirmation_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

次に、フラグメントがまだ存在しない場合は、プログラムによって追加します。

    private void showMap(Place place) {
        coordinates = place.getLatLng();

        // It isn't possible to set a fragment's id programmatically so we set a tag instead and
        // search for it using that.
        mapFragment = (SupportMapFragment)
                getSupportFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);

        // We only create a fragment if it doesn't already exist.
        if (mapFragment == null) {
            mapPanel = ((ViewStub) findViewById(R.id.stub_map)).inflate();
            GoogleMapOptions mapOptions = new GoogleMapOptions();
            mapOptions.mapToolbarEnabled(false);

            // To programmatically add the map, we first create a SupportMapFragment.
            mapFragment = SupportMapFragment.newInstance(mapOptions);

            // Then we add it using a FragmentTransaction.
            getSupportFragmentManager()
                    .beginTransaction()
                    .add(R.id.confirmation_map, mapFragment, MAP_FRAGMENT_TAG)
                    .commit();
            mapFragment.getMapAsync(this);
        } else {
            updateMap(coordinates);
        }
    }

フラグメントに対するハンドルの取得とコールバックの登録

  1. フラグメントに対するハンドルを取得するには、FragmentManager.findFragmentById メソッドを呼び出して、レイアウト ファイルに含まれているフラグメントのリソース ID を渡します。フラグメントを動的に追加している場合は、ハンドルをすでに取得しているため、この手順を省略してください。

  2. getMapAsync メソッドを呼び出して、フラグメントにコールバックを設定します。

フラグメントを静的に追加している場合は、以下の例のようになります。

Java


SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
    .findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

      

Kotlin


val mapFragment = supportFragmentManager
    .findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)

      

スタイル設定と地図へのマーカーの追加

地図の準備ができたら、スタイルを設定し、カメラの中心を設定して、入力された住所の座標にマーカーを追加します。次のコードでは、JSON オブジェクトで定義されたスタイル設定を使用します。または、クラウドベースの地図のスタイル設定で定義されている地図 ID を読み込むこともできます

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;
        try {
            // Customise the styling of the base map using a JSON object defined
            // in a string resource.
            boolean success = map.setMapStyle(
                    MapStyleOptions.loadRawResourceStyle(this, R.raw.style_json));

            if (!success) {
                Log.e(TAG, "Style parsing failed.");
            }
        } catch (Resources.NotFoundException e) {
            Log.e(TAG, "Can't find style. Error: ", e);
        }
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 15f));
        marker = map.addMarker(new MarkerOptions().position(coordinates));
    }

コードサンプル全体を見る)。

地図のコントロールを無効にする

地図コントロール(コンパス、ツールバー、その他の組み込み機能など)を追加せずに位置情報を表示し、地図をシンプルに保つには、不要なコントロールを無効にすることをおすすめします。Android では、ライトモードを有効にして操作を制限することもできます。

ユーザーが入力した住所とデバイスの位置情報を比較する

公共料金の請求書などの文書による住所証明(ユーザーが入力した住所に所在していることの確認)の取得は、ユーザーの所在地が遠隔地、ユーザーが新しい住所に引っ越している、ユーザーが訪れることができる実店舗がないデジタル ビジネス(デジタルバンクなど)を運営しているといった要因があると、難しくなる場合があります。ユーザーの住所をデジタル方式で確認できるようにすると、迅速でスムーズな登録プロセスを実現できます。

特にデジタルの登録プロセスによって住所証明を取得する場合は、セキュリティの確保が最重要です。このセクションでは、登録時のユーザーの所在地が、ユーザーが入力した住所と一致しているかどうかを確認する方法を解説し、そのサンプルを紹介します。

入力された住所をデバイスの位置情報と比較する手順は次のとおりです。

  1. ユーザーが入力した住所を地理座標に変換する
  2. デバイスの位置情報の利用許可をユーザーに求める
  3. 入力された住所からデバイスの場所までの距離を計算する(住所と位置情報が一致したとみなす最大距離を指定する)

次の図は、ユーザーが入力した住所とユーザーの現在地を比較するよう促すプロンプトの例です。

ユーザーが入力した住所を地理座標に変換する

この例で使用する API または SDK: Places SDK for Android その他: iOS | JavaScript | Geocoding API

ユーザーが住所確認に同意したら(前の図の [Verify I'm there now] をタップしたら)、住所と現在地を比較する最初のステップとして、入力された住所を地理座標に変換します。

ユーザーがプレイス オートコンプリートから住所を選択した場合は、プレイス オートコンプリート ウィジェットを追加するで説明されているコード スニペットのように、プレイス オートコンプリートのフィールド リストで Place.Field.LAT_LNG をリクエストしてから、Place.getLatLng() メソッドを呼び出し、選択した住所の地理座標を取得します。

coordinates = place.getLatLng();

ユーザーが住所を手動で入力した場合や、プレイス オートコンプリートによる入力内容を編集した場合は、Android Geocoder サービスまたは Geocoding API を使用して、その住所に一致する座標を検索します。

https://maps.googleapis.com/maps/api/geocode/json?address=1600%20Amphitheatre%2BParkway%2C%20Mountain%20View%2C%20CA%2094043&key=YOUR_API_KEY

Geocoding API の呼び出しは URL エンコードしてください。

URL エンコードのクイック リファレンス: %20 = スペース、%2B = +(プラス)、%2C = ,(カンマ)

デバイスの位置情報の利用許可をユーザーに求める

アプリでユーザーの位置情報を取得するには、位置情報サービスの利用許可をユーザーにリクエストする必要があります。Android 向け位置認識アプリの作成に関するドキュメントのガイダンスに従って、次のフローを実装します。

  • 厳密なレベル(ACCESS_FINE_LOCATION)での 1 回限りの許可として、位置情報の利用許可をリクエストします。

  • ユーザーが位置情報の利用を許可した場合は、ユーザーの位置情報を取得します。

  • ユーザーが位置情報の利用を拒否した場合は、適切に対応します。たとえば、次のようなメッセージを使用します(ユーザーの現在地を保存しない場合のみ)。

    「正確な位置情報の確認を許可していただけない場合、アカウントを有効にするためには、郵送で確認を行っていただく必要があります[OK]」

次の図は、デバイスの位置情報の利用許可をユーザーに求めるためのプロンプトの例です。

位置情報の利用許可を確認するには、ActivityResultLauncher を使用して、開始されたアクティビティの結果をリッスンするアクティビティ ランチャーを作成します。結果のコールバックには、ユーザーが利用を許可したか却下したかを示す文字列が含まれます。

    // Register the permissions callback, which handles the user's response to the
    // system permissions dialog. Save the return value, an instance of
    // ActivityResultLauncher, as an instance variable.
    private final ActivityResultLauncher<String> requestPermissionLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                if (isGranted) {
                    // Since ACCESS_FINE_LOCATION is the only permission in this sample,
                    // run the location comparison task once permission is granted.
                    // Otherwise, check which permission is granted.
                    getAndCompareLocations();
                } else {
                    // Fallback behavior if user denies permission
                    Log.d(TAG, "User denied permission");
                }
            });

次に、アプリにすでに ACCESS_FINE_LOCATION 権限が付与されているかどうかを確認します。付与されていない場合は、前の手順で作成したランチャーを使用して、権限リクエスト アクティビティを起動し、ユーザーに確認します。

    private void checkLocationPermissions() {
        if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            getAndCompareLocations();
        } else {
            requestPermissionLauncher.launch(
                    ACCESS_FINE_LOCATION);
        }
    }

ACCESS_FINE_LOCATION 権限が付与されたら、Fused Location Provider を利用して、デバイスの最後に確認された位置情報を取得し、それを基に LatLng オブジェクトを作成します。

        FusedLocationProviderClient fusedLocationClient =
                LocationServices.getFusedLocationProviderClient(this);

        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, location -> {
                    // Got last known location. In some rare situations this can be null.
                    if (location == null) {
                        return;
                    }

                    deviceLocation = new LatLng(location.getLatitude(), location.getLongitude());
                    // ...
                });
    }

入力された住所からデバイスの場所までの距離を計算する

緯度 / 経度で構成される 2 つの座標(入力された住所とデバイスの位置)間の距離を計算します。オープンソースの Maps SDK for Android ユーティリティ ライブラリに、地球上の 2 地点間の球面距離を計算できる便利なメソッドが用意されています。

まず、アプリの build.gradle ファイルに次の依存関係を追加して、Maps SDK for Android ユーティリティ ライブラリをインストールします。

dependencies {
    implementation 'com.google.maps.android:android-maps-utils:2.3.0'

}

続いて、最後に確認されたデバイスの位置情報を取得してから、アクティビティ ファイルに戻り、半径を定義して、2 つの位置情報が「一致」したとみなす半径をメートル単位で指定します。この半径は、GPS の精度のばらつきと、ユーザーが住所を入力した地点の大きさを考慮し、大きめにしてください。例は次のとおりです。

private static final double acceptableProximity = 150;

次に、ユーティリティ ライブラリのメソッド computeDistanceBetween() を使用して、デバイスの位置とユーザーが入力した住所の位置の間の距離を計算します。その距離が上で定義した半径内に収まっている場合は、2 つの位置が一致しているとみなします

// Use the computeDistanceBetween function in the Maps SDK for Android Utility Library
// to use spherical geometry to compute the distance between two Lat/Lng points.
double distanceInMeters = computeDistanceBetween(deviceLocation, enteredLocation);
if (distanceInMeters <= acceptedProximity) {
    Log.d(TAG, "location matched");
    // TODO: Display UI based on the locations matching
} else {
    Log.d(TAG, "location not matched");
    // TODO: Display UI based on the locations not matching
}

コードサンプル全体を見る)。

住所と位置が一致した場合は、次の図のように、アプリに確認メッセージを表示します。

証明済み簡単登録を強化するためのヒント

ユーザーが企業や店舗、スポットの名前から住所を入力できるようにします。「予測入力」サービスの対象は住所だけではありません。ユーザーにお店やサービスの名前を入力してもらうこともできます。住所と施設名の両方の入力に対応するには、types プロパティをオートコンプリートの定義から削除します。

プレイス オートコンプリートのボックスのデザインをウェブサイトのデザインに合わせてカスタマイズします。プレイス オートコンプリートのデザインを、Google のウィジェットではなく自分のアプリで管理したい場合は、プログラムによるプレイス オートコンプリートを利用して、プレイス オートコンプリート サービスを組み込む UI を強化できます。