位置情報の設定を変更する

位置情報をリクエストしたり、パーミッションの更新を受信したりする必要があるアプリの場合、デバイス側で、該当のシステム設定(GPS や Wi-Fi スキャンなど)を有効にする必要があります。アプリは、デバイスの GPS などのサービスを直接有効にするのではなく、必要なレベルの精度や消費電力、希望する更新間隔を指定します。それに基づいて、デバイスは、システム設定に対する適切な変更を自動的に行います。この設定は、LocationRequest データ オブジェクトによって定義されます。

このレッスンでは、SettingsClient を使用して、どの設定が有効になっているかチェックする方法について説明します。また、[位置情報の設定] ダイアログで 1 回のタップで設定を更新できるようにする仕組みについても説明します。

位置情報サービスを設定する

Google Play 開発者サービスと融合型位置予測プロバイダによって提供される位置情報サービスを使用するには、SettingsClient を使用してアプリを接続して、現在の位置情報設定をチェックし、必要に応じて、必須の設定を有効にするようユーザーに求めるプロンプトを表示します。

位置情報サービスを使用するアプリは、位置情報パーミッションをリクエストする必要があります。このレッスンに関しては、概略位置情報の検出で十分です。アプリ マニフェストの uses-permission 要素を使用して、このパーミッションをリクエストします。たとえば、次のようになります。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.google.android.gms.location.sample.locationupdates" >

      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    </manifest>
    

デバイスで Android 6.0 以降が搭載していて、アプリのターゲット SDK が 23 以上の場合、アプリは、マニフェスト内にパーミッションのリストを登録しておいて、実行時に個々のパーミッションをリクエストする必要があります。詳細については、実行時にパーミッションをリクエストするをご覧ください。

Android 10(API レベル 29)以降をターゲットとしているアプリが、バックグラウンドで稼働しているときにデバイス位置情報にアクセスする必要がある場合は、ACCESS_BACKGROUND_LOCATION パーミッションも宣言する必要があります。詳細については、バックグラウンド位置情報へのアクセスをリクエストするをご覧ください。

注: アプリのターゲット SDK バージョンに関係なく、アプリがバックグラウンドで稼働しているときに位置情報にアクセスできるのは、それがアプリの中核的機能にとって重要な場合に限られ、アクセスしていることをユーザーに適切に開示する必要があります。

ほとんどの位置情報ベース ユースケースは、アプリがユーザーに明示されている間(フォアグラウンド サービスにいる間)に実現できます。このようなコンテキスト内で位置情報をリクエストすることにより、優れた透明性と管理性をユーザーに提供することができます。

位置情報リクエストをセットアップする

融合型位置予測プロバイダへのリクエスト用のパラメータを格納するために、LocationRequest を作成します。このパラメータは、位置情報リクエストの精度レベルを指定します。利用可能なすべての位置情報リクエスト オプションについては、LocationRequest クラス リファレンスをご覧ください。このレッスンでは、以下に示すように、更新間隔、最短更新間隔、優先度を設定します。

更新間隔
setInterval() - このメソッドは、アプリが位置情報の更新データを受信する頻度をミリ秒単位で設定します。実際の位置情報の更新間隔は、バッテリー使用量の最適化のために、ここで設定した更新間隔とは多少異なる場合があります。また、まったく更新されないこともあります(デバイスが接続されていない場合など)。
最短更新間隔
setFastestInterval() - このメソッドは、アプリが位置情報の更新データを処理する最短の間隔をミリ秒単位で設定します。setInterval() で指定した間隔よりも短い間隔で更新データを受信するメリットがない限り、このメソッドを呼び出す必要はありません。
優先度

setPriority() - このメソッドは、リクエストの優先度を設定します。この情報は、Google Play 開発者サービスの位置情報サービスにとって、使用する位置情報ソースを判断する際の大きなヒントになります。サポートされる値は次のとおりです。

  • PRIORITY_BALANCED_POWER_ACCURACY - 都市ブロックの範囲内の位置情報の精度(約 100 メートルの精度)をリクエストするには、この設定を使用します。この設定は、概略レベルの精度と見なされ、消費電力を低減できる可能性があります。この設定を使用すると、位置情報サービスにおいて Wi-Fi と基地局による位置決めが使用される可能性があります。ただし、位置情報プロバイダの選択は、他のさまざまな要素(利用可能なソースなど)によって変わります。
  • PRIORITY_HIGH_ACCURACY - 可能な限り最も高精度の位置情報をリクエストするには、この設定を使用します。この設定を使用すると、位置情報サービスは、GPS を使用して位置情報を判断する可能性が高くなります。
  • PRIORITY_LOW_POWER - 都市レベルの精度(約 10 キロメートルの精度)をリクエストするには、この設定を使用します。この設定は、概略レベルの精度と見なされ、消費電力を低減できる可能性があります。
  • PRIORITY_NO_POWER - 消費電力への影響を抑える必要があるものの、位置情報の更新データが利用可能なときには受信したい場合は、この設定を使用します。この設定を使用すると、アプリは、位置情報の更新をトリガーしませんが、他のアプリがトリガーした位置情報の更新は受信します。

