Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

アプリの権限をリクエストする

すべての Android アプリは、アクセスが制限されたサンドボックス内で実行されます。アプリ自体のサンドボックスの外部にあるリソースや情報を使用しなければならない場合は、適切な権限をリクエストする必要があります。アプリ マニフェストに権限をリストすることにより、アプリが権限を必要としていることを宣言し、実行時に権限ごとにユーザーの承認をリクエストします(Android 6.0 以降)。

次の基本原則があります。

  • 権限を必要とする機能をユーザーが操作し始めたら、その状況に応じた権限をリクエストすること。
  • ユーザーをブロックしないこと。権限に関連した説明を表示する UI フローは、常にキャンセルできるようにしてください。
  • 機能に必要な権限をユーザーが拒否または取り消した場合は、グレースフル デグラデーションを行って、アプリの使用を続けられるようにしてください。このために、権限を必要とする機能を無効にする場合もあります。
  • システム動作を前提としないこと。

このページでは、アプリに権限を追加する手順と、必要に応じてそれらの権限を実行時にリクエストする手順を詳しく説明します。

マニフェストに権限を追加する

アプリが権限を必要としていることを宣言するには、Android のバージョンにかかわらず、アプリ マニフェスト内で最上位の <manifest> 要素の子要素として <uses-permission> 要素を挿入します。

たとえば、アプリでインターネットにアクセスする必要がある場合は、マニフェストに次の行を記述します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.snazzyapp">

    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- other permissions go here -->

    <application ...>
        ...
    </application>
</manifest>

権限を宣言した後のシステムの動作は、権限の保護レベルによって異なります。「normal」とみなされる権限はインストール直後にシステムによって付与されますが、「dangerous」とみなされる権限については、ユーザーがアプリのアクセスを明示的に許可する必要があります。権限の種類について詳しくは、保護レベルをご覧ください。

権限を確認する

アプリに dangerous 権限が必要な場合は、dangerous 権限が必要な操作を実行するたびに、権限の有無を確認する必要があります。Android 6.0(API レベル 23)以降では、ユーザーは任意のアプリから dangerous 権限をいつでも取り消すことができます。

アプリに権限が付与されているかどうかを確認する

ユーザーがすでに特定の権限をアプリに付与しているかどうかを確認するには、その権限を ContextCompat.checkSelfPermission() メソッドに渡します。このメソッドは、アプリに権限があるかどうかに応じて、PERMISSION_GRANTED または PERMISSION_DENIED のいずれかを返します。

アプリが権限を必要とする理由を説明する

ContextCompat.checkSelfPermission() メソッドが PERMISSION_DENIED を返した場合は、shouldShowRequestPermissionRationale() を呼び出します。このメソッドが true を返した場合は、ユーザーに説明 UI を表示します。この UI で、ユーザーが有効にしようとしている機能が特定の権限を必要とする理由を説明します。

権限をリクエストする

ユーザーに説明 UI を表示した後、または shouldShowRequestPermissionRationale() の戻り値が今回は説明 UI を表示する必要がないことを示したときは、権限をリクエストします。システム権限ダイアログがユーザーに表示され、アプリに特定の権限を付与するかどうかの選択をユーザーに促します。

従来からある方法では、権限リクエストの一部として開発者自身がリクエスト コードを管理し、このリクエスト コードを権限コールバックのロジックに含めます。別の方法として、AndroidX ライブラリに含まれる RequestPermission コントラクトを使用して、システムに権限リクエスト コードの管理を許可することもできます。RequestPermission コントラクトを使用するとロジックが簡素化されるため、使用できる場合は使用することをおすすめします。

システムに権限リクエスト コードの管理を許可する

権限リクエストに関連付けられたリクエスト コードの管理をシステムに許可するには、モジュールの build.gradle ファイルに androidx.activity ライブラリへの依存関係を追加します。バージョン 1.2.0 以降のライブラリを使用してください。

次のクラスのいずれかを使用できます。

RequestPermission コントラクトを使用する手順を以下に示します。RequestMultiplePermissions コントラクトを使用する手順もこれとほぼ同じです。

  1. アクティビティまたはフラグメントの初期化ロジックで、registerForActivityResult() の呼び出しに ActivityResultCallback の実装を渡します。ActivityResultCallback は、権限リクエストに対するユーザーの応答の処理方法を定義します。

    ActivityResultLauncher 型の戻り値 registerForActivityResult() への参照を保持します。

  2. 必要に応じてシステム権限ダイアログを表示するには、前の手順で保存した ActivityResultLauncher のインスタンスで launch() メソッドを呼び出します。

    launch() が呼び出されると、システム権限ダイアログが表示されます。ユーザーが選択すると、前のステップで定義した ActivityResultCallback の実装が非同期で呼び出されます。

    注: launch() を呼び出したときに表示されるダイアログをアプリでカスタマイズすることはできません。ユーザーに詳細な情報やコンテキストを提供するには、アプリの UI を変更して、アプリの機能に特定の権限が必要な理由をユーザーにわかりやすく説明します。たとえば、機能を有効にするボタンのテキストを変更します。

    また、システム権限ダイアログのテキストでは、リクエストする権限に関連付けられた権限グループが参照されます。この権限グループはシステムを使いやすくするために設計されたものです。アプリでは、権限が特定の権限グループに属しているかどうかに依存するロジックを使用するべきではありません。

