Android 11 个运行时权限

Android 11 Runtime Permissions

几天前,代码运行良好,没有权限问题。

我无法在 运行 时授予权限,在从设置中授予权限时也遇到了问题。 (应用权限详细信息页面)。

var permissions = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
        arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
    } else {
        arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
    }

单击相应按钮请求权限。

permissionResultLauncher =
        registerForActivityResult(
                ActivityResultContracts.RequestMultiplePermissions()
        ) { permissions ->
            var allPermissionGranted = true
            permissions.entries.forEach {
                if (!it.value) {
                    Log.e(TAG, "Permission ${it.key} granted : ${it.value}")
                    allPermissionGranted = false
                }
            }
            if (!permissionDeniedDialog && !allPermissionGranted) {
                showDialog(
                        "Required",
                        "App needs Bluetooth and Location permissions to scan bluetooth devices.",
                        "Later",
                        "Allow",
                        object : DialogView.ButtonListener {
                            override fun onNegativeButtonClick(dialog: AlertDialog) {
                                dialog.dismiss()
                                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                        Uri.fromParts("package", requireActivity().applicationContext.packageName, null))
                                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                                startActivity(intent)
                            }

                            override fun onPositiveButtonClick(dialog: AlertDialog) {
                                dialog.dismiss()
                                requestRequirdPermissions()
                            }
                        })
            } else {
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                        Uri.fromParts("package", requireActivity().applicationContext.packageName, null))
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                startActivity(intent)
            }
            permissionDeniedDialog = true
        }
permissionResultLauncher.launch(permissions)

检查权限的功能

private fun checkPermission(): Boolean {
        for (permission in permissions) {
            if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) return false
        }
        return true
    }

有人可以告诉我为什么上面的方法不起作用吗?。系统直接在结果上,应用程序将应用程序重定向到设置页面,但我也无法从设置页面授予权限。

这是 OS 具体的吗?有人对 ColorOS 11 有同样的问题吗? 如果我身边有什么遗漏,请指导我。

设备:OPPO F17 Pro OS: 颜色 OS 11,Android 11 基于

注:

以上代码,使用三星设备,Android 基于 11 (OneUI 3.1),应用程序没有要求 运行时间,但在设置页面上重定向后,我授予位置权限并且应用程序是工作正常,关于 OPPO 我无法从设置页面授予权限。

尝试了什么:

  var permissions = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
    arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
} else {
    arrayOf(Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_COARSE_LOCATION)
}


private fun requestRequirdPermissions() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            permissionResultLauncher.launch(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
        }
        else
        {
            permissionResultLauncher.launch(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION ))
        }
    }

试试这个方法可能对你有帮助

fun checkPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            var permissions: ArrayList<String> = ArrayList<String>()
            permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION)
            val listPermissionsNeeded: ArrayList<String> = ArrayList()
            for (p in permissions) {
                var result = ContextCompat.checkSelfPermission(this, p!!)
                if (result != PackageManager.PERMISSION_GRANTED) {
                    listPermissionsNeeded.add(p)
                }
            }

            if (!listPermissionsNeeded.isEmpty()) {
                ActivityCompat.requestPermissions(
                        this,
                        listPermissionsNeeded.toTypedArray(),
                        CODE
                )
            } else {
                next()
            }
        } else {
            next()
        }
    }

    override fun onRequestPermissionsResult(
            requestc: Int,
            permissions: Array<String>,
            grantRes: IntArray
    ) {
        super.onRequestPermissionsResult(requestc, permissions, grantRes);
        when (requestc) {
            CODE -> {
                var isGrant = true
                if (grantRes.size > 0) {
                    for (i in 0 until grantResults.size) {
                        if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                            isGrant = false
                        }
                    }
                }
                if (isGrant) {
                    next()
                } else {
                    checkRationalePermission(permissions)
                }
            }
        }
    }


    var alertDialogRatinal: android.app.AlertDialog? = null
    fun checkRationale(permissions: Array<String>) {
        if (alertDialogRatinal != null && alertDialogRatinal!!.isShowing || permissions.size == 0) {
            return
        }
        var someDenied = false
        for (permission in permissions) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(
                    this@Activity,
            permission!!
                )
            ) {

            } else {
                if (ActivityCompat.checkSelfPermission(
                        this@Activity,
                permission
                    ) == PackageManager.PERMISSION_GRANTED
                ) {
                } else {
                    someDenied = true
                }
            }
        }
        if (someDenied) {
            val alertDialogBuilder =
                    android.app.AlertDialog.Builder(this@Activity)
            alertDialogRatinal = alertDialogBuilder.setTitle("Permissions Required")
                    .setMessage(
                            "Please open settings, go to permissions and allow them."
                    )
                    .setPositiveButton(
                            "Settings"
                    ) { dialog, which ->
                    val intent = Intent(
                    Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                    Uri.fromParts(
                            "package",
                            this@Activity.getPackageName(),
                null
                        )
                    )
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                startActivityForResult(intent, 100)
            }
                .setNegativeButton(
                    "Cancel"
            ) { dialog, which -> }
                .setCancelable(false)
                    .create()
            alertDialogRatinal!!.show()
        }
    }

