【问题标题】:Android 11 Runtime PermissionsAndroid 11 运行时权限
【发布时间】:2021-10-05 07:45:29
【问题描述】:

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

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

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
    }

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

这是特定于操作系统的吗?有人遇到与 ColorOS 11 相同的问题吗? 如果我身边缺少任何东西,请指导我。

设备:OPPO F17 Pro 操作系统:Color 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 ))
        }
    }

【问题讨论】:

  • “几天前,代码运行良好,没有权限问题”。那么从那以后你有什么改变呢?
  • 什么都没变,和以前一样,这就是我来这里的原因,因为我从2小时就开始检查了。
  • 您不能一次请求所有不同的位置权限。阅读文档。
  • 谢谢,但不确定,我已经尝试使用名为 ACCESS_BACKGROUND_LOCATION 的单一权限仍然无法正常工作。
  • @Ashvinsolanki 您必须逐步请求位置许可:请求前景 (ACCESS_FINE_LOCATION) 然后在获得许可后您可以请求背景 (ACCESS_BACKGROUND_LOCATION)。如果您在没有先授予前景的情况下要求背景或同时要求两者,则请求会立即被拒绝,甚至不会显示对话框。见stackoverflow.com/questions/66321232/…

标签: android kotlin permissions oppo


【解决方案1】:

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

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()
        }
    }

【讨论】:

  • 我建议你使用新的 API "ActivityResultContracts"
【解决方案2】:

我的问题已通过系统重置得到解决,但根据 cmets 和文档,请按照以下指南获取位置权限。

感谢Pawelcmets,

参考:https://stackoverflow.com/a/66321942/9909365

后台位置权限不像其他权限那样工作。这是一个将位置权限从仅前台提升到前台和后台的请求。

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

除非已授予前台位置,否则您甚至无法请求后台位置 - 当系统权限活动显示时,它应该已经选择了选项 2 或 3。

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

注意:

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

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

【讨论】:

    【解决方案3】:
    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()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 2017-10-17
      • 1970-01-01
      • 1970-01-01
      • 2022-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多