124

I want to check a permission inside a fragment.

my code:

        // Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(getActivity(),
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {


            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
                    android.Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                        1);



                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

but onRequestPermissionsResult not called after allow or deny.

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {
            Log.e("test","0");
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.
                //yes

                Log.e("test","1");

                Intent intent = new Intent(getActivity(), MapsActivity.class);
                intent.putExtra("latitude", 35.694828);
                intent.putExtra("longitude", 51.378129);
                startActivity(intent);

            } else {
                utilityFunctions.showSweetAlertWarning(getActivity(),r.getString(R.string.str_warning_title_empty),
                        r.getString(R.string.str_you_must_allow_this_permission_toast),
                        r.getString(R.string.str_warning_btn_login));

                Log.e("test","2");
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}
Sergio
  • 27,326
  • 8
  • 128
  • 149
S.M_Emamian
  • 17,005
  • 37
  • 135
  • 254
  • Possible duplicate of [Request runtime permissions from v4.Fragment and have callback go to Fragment?](http://stackoverflow.com/questions/32890702/request-runtime-permissions-from-v4-fragment-and-have-callback-go-to-fragment) – R. Zagórski Nov 23 '16 at 09:40

16 Answers16

302

This is how I did, it works for me. Thanks!

For Activity :

ActivityCompat.requestPermissions(this, permissionsList, REQUEST_CODE);

For Fragment :

requestPermissions(permissionsList, REQUEST_CODE);
ThetNaing Mizo
  • 4,049
  • 2
  • 14
  • 15
94

Fragment has requestPermissions() and onRequestPermissionsResult() methods, use it.

But checkSelfPermission() is from ActivityCompat (not require Activity, only Context).

if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    requestPermissions( //Method of Fragment
        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
        REQUEST_PERMISSIONS_CODE_WRITE_STORAGE
    );
} else {
    downloadImage();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_PERMISSIONS_CODE_WRITE_STORAGE) {
        if (permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            proceedWithSdCard();
        }
    }
}
JerabekJakub
  • 5,268
  • 4
  • 26
  • 33
Evgeny Nozdrev
  • 1,530
  • 12
  • 15
75

I have done following to check a permission inside a fragment.

if (ActivityCompat.checkSelfPermission(getContext(),
            android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(getContext(),
                    android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
         requestPermissions(getActivity(),
                new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION,
                        android.Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_LOCATION);
    } else {
        Log.e("DB", "PERMISSION GRANTED");
    }

Update

Since Fragment.requestPermissions is now deprecated, Google advises using registerForActivityResult instead.

I have done the request like this:

val permissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted ->
    if (isGranted) {
        // Do if the permission is granted
    }
    else {
        // Do otherwise
    }
}

permissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

For more documentation on this method you can check this link.

rookieDeveloper
  • 2,459
  • 1
  • 22
  • 44
  • 5
    We still need to ask for permission if the user hasn't granted it. – Karan Thakkar May 09 '17 at 06:30
  • 22
    Remember that if you do this, your request permission result will come to the activity that started your fragment. See *ThetNaing Mizo*'s answer for a way to receive result in your fragment. – lsrom Apr 18 '18 at 13:54
  • 1
    why requestPermissions is depricated , any updated ans – Bolt UIX May 29 '21 at 04:51
30

Check Permissions from Fragment (the 2021 way)

The registerForActivityResult() method in fragment is now deprecated. The deprecation message suggests to use registerForActivityResult. So after some trial and errors, here is the 2021 way:

Suppose your fragment's name is AwesomeFragment. Then in the constructor (before the fragment's onCreate method to be precise), you initialize ActivityResultLauncher<String[]> activityResultLauncher.

java version

private ActivityResultLauncher<String[]> activityResultLauncher; 

public AwrsomeFragment() {
 activityResultLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
            @Override
            public void onActivityResult(Map<String, Boolean> result) {
                Log.e("activityResultLauncher", ""+result.toString());
                Boolean areAllGranted = true;
                for(Boolean b : result.values()) {
                    areAllGranted = areAllGranted && b;
                }

                if(areAllGranted) {
                    capturePhoto();
                }
            }
        });
}

Then maybe on some button click, you invoke the launch method:

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        String[] appPerms;
        appPerms = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
        this.cameraClick.setOnClickListener(v -> {
            this.activityResultLauncher.launch(appPerms);
        });
    }

