如何使用导航组件管理权限请求代码?

8

如何使用导航组件管理权限请求代码?

我查阅了很多网站和Stack链接,但都没有用,仍然显示过时的警告 enter image description here

Google参考链接: 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
    }
}

2
你是否按照上面的指南进行操作?它展示了如何使用非废弃的API。 - ianhanniballake
我更新了我的全部代码。 - Bolt UIX
那段代码没有遵循使用非弃用API的指南。你尝试过那些API吗? - ianhanniballake
是的,已添加实现 "androidx.fragment:fragment-ktx:1.3.4",请参阅此主题:自行管理权限请求代码:https://developer.android.com/training/permissions/requesting#manage-request-code-yourself(引用代码)。 - Bolt UIX
是的,那是使用旧的、已弃用的API的指南...如果你想避免使用已弃用的API,你必须跳到我特别链接的那一节。 - ianhanniballake
3个回答

13
requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 100)

此方法已过时。使用 registerForActivityResult(ActivityResultContract, ActivityResultCallback),传入一个ActivityResultContracts.RequestMultiplePermissions对象用作 ActivityResultContract,并在回调中处理结果。

requestPermissions() API已被弃用,已被新API所取代。

首先需要在build.gradle模块级别依赖项中添加activity-ktx

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

更新

如果需要一次请求多个权限:您需要将权限数组传递给launch()。 ActivityResultCallback 返回一个以权限为键、授权状态为值的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

}

0

使用NavController的PermissionFragment。Kotlin。

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

-1

您忘记传递以下函数的参数Activity

 public static void requestPermissions(final @NonNull Activity activity,
            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)

检查您是否已经获得了权限,如果没有,请请求权限。 在下面的代码中,您需要传递您的活动。
            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
                }
            }
        }
    }

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