How to check permission in fragment
JavaAndroidKotlinAndroid FragmentsAndroid PermissionsJava Problem Overview
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
}
}
Java Solutions
Solution 1 - Java
This is how I did, it works for me. Thanks!
For Activity :
ActivityCompat.requestPermissions(this, permissionsList, REQUEST_CODE);
For Fragment :
requestPermissions(permissionsList, REQUEST_CODE);
Solution 2 - Java
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();
}
}
}
Solution 3 - Java
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.
Solution 4 - Java
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)
}
}
Solution 5 - Java
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.
Solution 6 - Java
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 {
}
Solution 7 - Java
onRequestPermissionsResult
is invoked in the activity not the fragment. Try overriding onRequestPermissionsResult
in the activity instead.
Solution 8 - Java
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;
}
}
Solution 9 - Java
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
Solution 10 - Java
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();
}
}
}
}
Solution 11 - Java
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
)
}