You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android SDK34下requestPermissions失效及权限弹窗不显示问题求助

问题修正方案(适配SDK34+)

核心问题说明

SDK34(Android 14)中requestPermissions()已被废弃,官方推荐使用Activity Result API处理权限请求;同时Android 13+对文件访问权限做了简化,使用系统文件选择器无需申请存储权限,这也是权限弹窗不弹出的原因之一。以下是完整修正代码:


步骤1:定义权限请求与操作启动器

在Fragment类中添加成员变量,替换废弃的权限请求方法:

import android.Manifest
import android.app.Activity
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.provider.MediaStore
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.activity.result.contract.ActivityResultContracts

class YourFragment : Fragment() {
    // 相机权限请求启动器
    private val cameraPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted ->
        if (isGranted) {
            presentCamera()
        } else {
            Toast.makeText(requireContext(), "需要相机权限才能拍照", Toast.LENGTH_SHORT).show()
        }
    }

    // 拍照结果处理启动器
    private val takePictureLauncher = registerForActivityResult(
        ActivityResultContracts.TakePicture()
    ) { isSuccess ->
        if (isSuccess) {
            // 拍照成功,处理临时URI对应的图片
            // 注意:此处需配合createImageUri()生成的URI使用
        }
    }

    // 文件选择结果处理启动器(可选,替代startActivityForResult)
    private val filePickerLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            result.data?.data?.let { fileUri ->
                // 处理选中的文件URI
            }
        }
    }

步骤2:修正displayPicker函数

替换原权限检查逻辑,使用新启动器处理权限请求:

fun displayPicker() {
        val options = arrayOf("选择文件", "拍照")
        AlertDialog.Builder(requireContext())
            .setTitle("选择操作")
            .setItems(options) { _, which ->
                when (which) {
                    0 -> {
                        // SDK34下使用系统文件选择器无需申请存储权限
                        presentFiles()
                    }
                    1 -> {
                        // 检查相机权限
                        when {
                            ContextCompat.checkSelfPermission(
                                requireContext(),
                                Manifest.permission.CAMERA
                            ) == PackageManager.PERMISSION_GRANTED -> {
                                presentCamera()
                            }
                            shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
                                // 显示权限说明弹窗
                                AlertDialog.Builder(requireContext())
                                    .setMessage("需要相机权限拍摄照片,请允许")
                                    .setPositiveButton("确定") { _, _ ->
                                        cameraPermissionLauncher.launch(Manifest.permission.CAMERA)
                                    }
                                    .setNegativeButton("取消", null)
                                    .show()
                            }
                            else -> {
                                // 直接发起权限请求
                                cameraPermissionLauncher.launch(Manifest.permission.CAMERA)
                            }
                        }
                    }
                }
            }
            .show()
    }

步骤3:实现presentFiles与presentCamera

使用新API处理文件选择与拍照逻辑:

private fun presentFiles() {
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "*/*" // 可指定具体类型,如"image/*"限制图片选择
        }
        filePickerLauncher.launch(intent)
    }

    private fun presentCamera() {
        val photoUri = createImageUri() ?: run {
            Toast.makeText(requireContext(), "无法创建临时存储文件", Toast.LENGTH_SHORT).show()
            return
        }
        takePictureLauncher.launch(photoUri)
    }

    // 创建拍照临时文件URI
    private fun createImageUri(): Uri? {
        val contentValues = ContentValues().apply {
            put(MediaStore.Images.Media.DISPLAY_NAME, "photo_${System.currentTimeMillis()}.jpg")
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
        }
        return requireContext().contentResolver.insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            contentValues
        )
    }
}

关键注意点

  1. 存储权限无需申请:Android 13+使用ACTION_OPEN_DOCUMENT调用系统文件选择器时,无需申请READ_EXTERNAL_STORAGE权限,系统会自动授予文件访问权限。
  2. 权限拒绝处理:若用户拒绝权限并勾选「不再询问」,shouldShowRequestPermissionRationale会返回false,此时需引导用户前往应用设置手动开启权限。
  3. 废弃API替换:所有原requestPermissions()、startActivityForResult()均需替换为Activity Result API,避免兼容性问题。

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 20:32:31