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

Android 13细分媒体权限弹窗不显示问题求助

Android 13(SDK33)媒体权限请求弹窗不显示问题排查与修复

我已将项目升级至SDK 33,按照谷歌文档将原有的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限替换为细分媒体权限,但权限请求弹窗始终未出现。以下是我的实现代码:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.storagepermission">
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

    <!-- Required to maintain app compatibility. -->
    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.StoragePermission"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity

class MainActivity : AppCompatActivity() {
    lateinit var button: Button

    private val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)

    @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
    private val permissionsFor13 = arrayOf(
        Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO,
        Manifest.permission.READ_MEDIA_AUDIO)

    fun permissions(): Array<String>? {
        val p: Array<String>
        p = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            Log.e("TAG", "permissions: permissionsFor13" )
            permissionsFor13
        } else {
            Log.e("TAG", "permissions: permission" )
            permissions
        }
        return p
    }

    @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
    private fun arePermissionsEnabled(): Boolean
    {
        for (permission in permissions()!!)
        {

            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)

                return false
        }

        return true
    }

    @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
    private fun requestMultiplePermissions()
    {
        val remainingPermissions = ArrayList<String>()
        for (permission in permissions()!!)
        {
            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
            {
                remainingPermissions.add(permission)
            }
        }
    }

    @RequiresApi(33)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button = findViewById(R.id.button)

        button.setOnClickListener {
             val readImagePermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) Manifest.permission.READ_MEDIA_IMAGES else Manifest.permission.READ_EXTERNAL_STORAGE
            if(ContextCompat.checkSelfPermission(this, readImagePermission) == PackageManager.PERMISSION_GRANTED){
                Toast.makeText(applicationContext,"permission granted", Toast.LENGTH_LONG).show()
                arePermissionsEnabled()
            } else {
                requestMultiplePermissions()
                Toast.makeText(applicationContext,"permission Not granted", Toast.LENGTH_LONG).show()
            }
        }

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="311dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

问题核心原因

代码中requestMultiplePermissions()方法仅收集了未授权的权限列表,但没有调用系统API发起权限请求,这是弹窗不出现的直接原因。此外还有几处逻辑冗余和注解限制可以优化。

修复后的MainActivity代码

class MainActivity : AppCompatActivity() {
    lateinit var button: Button

    // 根据系统版本自动返回对应权限列表
    private val requiredPermissions: Array<String>
        get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arrayOf(
                Manifest.permission.READ_MEDIA_IMAGES,
                Manifest.permission.READ_MEDIA_VIDEO,
                Manifest.permission.READ_MEDIA_AUDIO
            )
        } else {
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
        }

    // 检查所有必要权限是否已授权
    private fun arePermissionsEnabled(): Boolean {
        return requiredPermissions.all {
            ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
        }
    }

    // 发起权限请求
    private fun requestMultiplePermissions() {
        val remainingPermissions = requiredPermissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }.toTypedArray()

        if (remainingPermissions.isNotEmpty()) {
            ActivityCompat.requestPermissions(
                this,
                remainingPermissions,
                100 // 自定义请求码,用于后续处理权限结果
            )
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button = findViewById(R.id.button)

        button.setOnClickListener {
            if (arePermissionsEnabled()) {
                Toast.makeText(applicationContext, "权限已授权", Toast.LENGTH_LONG).show()
            } else {
                requestMultiplePermissions()
                Toast.makeText(applicationContext, "正在请求权限", Toast.LENGTH_LONG).show()
            }
        }
    }

    // 可选:处理权限请求结果
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 100) {
            if (arePermissionsEnabled()) {
                Toast.makeText(applicationContext, "权限请求成功", Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(applicationContext, "部分权限未授权", Toast.LENGTH_LONG).show()
            }
        }
    }
}

额外注意事项

  • AndroidManifest.xml的配置是正确的,无需修改
  • 测试时需使用Android 13及以上版本的设备/模拟器,低版本会自动适配READ_EXTERNAL_STORAGE权限
  • 若用户之前拒绝权限并勾选"不再询问",需引导用户到应用设置页面手动开启权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:25:16