jiichan.com

PROGRAMMING

Kotlin

ランタイムパーミッションの取得

ランタイムパーミッションの取得方法は何通りかありますが、その中で使いやすかったのが Accompanist の Permissions ライブラリを使用する方法でした。
その Accompanist の Permissions ライブラリが非推奨になったようで、結果のあるアクティビティを起動する rememberLauncherForActivityResult を使う方法が推奨されていました。
そこで、rememberLauncherForActivityResult を使ったコードを備忘録として載せておこうと思います。(2025.11.28)

≪開発環境≫
windows11
andriod studio Narwhal

MainActivity

普通の MainActivity です。


 class MainActivity : ComponentActivity() {
    private val viewModel: AudioRecorderViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AudioRecorderScreen(
                context = this,
                viewModel = viewModel)
        }
    }
}   

パーミッションを要求しているスクリーン

rememberLauncherForActivityResult はコンポーザブル関数内でなければ使用できないようです。


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AudioRecorderScreen(context: Context, viewModel: AudioRecorderViewModel) {
    /** Permission 要求 ======================================== */
    val permission = Manifest.permission.RECORD_AUDIO
    var showAlert by remember { mutableStateOf(false) }
    var btnEnabled by remember{ mutableStateOf(true)}

     // 権限リクエスト用の launcher を準備
    val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // 権限が許可された場合 ボタンを有効にする
            btnEnabled = true
        } else {
            // 権限が拒否された場合 ボタンを無効にする
            btnEnabled = false
            // 拒否された場合、権限が必要なことを説明するダイアログ表示
            showAlert = true
        }
    }

    // コンポーザブルが最初に表示されたときに権限リクエストを実行
    LaunchedEffect(Unit) {
        // 権限が付与されていない場合、権限リクエストを開始
        permissionLauncher.launch(permission)
    }

    if (showAlert) {
        // 拒否された場合に、権限が必要なことを説明するダイアログ
        AlertDialog(
            onDismissRequest = {},
            title = { Text("マイク使用の許可") },
            text = { Text("録音の権限が必要です。設定を確認してください。") },
            confirmButton = {
                TextButton(
                    onClick = { showAlert = false },
                ) {
                    Text("OK")
                }
            },
        )
    }
    /** ======================================================= */

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Spacer(modifier = Modifier.height(100.dp))
        Button(
            onClick = { viewModel.startRecording() },
            enabled = btnEnabled,
            :
            :

権限の有無でUIを切り分ける場合

権限が許可されている場合は OkScreen 、拒否されている場合は NoScreen 、というように切り分ける場合は、 var permissionGranted by remember { mutableStateOf(false) } を利用する方法などが考えられると思います。


    var permissionGranted by remember { mutableStateOf(false) }

    val permissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // 権限が許可された場合
            permissionGranted = true
        } else {
            // 権限が拒否された場合
            permissionGranted = false
        }
    }

    LaunchedEffect(Unit) {
        if (ContextCompat.checkSelfPermission(context, permission
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // 権限が付与されていない場合、権限リクエストを開始
            permissionLauncher.launch(permission)
        }
    }

    if (permissionGranted) {
        // 権限が許可されている場合に表示するUI
        OkScreen()
    } else {
        // 権限が拒否されている場合に表示するUI
        NoScreen()
    }    

複数のパーミッションがある場合

複数のパーミッションが有る場合は、パーミッションをリストにし、 複数のパーミッション用の RequestMultiplePermissions を使用するようです。


    // パーミッションのリスト
    val permissions = remember {
        arrayOf(
            Manifest.permission.READ_MEDIA_IMAGES,
            Manifest.permission.READ_MEDIA_AUDIO
        )
    }
    
    // 複数のパーミッション用ランチャー(RequestMultiplePermissions)
    val launcherMultiple = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestMultiplePermissions()
    ) { idGrantedList: Map<String, Boolean> ->
        // permission には 「android.permission.READ_MEDIA_AUDIO」等が入るので必要に応じて利用する
        idGrantedList.forEach { (permission, isGranted) ->
            if (!isGranted) {
                // 拒否された場合、権限が必要なことを説明するダイアログ表示
                showAlert = true
            }
        }
    }

    LaunchedEffect(Unit) {
        // 許可されていなければパーミッションリクエストが起動する
        launcherMultiple.launch(permissions)
    }




Kotlin
javascript
PHP
Java