在Android 13或12中,请求权限不起作用。

9
我将我的安卓项目从compileSdkVersion 31更新到compileSdkVersion 33。我有以下代码来启动应用程序中需要的权限,但它不起作用。
import android.Manifest
import android.app.Activity
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.os.Build



class Permissions(private val activity: Activity, private val permissionList: List<String>, val code: Int) {

    fun checkPermissions() {
        if (permissionsGranted() != PackageManager.PERMISSION_GRANTED) {
            requestPermissions()
        }
    }

    private fun permissionsGranted(): Int {
        var counter = 0
        for (permission in permissionList) {
            counter += ContextCompat.checkSelfPermission(activity, permission)
        }
        return counter
    }

    private fun deniedPermission(): String {
        for (permission in permissionList) {
            if (ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_DENIED) return permission
        }
        return ""
    }

    private fun requestPermissions() {
        val permission = deniedPermission()
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {

        } else {

            ActivityCompat.requestPermissions(activity, permissionList.toTypedArray(), code)
        }
    }

    fun checkPermission(manifest: String): Boolean {
        val result = ContextCompat.checkSelfPermission(activity, manifest)
        return result == PackageManager.PERMISSION_GRANTED
    }

    fun checkPermissionActivity(state: Boolean, urlPath: String, kind : String){
        val showRationale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            this.activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) && this.activity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        } else {
            true
        }

        if (!showRationale) {

            return
        } else {

            return
        }
    }

    fun getAllPermissions(): List<String> {
        val granted = ArrayList<String>()
        val pi = activity.packageManager.getPackageInfo(activity.packageName, PackageManager.GET_PERMISSIONS)
        for (i in pi.requestedPermissions.indices) {
            if (pi.requestedPermissionsFlags[i] and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0) {
                granted.add(pi.requestedPermissions[i])
            }
        }

        return granted
    }


}

该文本的意思是:清单是。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.co.retrofit.app">
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application
            android:name=".feature.RetrofitApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:networkSecurityConfig="@xml/network_security_config"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme"
            android:usesCleartextTraffic="true">
        <activity
                android:exported="true"
                android:name=".feature.view.activities.Maintenance" />
        <activity android:name=".feature.view.activities.SplashActivity"  android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".feature.view.activities.MainActivity"  android:exported="true"/>
    </application>

</manifest>

当我点击一个按钮时,我调用这个函数。
@Suppress("UNUSED_PARAMETER")
private fun addAlbum(view: View){
    val permissions = Permissions(this,
        arrayListOf(
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE),
        23)
    permissions.checkPermissions()
}

或者

@Suppress("UNUSED_PARAMETER")
private fun addAlbum(view: View){
    val permissions = Permissions(this,
        arrayListOf(
            Manifest.permission.CAMERA),
        23)
    permissions.checkPermissions()
}

如果我回滚更新,它会显示我需要的权限,但是我需要在33中编译。

evidence

现在,如果我只更新编译 SDK,它不会显示弹出窗口。

Evidence


您的 Permissions.permissionsGranted() 方法可能会有困难,因为它是基于计数器而不是每个权限具体指定的方式来区分普通和危险权限。危险和普通权限的定义可能在 Android 版本之间有所不同。 - ecle
2个回答

5
在Android 13中,Google引入了存储细分权限,这意味着您现在必须指定要在应用程序中使用哪种类型的媒体。介绍了三种类型的权限:READ_MEDIA_AUDIO、READ_MEDIA_VIDEO和READ_MEDIA_IMAGES。在Android 13上,您不能再请求READ_EXTERNAL_STORAGE权限,而且我是说没有人能够确定为什么。一旦您编译sdk 33,它就会停止在运行时请求并从应用程序设置中删除该权限。有关更多信息,请参见:https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions

如果我想访问相机,它也无法工作 @M Ashhal - Alejandro Gonzalez
@AlejandroGonzalez 你可能需要检查一下你合并的清单文件,可能有一个库在使用相机权限时使用了maxSdkVersion。请检查并查看是否有帮助! - M Ashhal
它是正确的。现在它正在运行。感谢@M Ashhal。 - Alejandro Gonzalez

4
针对 Android 13,您需要在清单文件中声明要读取哪种媒体。您不能直接在清单文件中请求 READ_EXTERNAL_STORAGE 权限。
例如,如果您想要音频权限,则需要使用 READ_MEDIA_AUDIO;如果您需要视频权限,则需要使用 READ_MEDIA_VIDEO;如果您需要图片权限,则需要使用 READ_MEDIA_IMAGES 等。
此外,如果您正在迁移到 Android 13,则可以参考这篇文章

如果我想要访问相机,需要哪个权限? - Alejandro Gonzalez
要访问相机,您需要 android.permission.CAMERA 权限。 - Christopher
@AlejandroGonzalez 我认为在Android 13中相机权限的行为没有改变。 - krupa parekh
很高兴能帮忙,如果您愿意,可以通过接受来表达感激之情 :) - krupa parekh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接