位置情報の利用許可をリクエストする

位置情報サービスを使用するアプリは、ユーザーのプライバシーを保護するために、位置情報の利用許可をリクエストする必要があります。

位置情報の利用許可をリクエストする場合は、他の実行時の権限と同じおすすめの方法に従ってください。ただし、位置情報の利用許可には、関連する権限がシステムに複数あるという重要な違いがあります。リクエストする権限とリクエストの方法は、アプリのユースケースにおける位置情報の要件によって異なります。

このページでは、さまざまな種類の位置情報の要件と、それぞれの場合に位置情報の利用許可をリクエストする方法について説明します。

位置情報へのアクセスの種類

各権限は、次の特性の組み合わせで構成されています。

フォアグラウンドでの位置情報

1 回のみ、あるいは指定した期間にわたって位置情報を共有または受信する機能がアプリに含まれている場合には、フォアグラウンドでの位置情報へのアクセスが必要です。以下はその一例です。

  • ナビゲーション アプリで、ターンバイターン方式の経路案内をする機能。
  • メッセージ アプリで、現在地を別のユーザーと共有する機能。

アプリの機能が次のいずれかの状況でデバイスの現在地にアクセスする場合、システムはアプリがフォアグラウンドで位置情報を使用しているとみなします。

  • アプリに属するアクティビティが可視状態にある。
  • アプリがフォアグラウンド サービスを実行している。フォアグラウンド サービスが実行されているとき、システムはユーザーに対して常に通知を表示します。ユーザーがデバイスのホームボタンを押したりディスプレイをオフにしたりしてアプリがバックグラウンドに移動しても、アクセスは継続します。

    また、次のコード スニペットに示すように、フォアグラウンド サービス タイプlocation と宣言することをおすすめします。Android 10(API レベル 29)以降では、このフォアグラウンド サービス タイプを宣言する必要があります。

    <!-- Recommended for Android 9 (API level 28) and lower. -->
    <!-- Required for Android 10 (API level 29) and higher. -->
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        <!-- Any inner elements would go here. -->
    </service>
    

次のスニペットに示すように、アプリが ACCESS_COARSE_LOCATION または ACCESS_FINE_LOCATION のいずれかの権限をリクエストするときに、フォアグラウンドでの位置情報が必要であることを宣言します。

<manifest ... >
  <!-- Always include this permission -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

バックグラウンドでの位置情報

アプリ内の機能が常に他のユーザーと位置情報を共有する場合や、Geofencing API を使用する場合、アプリはバックグラウンドでの位置情報へのアクセスを必要とします。以下はその一例です。

  • 家族間位置情報共有アプリで、家族と位置情報を継続的に共有する機能。
  • IoT アプリで、ユーザーが自宅を離れるとオフになり、帰宅すると再びオンになるようにホームデバイスを設定する機能。

フォアグラウンドでの位置情報のセクションで説明した以外の状況で、アプリがデバイスの現在地にアクセスする場合、システムはアプリがバックグラウンドで位置情報を使用しているとみなします。バックグラウンドでの位置情報の精度は、フォアグラウンドでの位置情報の精度と同じであり、アプリが宣言する位置情報へのアクセスによって異なります。

Android 10(API レベル 29)以降では、実行時にバックグラウンドでの位置情報へのアクセスをリクエストするために、アプリのマニフェストで ACCESS_BACKGROUND_LOCATION 権限を宣言する必要があります。以前のバージョンの Android では、アプリがフォアグラウンドでの位置情報へのアクセスを取得すると、バックグラウンドでの位置情報へのアクセスも自動的に取得します。

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

精度

Android は、次のレベルの位置情報の精度をサポートしています。

おおよそ
デバイスの位置情報の推定値を提供します。この位置情報の推定値が LocationManagerService または FusedLocationProvider から取得されている場合、この推定値の精度は約 3 平方キロメートル(約 1.2 平方マイル)以内になります。ACCESS_FINE_LOCATION 権限ではなく、ACCESS_COARSE_LOCATION 権限を宣言すると、アプリはこの精度の位置情報を取得できます。
正確
デバイスの位置情報の推定値をできる限り正確に提供します。位置情報の推定値が LocationManagerService または FusedLocationProvider から取得されている場合、通常、その推定値の精度は約 50 メートル(160 フィート)以内になります(誤差は数メートル(10 フィート)以内になることもあります)。ACCESS_FINE_LOCATION 権限を宣言すると、アプリはこの精度の位置情報を取得できます。