次のコードサンプルに示すように、位置情報リクエストを作成してパラメータを設定します。

Kotlin

    fun createLocationRequest() {
        val locationRequest = LocationRequest.create()?.apply {
            interval = 10000
            fastestInterval = 5000
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
    }
    

Java

    protected void createLocationRequest() {
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(10000);
        locationRequest.setFastestInterval(5000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }
    

PRIORITY_HIGH_ACCURACY の優先度、アプリ マニフェスト内で定義した ACCESS_FINE_LOCATION パーミッション設定、ならびに 5000 ミリ秒(5 秒)という短い更新間隔が組み合わさることで、数フィート以内の精度の位置情報更新データが、融合型位置予測プロバイダから返されるようになります。このアプローチは、位置情報をリアルタイムで表示する地図アプリに適しています。

パフォーマンス向上のヒント: アプリがネットワークにアクセスする場合や、アプリが位置情報の更新データを受信した後に時間のかかる別の処理を行う場合は、最短更新間隔を大きい値に変更します。この調整により、アプリが使用できない更新情報を受信しないようにすることができます。実行時間が長い処理が完了したら、最短更新間隔を小さい値に設定し直します。

現在の位置情報設定を取得する

Google Play 開発者サービスと Location Services API に接続すると、ユーザー デバイスの現在の位置情報設定を取得できるようになります。そのためには、LocationSettingsRequest.Builder を作成して、1 つまたは複数の位置情報リクエストを追加します。前のステップで作成した位置情報リクエストを追加する方法を次のコード スニペットに示します。

Kotlin

    val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)
    

Java

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
         .addLocationRequest(locationRequest);
    

次に、現在の位置情報の設定が満たされているかどうかを確認します。

Kotlin

    val builder = LocationSettingsRequest.Builder()

    // ...

    val client: SettingsClient = LocationServices.getSettingsClient(this)
    val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())
    

Java

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();

    // ...

    SettingsClient client = LocationServices.getSettingsClient(this);
    Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
    

Task の完了後、LocationSettingsResponse オブジェクトのステータス コードを確認することで、アプリは位置情報設定をチェックできます。対象の位置情報設定の現在の状態についてさらに詳細な情報を取得するには、LocationSettingsResponse オブジェクトの getLocationSettingsStates() メソッドを呼び出します。

位置情報設定を変更するようユーザーに促す

位置情報設定が位置情報リクエストに適しているか判断するには、位置情報設定を検証する Task オブジェクトに OnFailureListener を追加します。そして、onFailure() メソッドに渡された Exception オブジェクトが、設定の変更が必要であることを示す ResolvableApiException クラスのインスタンスかどうかをチェックします。さらに、startResolutionForResult() を呼び出して、位置情報設定を変更するパーミッションを付与するようユーザーに求めるダイアログを表示します。

ユーザーの位置情報設定が位置情報サービスによる LocationRequest の作成を許可しているか判断する方法と、必要に応じて、位置情報設定を変更するパーミッションを付与するようユーザーに求める方法を、次のコード スニペットに示します。

Kotlin

    task.addOnSuccessListener { locationSettingsResponse ->
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }

    task.addOnFailureListener { exception ->
        if (exception is ResolvableApiException){
            // Location settings are not satisfied, but this can be fixed
            // by showing the user a dialog.
            try {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                exception.startResolutionForResult(this@MainActivity,
                        REQUEST_CHECK_SETTINGS)
            } catch (sendEx: IntentSender.SendIntentException) {
                // Ignore the error.
            }
        }
    }
    

Java

    task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            // All location settings are satisfied. The client can initialize
            // location requests here.
            // ...
        }
    });

    task.addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            if (e instanceof ResolvableApiException) {
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    // Show the dialog by calling startResolutionForResult(),
                    // and check the result in onActivityResult().
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult(MainActivity.this,
                            REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                }
            }
        }
    });
    

次のレッスンの位置情報の更新データを受信するでは、位置情報の更新データを定期的に受信する方法について説明します。