オーディオ グラスとディスプレイ グラスのハードウェア権限をリクエストする

対象となる XR デバイス
このガイダンスは、次のようなタイプの XR デバイス向けのエクスペリエンスを構築する際に役立ちます。
オーディオと
ディスプレイ グラス

スマートフォンと同様に、オーディオ グラスやディスプレイ グラスでカメラやマイクなどの機密性の高いハードウェアにアクセスするには、ユーザーの明示的な同意が必要です。これらはメガネ固有の権限と見なされ、アプリがスマートフォンで対応する権限をすでに持っている場合でも、実行時にリクエストする必要があります。

アプリのマニフェストで権限を宣言する

権限をリクエストする前に、<uses-permission> 要素を使用して、アプリのマニフェスト ファイルで権限を宣言する必要があります。この宣言は、権限がスマートフォン固有の機能のものであっても、グラス固有の機能のものであっても同じですが、グラス固有のハードウェアまたは機能に対しては明示的にリクエストする必要があります。

<manifest ...>
    <!-- Only declare permissions that your app actually needs. In this example,
    we declare permissions for the camera. -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <application ...>
        ...
    </application>
</manifest>

グラスの権限をリクエストする前に

権限の原則とワークフローを確認して、アプリが必要とする実行時の権限をユーザーがすでに付与しているかどうか、メガネ固有の権限をリクエストする前にアプリがユーザーに根拠を示す必要があるかどうかなど、ユーザーに最適なエクスペリエンスを提供できるようにしてください。

パーミッション シナリオ

オーディオ グラスとディスプレイ グラスで危険な実行時の権限をリクエストするシナリオとして、次のようないくつかの場合があります。

  • プロジェクションされたアクティビティから実行時の権限をリクエストする
  • スマートフォンのアクティビティから実行時の権限をリクエストする

各シナリオの詳細については、このガイドの以降のセクションをご覧ください。

投影されたアクティビティから実行時の権限をリクエストする

投影されたアクティビティからオーディオまたはディスプレイ メガネの実行時の権限をリクエストするには、ProjectedActivityCompat.requestPermissions メソッドを使用します。

このメソッドを呼び出すと、メガネとホスト スマートフォンの両方で連携したユーザーフローがトリガーされます。

  1. メガネの場合: システムはメガネに投影されたコンパニオン アクティビティを開き、権限のリクエストに対応するためにスマートフォンを確認するようユーザーに指示します。
  2. スマートフォン: スマートフォンの画面に Android システムの権限ダイアログが表示されます。ダイアログには、ユーザーがスマートフォンではなくメガネの権限を付与していることが明示的に示されます。ユーザーはリクエストを許可または拒否できます。

次の例は、プロジェクション アクティビティからメガネの権限をリクエストする方法を示しています。

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
private fun requestCameraPermission() {
    lifecycleScope.launch {
        try {
            ProjectedActivityCompat.requestPermissions(
                this@PermissionsFromProjectedActivity,
                arrayOf(Manifest.permission.CAMERA),
                // CAMERA_PERMISSION_REQUEST_CODE is a developer defined constant
                CAMERA_PERMISSION_REQUEST_CODE,
            )
        } catch (e: IllegalStateException) {
            // Thrown when the projected system service can't be bound.
            Log.e(TAG, "Camera permission request failed: projected service unavailable.", e)
        }
    }
}

コードに関する主なポイント

  • 標準の ActivityCompat メソッドではなく ProjectedActivityCompat.requestPermissions を使用します。このメソッドは、ホスト スマートフォンではなく、オーディオ グラスとディスプレイ グラスのランタイム権限を明示的に対象とします。

権限の結果を処理する

ユーザーがスマートフォンで権限ダイアログに応答すると、onRequestPermissionsResult コールバックが呼び出され、ユーザーの決定がアプリに配信されます。

システムは、投影されたコンパニオン アクティビティを自動的に閉じます。オーディオ グラスの場合、音声アラートの再生が終了した後に発生します。ディスプレイ メガネでは、ユーザーがすべての権限ダイアログに返信した後に発生します。

レスポンスを処理するには、権限のリクエストを開始した Activity インスタンス内で onRequestPermissionsResult() をオーバーライドします。

次のコード スニペットは、コールバックを処理し、ユーザーがリクエストされた権限を付与したかどうかを確認する方法を示しています。

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray,
    deviceId: Int,
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId)
    if (requestCode != CAMERA_PERMISSION_REQUEST_CODE) return

    val isCameraGranted =
        grantResults.getOrNull(permissions.indexOf(Manifest.permission.CAMERA)) ==
            PackageManager.PERMISSION_GRANTED

    if (isCameraGranted) {
        initializeCameraFeatures()
    } else {
        onCameraPermissionDenied()
    }
}

コードに関する主なポイント
  • onRequestPermissionsResult コールバックで deviceId オーバーロードを使用して、権限ステータスが特定のコンテキスト(ホスト スマートフォンではなく、オーディオ グラスやディスプレイ グラスなど)に正しくマッピングされるようにします。
  • アプリは、許可と拒否の両方の結果を適切に処理する必要があります。

スマートフォン アクティビティで実行時の権限をリクエストする

アプリがスマートフォン アクティビティで実行されていて、オーディオ グラスやディスプレイ グラスの権限を必要とする場合(ユーザーが動画ストリームをグラスのカメラに切り替えて一人称視点にするなど)は、デバイス固有の Activity#requestPermissions(permissions, requestCode, deviceId) メソッドを使用して権限をリクエストします。

// Request the projected permission from phone activity
requestPermissions(
    arrayOf(Manifest.permission.CAMERA),
    // REQUEST_CODE_GLASSES_CAMERA is a developer-defined constant
    REQUEST_CODE_GLASSES_CAMERA,
    projectedDeviceId
)

コードに関する主なポイント

  • オーディオ グラスとディスプレイ グラスをターゲットにするには、createProjectedDeviceContext を使用して作成した投影コンテキストから適切なデバイス ID を取得します。この ID を requestPermissions メソッドの呼び出しで渡します。

権限の結果を処理する

ユーザーがスマートフォンで権限ダイアログに応答すると、onRequestPermissionsResult コールバックが呼び出され、ユーザーの決定がアプリに配信されます。

レスポンスを処理するには、権限のリクエストを開始した Activity インスタンス内の onRequestPermissionsResult をオーバーライドします。

次のコード スニペットは、コールバックを処理し、ユーザーがリクエストされた権限を付与したかどうかを確認する方法を示しています。

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray,
    deviceId: Int,
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId)
    if (requestCode != CAMERA_PERMISSION_REQUEST_CODE) return

    val isCameraGranted =
        grantResults.getOrNull(permissions.indexOf(Manifest.permission.CAMERA)) ==
            PackageManager.PERMISSION_GRANTED

    if (isCameraGranted) {
        initializeCameraFeatures()
    } else {
        onCameraPermissionDenied()
    }
}

コードに関する主なポイント
  • deviceId オーバーロードと onRequestPermissionsResult コールバックを使用して、権限ステータスが特定のコンテキスト(ホスト スマートフォンではなく、オーディオやディスプレイ グラスなど)に正しくマッピングされるようにします。
  • アプリは、許可と拒否の両方の結果を適切に処理する必要があります。