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()
}
几天前,代码运行良好,没有权限问题。
我无法在 运行 时授予权限,在从设置中授予权限时也遇到了问题。 (应用权限详细信息页面)。
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()
}