kotlin version

private var activityResultLauncher: ActivityResultLauncher<Array<String>>
init{
this.activityResultLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()) {result ->
        var allAreGranted = true
        for(b in result.values) {
            allAreGranted = allAreGranted && b
        }
        
        if(allAreGranted) {
          capturePhoto()            
        }
    }
}

// --- ---
 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
// ... ... init views / binding... ...
   someBtn.setOnClickListener{
        val appPerms = arrayOf(
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA
        )
        activityResultLauncher.launch(appPerms)
  }       
}
Qazi Fahim Farhan
  • 2,066
  • 1
  • 14
  • 26
8

To handle permissions in a Fragment call requestPermissions method. If you override onRequestPermissionsResult method in both fragment and activity, containing that fragment, make sure to call super.onRequestPermissionsResult(...) in the activity method to propagate call to the onRequestPermissionsResult method in the fragment.

Sergio
  • 27,326
  • 8
  • 128
  • 149
6

Using Kotlin, you call requestPermissions(arrayOf(Manifest.permission.THE_PERMISSION_CODE_YOU_WANT), PERMISSION_REQUEST_CODE) and add the following override to your fragment

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out kotlin.String>, grantResults: IntArray): Unit {

}
Erik
  • 1,246
  • 13
  • 31
4

onRequestPermissionsResult is invoked in the activity not the fragment. Try overriding onRequestPermissionsResult in the activity instead.

Ryan
  • 1,863
  • 13
  • 20
  • While this is true, it lacks explanation of why this is true and how to fix it - how to get `onRequestPermissionResult` in fragment. Both the explanation and way of receiving the result in fragmented are explained in the answer by *ThetNaing Mizo*. – lsrom Apr 18 '18 at 13:33
  • Thanks, i was wondering why my code is not working inside Fragment – Azizjon Kholmatov Oct 01 '19 at 16:03
3

What worked for me was calling the onRequestPermissionsResult method in the activity inside which fragment is implemented rather than calling it in fragment itself. Inside onCreateView method in fragment:

    Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE);

            if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_MEDIA);
            }else{
                //Do your work
                fetchMethod();
            }

        }
});

In the Activity which helps to implement fragment, outside of onCreate method:

    @Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_MEDIA:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                fetchMethod();

            }else{
                Toast.makeText(getApplicationContext(), "Permission not granted!", Toast.LENGTH_SHORT).show();
            }
            break;

        default:
            break;
    }
}
2

If you closed your permission of app from settings , you can not open your permission from code or your android version lower than Marshmallow.

You can check this documentation https://developer.android.com/training/permissions/requesting.html And this is a example https://www.learn2crack.com/2015/10/android-marshmallow-permissions.html

0

I was getting tripped up using checkSelfPermission() in a Fragment and wondering what would be the best approach for Context being null (Kotlin specific)... should I use !! or something else?

I went with something else based on code I found in iosched. Have a look at the sample below, and remember, before the Fragment is attached to an Activity, the Context will be null.

private fun fineLocationPermissionApproved(): Boolean {

    val context = context ?: return false

    return PackageManager.PERMISSION_GRANTED == checkSelfPermission(
        context,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}
codingjeremy
  • 5,215
  • 1
  • 36
  • 39
0

To check permission within a fragment, I did the following.

Before onCreateView in Fragment add the following,

private final int STORAGE_PERMISSION_CODE = 1;

private Activity mActivity;
 
 @Override
    public void onAttach(@NotNull Context context) {
        super.onAttach(context);
        mActivity = (Activity) context;
    }

Check the permission,

if ((ContextCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED))
            {
                if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    new AlertDialog.Builder(mActivity)
                            .setTitle("Permission needed")
                            .setMessage("Allow "+getResources().getString(R.string.app_name)+" to access your storage?")
                            .setPositiveButton("ok", (dialog, which) -> ActivityCompat.requestPermissions(mActivity,
                                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE)
                            )
                            .setNegativeButton("cancel", (dialog, which) -> {
                                dialog.dismiss();
                                Toast.makeText(mActivity, "Please allow this permission!", Toast.LENGTH_SHORT).show();
                            })
                            .create().show();
                } else {
                    ActivityCompat.requestPermissions(mActivity,
                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE);
                }
            }