ユーザーがおおよその位置情報の利用を許可した場合、アプリが宣言した位置情報の利用許可にかかわらず、アプリはおおよその位置情報にのみアクセスできます。

ユーザーがおおよその位置情報の利用のみを許可した場合でも、アプリは機能します。アプリの機能が、ACCESS_FINE_LOCATION 権限を使用して正確な位置情報にアクセスすることが必要不可欠になった場合は、アプリに正確な位置情報へのアクセスを許可するようユーザーに求めることができます。

実行時に位置情報へのアクセスをリクエストする

アプリ内の機能が位置情報へのアクセスを必要とするときは、ユーザーがその機能を操作してから、権限のリクエストを行います。このワークフローは、状況に応じて実行時の権限をリクエストするおすすめの方法(アプリの権限をリクエストする方法を参照)に従っています。

図 1 に、このプロセスの実行方法の例を示します。このアプリには、フォアグラウンドでの位置情報へのアクセスを必要とする「位置情報を共有」機能が含まれています。ただし、ユーザーが [位置情報を共有] ボタンを選択するまで、アプリは位置情報へのアクセスをリクエストしません。

ユーザーが [位置情報を共有] ボタンを選択すると、位置情報へのアクセスをリクエストするシステム ダイアログが表示されます
図 1. フォアグラウンドでの位置情報へのアクセスを必要とする位置情報共有機能。この機能は、ユーザーが [アプリの使用中のみ許可] を選択した場合に有効になります。

ユーザーはおおよその位置情報の取得のみを許可できる

Android 12(API レベル 31)以降では、ユーザーはアプリがおおよその位置情報のみを取得するようリクエストできます。これは、アプリが実行時の ACCESS_FINE_LOCATION 権限をリクエストした場合も同様です。

このようなユーザーの想定操作を処理するには、ACCESS_FINE_LOCATION 権限を単独でリクエストせず、代わりに ACCESS_FINE_LOCATION 権限と ACCESS_COARSE_LOCATION 権限の両方を 1 つのランタイム リクエストでリクエストしてください。ACCESS_FINE_LOCATION のみをリクエストしようとすると、Android 12 の一部のリリースではそのリクエストが無視されてしまいます。Android 12 以上をターゲットとするアプリの場合は、次のエラー メッセージが Logcat に記録されます。

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

アプリが ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION の両方をリクエストした場合、システム権限ダイアログには次のオプションが表示されます。

  • 正確: アプリに正確な位置情報の取得を許可します。
  • おおよそ: アプリにおおよその位置情報のみの取得を許可します。

図 3 は、ユーザーの選択を容易にするため、両方のオプションに対応するビジュアル キューがダイアログに含まれていることを示しています。ユーザーは、位置情報の精度を決定した後、3 つのボタンのいずれかをタップして、権限を付与する期間を選択します。

Android 12 以降では、アプリのターゲット SDK のバージョンにかかわらず、ユーザーはシステム設定に移動して、アプリごとに適切な位置情報の精度を設定できます。これは、Android 11 以前を搭載しているデバイスにアプリがインストールされ、ユーザーがデバイスを Android 12 以降にアップグレードした場合でも同じです。

このダイアログでは、おおよその位置情報へのアクセス権のみを確認するメッセージが表示され、3 つのボタンが上下に並んでいます
図 2. アプリが ACCESS_COARSE_LOCATION のみをリクエストした場合に表示されるシステム権限ダイアログ。
ダイアログでは 2 つのオプション セットが上下に表示されています
図 3. アプリが 1 つのランタイム リクエストで ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION の両方をリクエストした場合に表示されるシステム権限ダイアログ。

ユーザーの選択は権限の付与に影響

次の表に、ユーザーがランタイム権限ダイアログで選択したオプションに基づいて、システムがアプリに付与する権限を示します。

正確 おおよそ
アプリの使用時のみ ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
今回のみ ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
許可しない 位置情報の利用を許可しない 位置情報の利用を許可しない