我的问题已通过系统重置解决,但根据评论和文档,请遵循以下位置权限指南。

感谢Pawel的评论,

参考:

后台位置权限与其他权限不同。这是将位置权限从仅限前台提升到前台和后台的请求。

用户必须有意识地select“始终允许”才能执行此操作并授予后台位置权限。否则,该权限被视为被拒绝。

除非已授予前台位置,否则您甚至不能请求后台位置 - 当系统权限 activity 出现时,它应该已经有选项 2 或 3 selected。

https://developer.android.com/training/location/permissions#request-background-location

注:

当您的应用程序使用此后台位置时,请准备一个简短的视频,演示您的应用程序中的基于位置的功能,该功能需要在后台访问位置(当应用程序未使用时)。

https://support.google.com/googleplay/android-developer/answer/9799150

private val requestIdMultiplePermissions = 1
private val permissionsRequest: ArrayList<String> =
    arrayListOf(READ_CALENDAR
            , CAMERA)
findViewById<Button>(R.id.multiplePermissionBtn).setOnClickListener {
            if (checkMultipleRequestPermissions()) {
                doOperation()
            }
}
 private fun doOperation() {
        Toast.makeText(this, "Successfully granted", Toast.LENGTH_LONG).show()
    }
private fun checkMultipleRequestPermissions(): Boolean {
        val listPermissionsNeeded: MutableList<String> = ArrayList()

        for (p in permissionsRequest) {
            val result = ContextCompat.checkSelfPermission(this, p)
            if (result != PackageManager.PERMISSION_GRANTED) {
                listPermissionsNeeded.add(p)
            }
        }

        if (listPermissionsNeeded.isNotEmpty()) {
            ActivityCompat.requestPermissions(
                this,
                listPermissionsNeeded.toTypedArray(),
                requestIdMultiplePermissions
            )
            return false
        }
        return true
    }
override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == requestIdMultiplePermissions) {
            if (grantResults.isNotEmpty()) {
                var isGrant = true
                for (element in grantResults) {
                    if (element == PackageManager.PERMISSION_DENIED) {
                        isGrant = false
                    }
                }
                if (isGrant) {
                    doOperation()
                } else {
                    var someDenied = false
                    for (permission in permissions) {
                        if (!ActivityCompat.shouldShowRequestPermissionRationale(
                                this,
                                permission
                            )
                        )  {
                            if (ActivityCompat.checkSelfPermission(
                                    this,
                                    permission
                                ) == PackageManager.PERMISSION_DENIED
                            ) {
                                someDenied = true
                            }
                        }
                    }
                    if (someDenied) {
                        settingActivityOpen()
                    }else{
                        showDialogOK { _: DialogInterface?, which: Int ->
                            when (which) {
                                DialogInterface.BUTTON_POSITIVE -> checkMultipleRequestPermissions()
                                DialogInterface.BUTTON_NEGATIVE -> { }
                            }
                        }
                    }
                }
            }
        }
}
 private fun settingActivityOpen() {
        Toast.makeText(
            this,
            "Go to settings and enable permissions",
            Toast.LENGTH_LONG
        )
            .show()
        val i = Intent()
        i.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
        i.addCategory(Intent.CATEGORY_DEFAULT)
        i.data = Uri.parse("package:$packageName")
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
        i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
        startActivity(i)
}
private fun showDialogOK(okListener: DialogInterface.OnClickListener) {
        MaterialAlertDialogBuilder(this)
            .setMessage("All Permission required for this app")
            .setPositiveButton("OK", okListener)
            .setNegativeButton("Cancel", okListener)
            .create()
            .show()
}