1. はじめに
Android 12(API レベル 31)以降では、ユーザーはアプリに利用を許可する位置情報の精度を制御できます。以前のバージョンの Android では、アプリが ACCESS_FINE_LOCATION
利用許可または ACCESS_COARSE_LOCATION
利用許可をリクエストするかどうかによって位置情報の精度が暗黙的に制御されます。
この Codelab では、ターゲットとする SDK のバージョンが 31 以降のアプリで位置情報の利用許可をリクエストする場合に役立つガイダンスとおすすめの方法を紹介します。
前提条件
- Android 開発に携わった経験
- アクティビティと権限の基本事項を理解していること
- アプリの権限をリクエストする方法に関する予備知識
- 位置情報の利用許可をリクエストする方法に関する予備知識
学習内容
- Android S で位置情報の利用許可をリクエストする方法
- ユーザーがアプリに正確な位置情報の利用許可を付与できるように、最適な位置情報リクエスト フローを実装する方法
用語
正確な位置情報: 位置情報の利用許可の粒度が ACCESS_FINE_LOCATION
です。
おおよその位置情報: 位置情報の利用許可の粒度が ACCESS_COARSE_LOCATION
です。
取り上げる API
2. ACCESS_FINE_LOCATION 利用許可をリクエストする
新しい UI フロー
まず、新しい UI で位置情報の精度に関する変更点を確認しましょう。
以下の図 1a と図 1b は、アプリに ACCESS_FINE_LOCATION
利用許可も ACCESS_COARSE_LOCATION
利用許可も付与されていない場合に表示される利用許可ダイアログを示しています。
図 1a: 正確な現在地が選択される 図 1b: おおよその現在地が選択される
以下の図 2a は、使用中のアプリに ACCESS_COARSE_LOCATION
利用許可が付与されている場合に表示される、利用許可アップグレード ダイアログを示しています。このダイアログは、ユーザーが前の画面(図 1b を参照)において [おおよその場所] で [アプリの使用時のみ] を選択した場合に表示されます。
図 2a
以下の図 2b は、アプリの現在のセッションのみに ACCESS_COARSE_LOCATION
利用許可が付与されている場合に表示される利用許可アップグレード ダイアログを示しています。このダイアログは、ユーザーが前の画面(図 1b を参照)で [今回のみ] を選択した場合に表示されます。
図 2b
3. コードの実装
アプリのマニフェストで位置情報の利用許可を宣言する
ACCESS_FINE_LOCATION
をリクエストするには、アプリのマニフェストで ACCESS_FINE_LOCATION
と ACCESS_COARSE_LOCATION
の両方を宣言することが要求されます。宣言していない場合、システムはリクエストを無視し、アプリにどちらの許可も与えません。
<manifest ... >
<!-- Required when requesting precise location access on Android 12 (API level 31) and higher. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
ACCESS_FINE_LOCATION 利用許可をリクエストする
MyActivity.kt(Kotlin)
when {
ContextCompat.checkSelfPermission(
CONTEXT,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED -> {
// You can use the API that requires the permission.
performAction(...)
}
shouldShowRequestPermissionRationale(...) -> {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...)
}
else -> {
// Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
requestPermissions(CONTEXT,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION),
REQUEST_CODE)
}
}
MyActivity.java(Java)
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
requestPermissions(CONTEXT,
new String[] { Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION },
REQUEST_CODE);
}
レスポンスを処理する
MyActivity.kt(Kotlin)
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE -> {
// If the request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty()) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_FINE_LOCATION is granted
} else if (grantResults[1] ==
PackageManager.PERMISSION_GRANTED) {
// ACCESS_COARSE_LOCATION is granted
}
} else {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
MyActivity.java(Java)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
// If the request is cancelled, the result arrays are empty.
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// ACCESS_FINE_LOCATION is granted
} else if (grantResults[1] ==
PackageManager.PERMISSION_GRANTED) {
// ACCESS_COARSE_LOCATION is granted
}
} else {
// Explain to the user that the feature is unavailable because
// the feature requires a permission that the user has denied.
// At the same time, respect the user's decision. Don't link to
// system settings in an effort to convince the user to change
// their decision.
}
return;
}
// Other 'case' lines to check for other
// permissions this app might request.
}
}
4. ACCESS_COARSE_LOCATION 利用許可のみをリクエストする
図 4 は、アプリが ACCESS_COARSE_LOCATION
利用許可のみをリクエストした場合に表示される利用許可ダイアログを示しています。
図 4
おおよその位置情報の利用許可のみを操作するには、アプリは各ステップでおおよその位置情報の利用許可のみを宣言して処理する必要があります。
5. 位置情報の設定
以下の図 5 は新しい位置情報利用許可設定を示しています。新しい切り替えスイッチを使用して、アプリが正確な位置情報にアクセスできるか、またはおおよその位置情報にアクセスできるかをユーザーが制御できます。
図 5
6. SDK バージョン 30 以下を対象とするアプリの場合
新しい位置情報の精度オプション(正確 / おおよそ)は、SDK バージョン 30 以下をターゲットとするアプリには表示されません。
7. 完了
Android 12 で位置情報の利用許可をリクエストする方法について学習しました。また、位置情報の利用許可に関する多くの重要な要素について確認しました。
これで、アプリのニーズに合わせて、さまざまなユースケースで位置情報の利用許可をリクエストできるようになりました。
位置情報についての詳細: