如何使用导航组件管理权限请求代码?
How to Manage the permission request code using Navigation Component?
如何使用导航组件管理权限请求代码?
我引用了太多网站和堆栈 link,其中 none 有效,仍然显示已弃用的 Waring
Google 参考 link:
https://developer.android.com/training/permissions/requesting#manage-request-code-yourself
代码::在片段
中使用以下代码
private fun checkMultiplePermissions() {
// check permission first
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// request the permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
} else {
proceedAfterPermission() // has the permission.
}
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
myLog("log", "location code : $requestCode")
when (requestCode) {
100 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted.
proceedAfterPermission() // permission was granted.
myLog("log", "location granted")
} else {
// permission denied.
myLog("log", "location denied")
}
return
}
}
}
Fragment.kt : 完整代码
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
class FragmentPermission : Fragment() {
private var binding: FragmentPermisionBinding ?= null
// Kotlin
//implementation "androidx.fragment:fragment-ktx:1.3.4"
//https://developer.android.com/training/permissions/requesting#manage-request-code-yourself
// <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
binding = FragmentPermisionBinding.inflate(inflater, container, false)
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// request the permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
} else {
//proceedAfterPermission() // has the permission.
}
return binding!!.root
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
myLog("location3", "location code : $requestCode")
when (requestCode) {
100 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted.
//proceedAfterPermission() // permission was granted.
myLog("location3", "location granted")
} else {
// permission denied.
myLog("location3", "location denied")
}
return
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding=null
}
}
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
This method is deprecated.
use registerForActivityResult(ActivityResultContract, ActivityResultCallback) passing in a ActivityResultContracts.RequestMultiplePermissions object for the ActivityResultContract and handling the result in the callback.
requestPermissions()
API is deprecated, and replaced by registerForActivityResult(ActivityResultContract, ActivityResultCallback)
传入一个 ActivityResultContracts.RequestMultiplePermissions
对象
对于 ActivityResultContract
并在回调中处理结果。
首先 activity-ktx build.gradle
新的 API:
需要模块级依赖
implementation 'androidx.activity:activity-ktx:1.3.0-beta01'
然后 ActivityResultCallback
回调需要实现并作为 registerForActivityResult
的参数传递。此接口具有处理用户对权限请求对话框的响应的回调。
要显示权限对话框,请在 registerForActivityResult
函数返回的 ActivityResultLauncher
实例上调用 launch()
方法。
因此,创建 ActivityResultLauncher
的实例并实施回调以处理用户响应:
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) { // Do something if permission granted
Log.d("LOG_TAG", "permission granted by the user")
} else { // Do something as the permission is not granted
Log.d("LOG_TAG", "permission denied by the user")
}
}
然后使用launch
函数请求权限:
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
更新
一次请求多个权限:您需要传递数组
启动()的权限。 ActivityResultCallback
returns a Map<String, Boolean>
以权限为键,其授权状态为值:
然后使用ActivityResultContracts.RequestMultiplePermissions()
如下:
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.e("LOG_TAG", "${it.key} = ${it.value}")
}
}
// Usage:
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA
)
)
将其应用于共享代码:
class FragmentPermission : Fragment() {
private var binding: FragmentPermisionBinding ?= null
//...
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) { // permission is granted
proceedAfterPermission()
} else {
// handle permission denial
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
binding = FragmentPermisionBinding.inflate(inflater, container, false)
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else {
proceedAfterPermission()
}
return binding!!.root
}
//.... rest of your code
}
您缺少为下面的函数传递参数 Activity
public static void requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)
如果没有请求权限,请检查您是否已经拥有权限。
在下面的代码中,您需要传递 activity.
if (ContextCompat.checkSelfPermission(
this.applicationContext,
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
//already you have permission
} else {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
)
}
使用这个获取用户响应。
/**
* Handles the result of the request for location permissions.
*/
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
mLocationPermissionGranted = false
when (requestCode) {
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.size > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
// user granted location call your function
}
}
}
}
带有 NavContoller 的 PermissionFragment。科特林
class PermissionFragment : Fragment() {
private val PERMISSIONS_REQUIRED = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.NFC,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
private var _binding: FragmentPermissionBinding? = null
private val binding get() = _binding!!
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
val granted = it.value
val permission = it.key
if (!granted) {
val neverAskAgain = !ActivityCompat.shouldShowRequestPermissionRationale(
requireActivity(),
permission
)
if (neverAskAgain) {
//user click "never ask again"
} else {
//show explain dialog
}
return@registerForActivityResult
}
}
goHome()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentPermissionBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
/*don't call this in onCreateView(), NavController has not been created yet
*
* don't call this in onResume(), if user selected "never ask again" - checkAppPermission() can go to dead loop after dialog show */
checkAppPermission()
}
private fun checkAppPermission() {
PERMISSIONS_REQUIRED.forEach { permission ->
if (ContextCompat.checkSelfPermission(requireContext(), permission) ==
PackageManager.PERMISSION_DENIED
) {
requestMultiplePermissions.launch(PERMISSIONS_REQUIRED)
return
}
}
goHome()
}
private fun goHome() {
val navController = requireActivity().findNavController(R.id.nav_host_fragment_content_main)
navController.navigate(R.id.nav_home)
}
}
如何使用导航组件管理权限请求代码?
我引用了太多网站和堆栈 link,其中 none 有效,仍然显示已弃用的 Waring
Google 参考 link: https://developer.android.com/training/permissions/requesting#manage-request-code-yourself
代码::在片段
中使用以下代码 private fun checkMultiplePermissions() {
// check permission first
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// request the permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
} else {
proceedAfterPermission() // has the permission.
}
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
myLog("log", "location code : $requestCode")
when (requestCode) {
100 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted.
proceedAfterPermission() // permission was granted.
myLog("log", "location granted")
} else {
// permission denied.
myLog("log", "location denied")
}
return
}
}
}
Fragment.kt : 完整代码
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
class FragmentPermission : Fragment() {
private var binding: FragmentPermisionBinding ?= null
// Kotlin
//implementation "androidx.fragment:fragment-ktx:1.3.4"
//https://developer.android.com/training/permissions/requesting#manage-request-code-yourself
// <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
binding = FragmentPermisionBinding.inflate(inflater, container, false)
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// request the permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
} else {
//proceedAfterPermission() // has the permission.
}
return binding!!.root
}
override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>, grantResults: IntArray) {
myLog("location3", "location code : $requestCode")
when (requestCode) {
100 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted.
//proceedAfterPermission() // permission was granted.
myLog("location3", "location granted")
} else {
// permission denied.
myLog("location3", "location denied")
}
return
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding=null
}
}
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)
This method is deprecated. use registerForActivityResult(ActivityResultContract, ActivityResultCallback) passing in a ActivityResultContracts.RequestMultiplePermissions object for the ActivityResultContract and handling the result in the callback.
requestPermissions()
API is deprecated, and replaced by registerForActivityResult(ActivityResultContract, ActivityResultCallback)
传入一个 ActivityResultContracts.RequestMultiplePermissions
对象
对于 ActivityResultContract
并在回调中处理结果。
首先 activity-ktx build.gradle
新的 API:
implementation 'androidx.activity:activity-ktx:1.3.0-beta01'
然后 ActivityResultCallback
回调需要实现并作为 registerForActivityResult
的参数传递。此接口具有处理用户对权限请求对话框的响应的回调。
要显示权限对话框,请在 registerForActivityResult
函数返回的 ActivityResultLauncher
实例上调用 launch()
方法。
因此,创建 ActivityResultLauncher
的实例并实施回调以处理用户响应:
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) { // Do something if permission granted
Log.d("LOG_TAG", "permission granted by the user")
} else { // Do something as the permission is not granted
Log.d("LOG_TAG", "permission denied by the user")
}
}
然后使用launch
函数请求权限:
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
更新
一次请求多个权限:您需要传递数组
启动()的权限。 ActivityResultCallback
returns a Map<String, Boolean>
以权限为键,其授权状态为值:
然后使用ActivityResultContracts.RequestMultiplePermissions()
如下:
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.e("LOG_TAG", "${it.key} = ${it.value}")
}
}
// Usage:
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA
)
)
将其应用于共享代码:
class FragmentPermission : Fragment() {
private var binding: FragmentPermisionBinding ?= null
//...
private val requestPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) { // permission is granted
proceedAfterPermission()
} else {
// handle permission denial
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
binding = FragmentPermisionBinding.inflate(inflater, container, false)
if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else {
proceedAfterPermission()
}
return binding!!.root
}
//.... rest of your code
}
您缺少为下面的函数传递参数 Activity
public static void requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)
如果没有请求权限,请检查您是否已经拥有权限。 在下面的代码中,您需要传递 activity.
if (ContextCompat.checkSelfPermission(
this.applicationContext,
Manifest.permission.ACCESS_FINE_LOCATION
)
== PackageManager.PERMISSION_GRANTED
) {
//already you have permission
} else {
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
)
}
使用这个获取用户响应。
/**
* Handles the result of the request for location permissions.
*/
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
mLocationPermissionGranted = false
when (requestCode) {
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.size > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
// user granted location call your function
}
}
}
}
带有 NavContoller 的 PermissionFragment。科特林
class PermissionFragment : Fragment() {
private val PERMISSIONS_REQUIRED = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.NFC,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
private var _binding: FragmentPermissionBinding? = null
private val binding get() = _binding!!
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
val granted = it.value
val permission = it.key
if (!granted) {
val neverAskAgain = !ActivityCompat.shouldShowRequestPermissionRationale(
requireActivity(),
permission
)
if (neverAskAgain) {
//user click "never ask again"
} else {
//show explain dialog
}
return@registerForActivityResult
}
}
goHome()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentPermissionBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
/*don't call this in onCreateView(), NavController has not been created yet
*
* don't call this in onResume(), if user selected "never ask again" - checkAppPermission() can go to dead loop after dialog show */
checkAppPermission()
}
private fun checkAppPermission() {
PERMISSIONS_REQUIRED.forEach { permission ->
if (ContextCompat.checkSelfPermission(requireContext(), permission) ==
PackageManager.PERMISSION_DENIED
) {
requestMultiplePermissions.launch(PERMISSIONS_REQUIRED)
return
}
}
goHome()
}
private fun goHome() {
val navController = requireActivity().findNavController(R.id.nav_host_fragment_content_main)
navController.navigate(R.id.nav_home)
}
}