Place the following code in MainActivity to enable permission from the app's settings if the user denied the permission forever.

@Override
            public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
            {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                if (requestCode == STORAGE_PERMISSION_CODE) {
        
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(this, "Permission GRANTED", Toast.LENGTH_SHORT).show();
                    } else {
        
                        //Now further we check if used denied permanently or not
                        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                            // 1. The user has temporarily denied permission.
                            Toast.makeText(MainActivity.this, "Permission DENIED", Toast.LENGTH_SHORT).show();
        
                        } else {
                            // 2. Permission has been denied.
                            // From here, you can access the setting's page.
        
                            new AlertDialog.Builder(MainActivity.this)
                                    .setTitle("Permission Required")
                                    .setMessage("This permission was already declined by you. Please open settings, go to \"Permissions\", and allow the permission.")
                                    .setPositiveButton("Settings", (dialog, which) -> {
                                        final Intent i = new Intent();
                                        i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                        i.addCategory(Intent.CATEGORY_DEFAULT);
                                        i.setData(Uri.parse("package:" + MainActivity.this.getPackageName()));
                                        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                        i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                                        i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                                        MainActivity.this.startActivity(i);
                                    })
                                    .setNegativeButton("cancel", (dialog, which) -> {
                                        dialog.dismiss();
                                        Toast.makeText(MainActivity.this, "Please allow this permission!", Toast.LENGTH_SHORT).show();
                                    })
                                    .create().show();
                        }
        
                    }
                }
            }
HAZEEM JOONUS
  • 483
  • 6
  • 9
0

If anyone is interested in Kotlin call permission.

    private fun directCall() {
    val numberText = phoneNo
    val intent = Intent(Intent.ACTION_CALL)
    intent.data = Uri.parse("tel:$numberText")
    if (ActivityCompat.checkSelfPermission(requireContext(),Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED)
    {
        if(ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.CALL_PHONE)){
                Toast.makeText(requireContext(), "Permission denied.", Toast.LENGTH_LONG).show()
                return //<-- Check user input history if user already denied then second time not request and not ask.
        }
        else{
            requestPermissions(arrayOf(Manifest.permission.CALL_PHONE),1)
            return //<--return will call onRequestPermissionsResult and wait for user input.
        }
    }
    startActivity(intent)
}

override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {
    if (requestCode == requestPhoneCall && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        directCall()
    }else{
        Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_LONG).show()
        return
    }
}
sandip
  • 394
  • 1
  • 4
  • 11
0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission( getActivity(),Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {

its working in my case

0

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ActivityCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{ Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS); //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method } else { // Android version is lesser than 6.0 or the permission is already granted. List contacts = getContactNames(); }

0

checkSelfPermission not working in fragments?? we can try this code

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 
ActivityCompat.checkSelfPermission( 
getActivity(),Manifest.permission.READ_CONTACTS) != 
PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]. 
{Manifest.permission.READ_CONTACTS}, 
PERMISSIONS_REQUEST_READ_CONTACTS); //After this point you wait for 
callback in onRequestPermissionsResult(int, String[], int[]) overriden 
method } else { // Android version is lesser than 6.0 or the permission 
is already granted. List<String> contacts = getContactNames();
}
Kumar Saurabh
  • 2,297
  • 5
  • 29
  • 43
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 11 '22 at 13:00
0

To check permissions inside a fragment

we should use requestPermissions instead of ActivityCompat.requestPermissions

// Replace with Permissions you need to check.
requestPermissions(arrayOf(
    "android.permission.ACCESS_COARSE_LOCATION",
    "android.permission.ACCESS_FINE_LOCATION"
), YOUR_REQUEST_CODE)

Then override onRequestPermissionsResult as uduel

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == YOUR_REQUEST_CODE) {
        if (
            grantResults.isNotEmpty() &&
            grantResults[0] == PackageManager.PERMISSION_GRANTED
        ) {
            // Permission granted
            Log.d("onRequestPermissionsResult", "permission granted")
        } else {
            // Permission was denied. Display an error message.
            Log.d("onRequestPermissionsResult", "permission denied")
        }
    }
}
Marawan Mamdouh
  • 584
  • 1
  • 6
  • 15