システムがアプリに付与した権限を確認するには、権限リクエストの戻り値を確認します。Jetpack ライブラリを次のようなコードで使用することも、プラットフォーム ライブラリを使用して権限リクエスト コードを自身で管理することもできます。

Kotlin

val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            } else -> {
                // No location access granted.
            }
        }
    }

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION))

Java

ActivityResultLauncher<String[]> locationPermissionRequest =
    registerForActivityResult(new ActivityResultContracts
        .RequestMultiplePermissions(), result -> {
            Boolean fineLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_FINE_LOCATION, false);
            Boolean coarseLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_COARSE_LOCATION,false);
            if (fineLocationGranted != null && fineLocationGranted) {
                // Precise location access granted.
            } else if (coarseLocationGranted != null && coarseLocationGranted) {
                // Only approximate location access granted.
            } else {
                // No location access granted.
            }
        }
    );

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(new String[] {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
});

正確な位置情報へのアップグレードをリクエストする

アプリのアクセス権をおおよその位置情報から正確な位置情報にアップグレードするようユーザーに求めることができます。ただし、アプリのアクセス権を正確な位置情報にアップグレードするようユーザーに依頼する前に、アプリのユースケースでこのレベルの精度が必要不可欠であるかどうかを判断してください。アプリがデバイスを Bluetooth または Wi-Fi 経由で近くのデバイスとペア設定する必要がある場合は、ACCESS_FINE_LOCATION 権限をリクエストする代わりに、コンパニオン デバイスのペア設定か、Bluetooth の権限を使用することをおすすめします。

位置情報に対するアプリのアクセス権を「おおよそ」から「正確」にアップグレードするようユーザーにリクエストする方法は次のとおりです。

  1. 必要に応じて、アプリが権限を必要とする理由を説明します。
  2. ACCESS_FINE_LOCATION 権限と ACCESS_COARSE_LOCATION 権限をもう一度リクエストします。ユーザーはすでにアプリにおおよその位置情報へのアクセス権を付与することをシステムに許可しているため、システム ダイアログの内容は前と異なります。図 4図 5 をご覧ください。
ダイアログには、[正確な位置情報に切り替える]、[今回のみ]、[許可しない] というオプションがあります。
図 4. ユーザーが以前に [おおよそ] と [アプリの使用時のみ] を選択していた場合(図 3 のダイアログを参照)。
ダイアログには [今回のみ] と [許可しない] のオプションがあります。
図 5. ユーザーが以前に [おおよそ] と [今回のみ] を選択していた場合(図 3 のダイアログを参照)。

最初にフォアグラウンドでの位置情報のみをリクエストする

位置情報へのアクセスが必要な機能がアプリに複数あったとしても、バックグラウンドでの位置情報へのアクセスが必要な機能は多くはありません。このため、アプリで位置情報へのアクセスをリクエストする際には、フォアグラウンドでの位置情報へのアクセスを要求してから、バックグラウンドでの位置情報へのアクセスを要求する「段階的なリクエスト」を実行することをおすすめします。段階的なリクエストを実行すると、アプリのどの機能がバックグラウンドでの位置情報へのアクセスを必要としているかをより正確に把握できるため、ユーザーが細かく管理できるようになり、透明性も増します。

図 6 は、段階的なリクエストを扱うように設計されたアプリの例を示しています。「現在地を表示」と「付近の場所をおすすめ」の両方の機能で、フォアグラウンドでの位置情報へのアクセスが必要です。しかし、バックグラウンドでの位置情報へのアクセスを必要とするのは「付近の場所をおすすめ」機能のみです。

フォアグラウンドでの位置情報へのアクセスを有効にするボタンが、バックグラウンドでの位置情報を有効にするボタンから画面半分の距離にある
図 6. どちらの機能も位置情報へのアクセスを必要としますが、「付近の場所をおすすめ」機能のみがバックグラウンドでの位置情報へのアクセスを必要とします。

段階的なリクエストを実行するプロセスは次のとおりです。

  1. まず、図 1 の「位置情報を共有」機能や図 2 の「現在地を表示」機能など、フォアグラウンドでの位置情報へのアクセスが必要な機能をユーザーに案内します。

    アプリからフォアグラウンドでの位置情報へのアクセスがあるまで、バックグラウンドでの位置情報へのアクセスを必要とする機能へのユーザー アクセスを無効にすることをおすすめします。

  2. 後になって、ユーザーがバックグラウンドでの位置情報へのアクセスを必要とする機能の使用を試みた際に、バックグラウンドでの位置情報へのアクセスをリクエストできます。