次のコード スニペットは、権限に関する応答の処理方法を示しています。

Kotlin

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features 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.
        }
    }

Java

// 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 ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features 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.
        }
    });

このコード スニペットは、権限を確認し、必要に応じてユーザーに権限をリクエストする場合の推奨されるプロセスを示しています。

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    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 -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        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 {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

開発者自身がリクエスト コードを管理する

システムに権限リクエスト コードの管理を許可する代わりに、開発者自身がリクエスト コードを管理することもできます。そのためには、requestPermissions() の呼び出しにリクエスト コードを含めます。

次のコード スニペットは、リクエスト コードを使用して権限をリクエストする方法を示しています。

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == 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 -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        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 {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

ユーザーがシステム権限ダイアログに応答すると、システムはアプリの onRequestPermissionsResult() の実装を呼び出します。システムは、ユーザーの応答と、開発者が定義したリクエスト コードを権限ダイアログに渡します。次のコード スニペットをご覧ください。

Kotlin

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the features 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.
        }
    }
}

Java

@Override
public void onRequestPermissionsResults(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the features 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.
    }
}

権限の拒否を処理する

ユーザーが権限のリクエストを拒否した場合は、その影響をユーザーが理解できるようにする必要があります。特に、権限がないために動作しない機能をユーザーに知らせる必要があります。その際は、次のベスト プラクティスを念頭に置いてください。

  • ユーザーの注意を引く。アプリに必要な権限がないために機能が制限されている UI を強調します。次のような方法が考えられます。

    • 機能の結果やデータが表示される場所にメッセージを表示する。
    • エラーアイコンとエラーを示す色を含んだ別のボタンを表示する。
  • 具体的に記述する。一般的なメッセージは表示しないでください。代わりに、アプリに必要な権限がないためにどの機能が利用できないかを記載します。

  • ユーザー インターフェースをブロックしない。具体的には、アプリの使用を妨げるような全画面の警告メッセージは表示しないでください。

同時に、アプリは権限のリクエストを拒否するというユーザーの決定を尊重する必要があります。Android 11(API レベル 30)以降では、デバイスにインストールされたアプリの全期間に、同じ権限に対してユーザーが何度も [許可しない] をタップした場合、アプリがその権限を再度リクエストしても、ユーザーにシステム権限ダイアログが表示されることはありません。このユーザーのアクションにより、[次回から表示しない] が選択されたことになります。以前のバージョンでは、ユーザーが以前に [次回から表示しない] チェックボックスまたはオプションをオンにしていない限り、アプリが権限をリクエストするたびに、システム権限ダイアログが表示されていました。

状況によっては、権限が自動的に拒否され、ユーザーによるアクションを必要としない場合があります(同じように、権限が自動的に付与される場合もあります)。自動的な動作を想定しないことが重要です。権限を必要とする機能にアプリがアクセスするたびに、その権限がアプリに付与されていることを確認する必要があります。

アプリの権限を求めるときのユーザー エクスペリエンスを向上させるには、アプリの権限に関するベスト プラクティスもご覧ください。

必要に応じてデフォルト ハンドラになるようリクエストする

アプリによっては、通話履歴や SMS メッセージに関するユーザーの機密情報にアクセスする必要があります。通話履歴や SMS メッセージに固有の権限をリクエストするアプリを Play ストアに公開する場合は、実行時の権限をリクエストする前に、アプリを中核的システム機能のデフォルト ハンドラとして設定することをユーザーに求める必要があります。

デフォルト ハンドラのプロンプトをユーザーに表示する方法など、デフォルト ハンドラの詳細については、デフォルト ハンドラに限り使用できる権限に関するガイドをご覧ください。

API レベルで権限を宣言する

実行時の権限をサポートするデバイス、つまり Android 6.0(API レベル 23)以降を実行しているデバイスでのみ権限を宣言するには、uses-permission タグではなく uses-permission-sdk-23 タグを追加します。

このいずれかのタグを使用すると、maxSdkVersion 属性を設定して、新しいバージョンが実行されているデバイスでは特定の権限が不要であることを指定できます。

参考情報

権限について詳しくは、以下の記事をご覧ください。

権限のリクエストについて詳しくは、以下のサンプルアプリをダウンロードしてください。

  • Android RuntimePermissionsBasic サンプル Java | Kotlin