Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I tried to implement request permissions for writing and reading from storage. Everything worked good but today Android showed me that the method onRequestPermissionsResult(...) is deprecated. There are so many questions about this topic in StackOverflow, but unfortunately, they are outdated.

I called the methods below in a fragment.

It was suggested simply to call:

requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
StorageKeys.STORAGE_PERMISSION_CODE)

instead of my approach:

ActivityCompat.requestPermissions(getActivity(),
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
StorageKeys.STORAGE_PERMISSION_CODE))

But both of them show that onRequestPermissionsResult(...) is deprecated.

Here is my onRequestPermissionsResult(...)-method:

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                         @NonNull int[] grantResults) {
    if (requestCode == StorageKeys.STORAGE_PERMISSION_CODE) {
      if (grantResults.length > 0
          && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        exportBibTex.createBibFile();
        exportBibTex.writeBibFile(exportBibTex
            .getBibDataLibrary(libraryModel, bookDao, noteDao));
        Toast.makeText(getContext(),
            getString(R.string.exported_file_stored_in) + '\n'
                + File.separator + StorageKeys.DOWNLOAD_FOLDER + File.separator + fileName
                + StorageKeys.BIB_FILE_TYPE, Toast.LENGTH_LONG).show();
      } else {
        Toast.makeText(getContext(), R.string.storage_permission_denied,
            Toast.LENGTH_SHORT).show();

Here is a simple alert dialog, in which I call the onRequestPermissionsResult(...):

  private void showRequestPermissionDialog() {
    AlertDialog.Builder reqAlertDialog = new AlertDialog.Builder(getContext());
    reqAlertDialog.setTitle(R.string.storage_permission_needed);
    reqAlertDialog.setMessage(R.string.storage_permission_alert_msg);
    reqAlertDialog.setPositiveButton(R.string.ok,
        (dialog, which) -> ActivityCompat.requestPermissions(getActivity(),
            new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
            StorageKeys.STORAGE_PERMISSION_CODE));
    reqAlertDialog.setNegativeButton(R.string.cancel,
        (dialog, which) -> dialog.dismiss());
    reqAlertDialog.create().show();

Is there any alternative for onRequestPermissionsResult(...), that I can use?

onRequestPermissionsResult() is not deprecated in androidx.appcompat.app.AppCompatActivity. did you use which Activity class? – Daniel.Wang Mar 9, 2021 at 17:35 I use it in a fragment. The explanation from Android Studio is: "Overrides deprecated method in 'androidx.fragment.app.Fragment' " – ashley Mar 9, 2021 at 17:43 You should check out this official guide: youtu.be/oP-zXjkT0C0. onActivityResult() and onRequestPermissionResult() are all deprecated now. – Sam Chen May 28, 2021 at 16:59

The onRequestPermissionsResult() method is deprecated in androidx.fragment.app.Fragment.

So you may use registerForActivityResult() method instead of onRequestPermissionsResult().

You can refer this URL.

Following is Kotlin code, but you can refer it:

val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted ->
    if (isGranted) {
        // PERMISSION GRANTED
    } else {
        // PERMISSION NOT GRANTED
// Ex. Launching ACCESS_FINE_LOCATION permission.
private fun startLocationPermissionRequest() {
    requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

I added java code from following URL.
How to get a permission request in new ActivityResult API (1.3.0-alpha05)?

private ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(
    new ActivityResultContracts.RequestPermission(),
    new ActivityResultCallback<Boolean>() {
        @Override
        public void onActivityResult(Boolean result) {
            if (result) {
                // PERMISSION GRANTED
            } else {
                // PERMISSION NOT GRANTED
// Ex. Launch the permission window -- this is in onCreateView()
floatingActionButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION);    

You can also request multiple permissions:

val requestMultiplePermissions = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
    permissions.entries.forEach {
        Log.d("DEBUG", "${it.key} = ${it.value}")
requestMultiplePermissions.launch(
    arrayOf(
        Manifest.permission.READ_CONTACTS,
        Manifest.permission.ACCESS_FINE_LOCATION
                Thanks, can I use the ActivityResultLauncher(..) for multiple permissions? For example        requestPermissionLauncher.launch(           Manifest.permission.WRITE_EXTERNAL_STORAGE);       requestPermissionLauncher.launch(           Manifest.permission.READ_EXTERNAL_STORAGE);
– ashley
                Mar 9, 2021 at 18:35
                So you need to use ActivityResultContracts.RequestMultiplePermissions() when call registerForActivityResult() method.
– Daniel.Wang
                Mar 9, 2021 at 18:47
                This answer is displaying an error: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public operator fun <T, R> DeepRecursiveFunction<TypeVariable(T), TypeVariable(R)>.invoke(value: TypeVariable(T)): TypeVariable(R) defined in kotlin
– Khris Vandal
                Dec 12, 2022 at 13:26
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
class MyFragment : Fragment() {
companion object {
    val TAG: String = MyFragment::class.java.simpleName
    var PERMISSIONS = arrayOf(
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
private val permReqLauncher =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
        val granted = permissions.entries.all {
            it.value == true
        if (granted) {
            displayCameraFragment()
private fun takePhoto() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        displayCameraFragment()
        return
    activity?.let {
        if (hasPermissions(activity as Context, PERMISSIONS)) {
            displayCameraFragment()
        } else {
            permReqLauncher.launch(
                PERMISSIONS
// util method
private fun hasPermissions(context: Context, permissions: Array<String>): Boolean = permissions.all {
    ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
private fun displayCameraFragment() {
    // open camera fragment

Example use:

 private fun permissionSetup() {
    val permission = ContextCompat.checkSelfPermission(
        requireContext(), Manifest.permission.READ_CONTACTS)
    if (permission != PackageManager.PERMISSION_GRANTED) {
        permissionsResultCallback.launch(Manifest.permission.READ_CONTACTS)
    } else {
        println("Permission isGranted")
private val permissionsResultCallback = registerForActivityResult(
    ActivityResultContracts.RequestPermission()){
    when (it) {
        true -> { println("Permission has been granted by user") }
        false -> {
            Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show()
            dialog.dismiss()

Register the permissions callback in your activity or fragment. which handle user permission Example-Storage permission

 private final ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(
        new ActivityResultContracts.RequestPermission(),
        result -> {
            if (result) {
                  //Permission granted
            } else {
               //permission denied
                if (ActivityCompat.shouldShowRequestPermissionRationale(activity, WRITE_EXTERNAL_STORAGE)) {
                    //show permission snackbar
                } else {
                   //display error dialog

Ask for the permission.The registered ActivityResultCallback gets the result of this request.

if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED) {
                    requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                } else {
                    //Permission already granted 

Suppose we need to take some permissions like audio and camera. Then we can put it on a variable of array.

  private val REQUESTED_PERMISSIONS =
            arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)

This registerForActivityResult invoke when we launch with multiple permission array.

private val requestMultiplePermissions = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        permissions.entries.forEach {
            Log.d("DEBUG", "${it.key} = ${it.value}")
            if (!it.value){
                return@registerForActivityResult
        init()

Now we make a function to check permission is already granted or not.

   private fun checkSelfPermission(): Boolean {
        return !(ContextCompat.checkSelfPermission(
            requireContext(),
            REQUESTED_PERMISSIONS[0]
        ) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(
                    requireContext(),
                    REQUESTED_PERMISSIONS[1]
                ) != PackageManager.PERMISSION_GRANTED)

Now we check permission is granted or not from onCreate method. If permission is not granted then we invoke requestMultiplePermissions.launch(REQUESTED_PERMISSIONS) like

        super.onCreate(savedInstanceState)
        if (!checkSelfPermission()) {
            requestMultiplePermissions.launch(REQUESTED_PERMISSIONS)
    } != PackageManager.PERMISSION_GRANTED) {
    Log.d(TAG, "Request Permissions")
    requestMultiplePermissions.launch(
        arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE))
 } else {
        Log.d(TAG, "Permission Already Granted")
private val requestMultiplePermissions =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
        permissions.entries.forEach {
            Log.d(TAG, "${it.key} = ${it.value}")
        if (permissions[READ_EXTERNAL_STORAGE] == true && permissions[WRITE_EXTERNAL_STORAGE] == true) {
            Log.d(TAG, "Permission granted")
        } else {
            Log.d(TAG, "Permission not granted")

Most of the answers address the OP requirement. But I have found few things that are missing so I thought to provide a complete example (in Koltin)

class ProfileFragment : Fragment(){
private lateinit var permissionRequest : ActivityResultLauncher<Array<String>>
companion object {
    val LOCATION_PERMISSIONS = arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    private fun getGpsLocation() {
        if(activity != null){
            permissionRequest.launch(LOCATION_PERMISSIONS)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.locBtn.setOnClickListener { getGpsLocation() }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        registerPermissionRequest()
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_profile, container, false)
        return binding.root
    private fun registerPermissionRequest(){
            var permissionCount = 0
            permissionRequest = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
                permissions.entries.forEach {
                    if(it.value){
                        permissionCount++
                if(permissionCount == 2){
                    getMyLocation()

The things that are missing are

A)Fragments must call registerForActivityResult() before they are created (i.e. initialization, onAttach(), or onCreate()). Other wise it won't work and the app would crash.

Error:

java.lang.IllegalStateException: Fragment ProfileFragment{bf12414} (210ad5a1-3286-4586-a48f-deac1d8e3eef id=0x7f09008b) is attempting to registerForActivityResult after being created. Fragments must call registerForActivityResult() before they are created (i.e. initialization, onAttach(), or onCreate()).

B) It is recommended to request permission when it is really needed. In my example when user clicks on Button with id locBtn, permission dialog is shown rather than showing when activity/fragment is created.

In your case you call registerForActivityResult in onCreateView. In my experience it is usually enough to create permissionRequest variable in onCreate, onAttach or as a initialized local variable. In onCreate we should check an order of calls. It would be better to create the variable before other operators, because sometimes it can be called too early. – CoolMind Aug 10, 2021 at 18:33 @CoolMind, I totally agree with you. I did mention the same in the description. I have corrected that now. Thanks. – tanni tanna Sep 19, 2021 at 9:58

Please refer to the official documentation: https://developer.android.com/training/permissions/requesting

Review the following, which can be found in the documentation.

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.

After which, launch the request

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    //Is not needed for it to work, but is a good practice as it plays a role
    //in letting user know why the permission is needed.
    shouldShowRequestPermissionRationale(...) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected. In this UI,
        // include a "cancel" or "no thanks" button that allows the user to
        // continue using your app without granting the permission.
        showInContextUI(...)
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)

Try this in in your pubspec.yamal under flutter section:

 plugin:
    androidPackage: com.ly.permission
    pluginClass: PermissionPlugin

It works with me.

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Community Apr 15, 2022 at 0:20

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.