必要に応じてバックグラウンドでの位置情報をリクエストする

図 7. バックグラウンドでの位置情報へのアクセスを許可する [常に許可] というオプションがある設定ページ。

権限ダイアログの内容がターゲット SDK のバージョンによって異なる

Android 10(API レベル 29)を搭載したデバイス上において、アプリ内の機能からバックグラウンドで位置情報がリクエストされる場合、システム権限ダイアログに [常に許可] オプションが表示されます。ユーザーがこのオプションを選択すると、アプリの機能からバックグラウンドでの位置情報へのアクセスが可能になります。

ただし Android 11(API レベル 30)以降では、システム ダイアログに [常に許可] オプションが表示されません。代わりに、図 7 に示すように、ユーザーは設定ページでバックグラウンドでの位置情報を有効にする必要があります。

バックグラウンドでの位置情報の権限をリクエストする場合に、おすすめの方法に従って、この設定ページへのユーザーの移動をサポートできます。権限を付与するプロセスは、アプリがターゲットとする SDK のバージョンによって異なります。

Android 11 以降をターゲットとするアプリ

アプリに ACCESS_BACKGROUND_LOCATION 権限が付与されておらず、shouldShowRequestPermissionRationale()true を返した場合、ユーザーに次の内容の説明 UI が表示されるようにします。

  • アプリの機能がバックグラウンドでの位置情報へのアクセスを必要とする明確な理由。
  • ユーザーに表示される、バックグラウンドでの位置情報へのアクセスを許可する設定オプションのラベル(たとえば図 7 の [常に許可])。このラベルを入手するには getBackgroundPermissionOptionLabel() を呼び出します。このメソッドの戻り値は、ユーザーのデバイスの言語設定に合わせてローカライズされています。
  • ユーザーが権限を拒否するためのオプション。ユーザーがバックグラウンド位置情報へのアクセスを拒否した場合に、アプリの使用を続行できるようにします。
ユーザーはシステム通知をタップしてアプリの位置情報設定を変更できます。
図 8. アプリにバックグラウンドでの位置情報へのアクセスを許可したことをユーザーに知らせる通知。

Android 10 以前をターゲットとするアプリ

アプリ内の機能からバックグラウンドでの位置情報へのアクセスがリクエストされると、ユーザーにシステム ダイアログが表示されます。このダイアログから、アプリの位置情報へのアクセスを許可する、設定ページのオプションに移動できます。

アプリがすでに位置情報へのアクセスをリクエストするおすすめの方法に従っている限り、この動作に対応するための変更は不要です。

ユーザーがバックグラウンドでの位置情報の精度に影響を与える可能性がある

ユーザーがおおよその位置情報をリクエストした場合は、位置情報の利用許可に関するダイアログで選択した内容がバックグラウンドでの位置情報にも適用されます。つまり、ユーザーがアプリに ACCESS_BACKGROUND_LOCATION 権限を付与したものの、フォアグラウンドではおおよその位置情報のみへのアクセス権を付与する場合は、アプリがバックグラウンドでアクセスできるのもおおよその位置情報に限定されます。

バックグラウンドでの位置情報の許可に関するリマインダー

Android 10 以降では、ユーザーがバックグラウンドでの位置情報へのアクセスを許可した後、アプリの機能がバックグラウンドでデバイスの位置情報に初めてアクセスすると、システムがユーザーへの通知の送信をスケジュールします。この通知は、デバイスの位置情報への常時アクセスがアプリに許可されていることをユーザーに知らせるものです。通知の例を図 8 に示します。

アプリの SDK の依存関係における位置情報の要件を確認する

アプリで位置情報の利用許可(特に ACCESS_FINE_LOCATION の権限)に依存する SDK を使用しているかどうかを確認します。Medium の記事、SDK の依存関係の動作を把握するをご覧ください。

参考情報

Android の位置情報へのアクセスについて詳しくは、以下の資料をご覧ください。

Codelab

動画

サンプル