onRequestPermissionsResult not being called in dialog fragment
Solution 1
There appears to be a bug in Android, where nested fragments do not support the onRequestPermissionsResult()
callback. For a DialogFragment
, a workaround appears to be to have the fragment wanting to show the dialog call a method on the hosting activity, and the activity shows the DialogFragment
itself.
Solution 2
If you're inside a Fragment
from support library, call requestPermissions()
directly, and your Fragment's onRequestPermissionsResult()
will be called back.
If you call ActivityCompat.requestPermissions()
, then it's the Activity
's onRequestPermissionsResult()
that will be called back.
Solution 3
This issue seems to be fixed in Android Support Library 23.3.0 and above versions.
If you’re using Support v4 Fragments, nested fragments will now receive callbacks to onRequestPermissionsResult().
Edit: @AndrewS, here's how you can update.
In your build.gradle(app) file, change the following line to use the latest support library 24.0.0 which is the latest version:
dependencies {
compile 'com.android.support:appcompat-v7:24.0.0'
}
Solution 4
EDIT:
I suggest to use a new version of Support Library 23.3.0, because Google fixed issue with not calling onRequestPermissionsResult
, but if for some reasons you need to use an older version, then see origin answer below.
ORIGINAL ANSWER:
I am using next workaround (together with easyPermissions library):
BaseFragment:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
/** child v4.fragments aren't receiving this due to bug. So forward to child fragments manually
* https://code.google.com/p/android/issues/detail?id=189121
*/
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
// it is possible that fragment might be null in FragmentManager
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
}
BaseActivity:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Fragment fragment = getSupportFragmentManager().findFragmentById(getFragmentContainer())
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
}
}
Usage:
public class SomeFragment extends BaseFragment implements EasyPermissions.PermissionCallbacks {
private static final int PICK_CONTACT = 1;
private static final int READ_CONTACTS_PERM = 2;
// some code
@AfterPermissionGranted(READ_CONTACTS_PERM)
private void pickContactWithPermissionsCheck() {
if (EasyPermissions.hasPermissions(getContext(), Manifest.permission.READ_CONTACTS)) {
// Have permission
pickContactForResult();
} else {
// Request one permission
EasyPermissions.requestPermissions(this, getString(R.string.read_contacts_permission_explanation),
READ_CONTACTS_PERM, Manifest.permission.READ_CONTACTS);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// FIXME problem with incorrect requestCode coming to callback for Nested fragments
// More information here - https://code.google.com/p/android/issues/detail?id=189121
if (isVisible() && Arrays.asList(permissions).contains(Manifest.permission.READ_CONTACTS)) {
requestCode = READ_CONTACTS_PERM;
}
// EasyPermissions handles the request result.
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
}
Solution 5
I had this problem without nested fragments, where the activity was showing the dialog fragment and the result was not getting passed.
Adding
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
to the Activity's onRequestPermissionsResult()
solved the issue.
![Dhaval Patel](https://i.stack.imgur.com/Lzcgg.png?s=256&g=1)
Dhaval Patel
Electronics Engineer that attempts to learn how to code. #SOreadytohelp
Updated on July 08, 2022Comments
-
Dhaval Patel almost 2 years
I have started to work on Android M runtime permission. Here I am facing the issue that if
requestPermissions
is called fromDialog Fragment
class thenonRequestPermissionsResult
not getting called in the sameDialog fragment
class. But ifrequestPermissions
is called fromActivity
class orFragment
class thenonRequestPermissionsResult
method get called in the same class.Here is my sample code:
public class ContactPickerDialog extends DialogFragment { private static final int READ_CONTACTS_REQUEST_CODE = 12; private Context mContext; private void loadContact() { if(hasPermission(mContext, Manifest.permission.READ_CONTACTS)){ new ContactSyncTask().execute(); } else { this.requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { Logger.d("TAG", "dialog onRequestPermissionsResult"); switch (requestCode) { case READ_CONTACTS_REQUEST_CODE: // Check Permissions Granted or not if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { new ContactSyncTask().execute(); } else { // Permission Denied Toast.makeText(getActivity(), "Read contact permission is denied", Toast.LENGTH_SHORT).show(); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private static boolean hasPermission(Context context, String permission){ return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; } }
Here in the code I am calling
requestPermissions
method ofDialog Fragment
class. So I am expecting to get result in same class.Any help is appreciated. Thanks in advance!
EDIT: Here I am adding more detail, so that it will be more helpful to others. Previously I have used getChildFragmentManager() to show the DialogFragment.
ContactPickerDialog dialog = new ContactPickerDialog(); dialog.show(getChildFragmentManager(), "Contact Picker");
But As @CommonWare asked me to use activity to show the DialogFragment. I have made following changes and it works.
ContactPickerDialog dialog = new ContactPickerDialog(); dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker");