Search code examples
androidkotlinandroid-permissionsandroid-architecture-componentsregisterforactivityresult

How to Manage the permission request code using Navigation Component?


How to Manage the permission request code using Navigation Component?

I referred too many website & stack links, none of it worked, still showing deprecated Waring enter image description here

Google Ref link: https://developer.android.com/training/permissions/requesting#manage-request-code-yourself

Code: :Using below code in fragment

  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 : full code

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

Solution

  • 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) passing in a ActivityResultContracts.RequestMultiplePermissions object for the ActivityResultContract and handling the result in the callback.

    First the activity-ktx build.gradle module level dependency is needed for the the new API:

    implementation 'androidx.activity:activity-ktx:1.3.0-beta01'
    

    Then ActivityResultCallback callback need to be implemented and passed as a parameter of the registerForActivityResult. This interface has callbacks that handle the user response to the permission request dialog.

    To display the permissions dialog, call the launch() method on the instance of ActivityResultLauncher that is returned by the registerForActivityResult function.

    So, create an instance of ActivityResultLauncher & implement the callback to handle the user response:

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

    Then request the permission by using the launch function:

    if (ContextCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
    }
    

    UPDATE

    For requesting multiple of permissions at once: You need to pass array of permission to launch(). ActivityResultCallback returns a Map<String, Boolean> with permission as key and its grant status as value:

    Then use ActivityResultContracts.RequestMultiplePermissions() as follows:

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

    Applying that on the shared code:

    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
    
    }