OnRequestPermissionsResult is not called in a dialog fragment

I started working on permission to launch Android M. Here I am faced with the problem that if requestPermissions is called from the Dialog Fragment class, then onRequestPermissionsResult does not receive a call in the same Dialog Fragment class. But if requestPermissions is called from the Activity class or Fragment , then the onRequestPermissionsResult method onRequestPermissionsResult 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 call the requestPermissions method of the Dialog Fragment class. Therefore, I expect to get the result in the same class.

Any help is appreciated. Thanks in advance!




EDIT: Here I am adding more detailed information so that it is more useful to others. I used to use getChildFragmentManager () to show a dialog box.

 ContactPickerDialog dialog = new ContactPickerDialog(); dialog.show(getChildFragmentManager(), "Contact Picker"); 

But As @CommonWare asked me to use activity to show DialogFragment. I made the following changes and it works.

 ContactPickerDialog dialog = new ContactPickerDialog(); dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker"); 
+51
android android-6.0-marshmallow android-fragments android-dialogfragment
Oct. 16 '15 at 11:32
source share
11 answers

There seems to be a bug in Android where nested fragments do not support the onRequestPermissionsResult() . For DialogFragment roundabout way, it seems that the fragment that wants to show the dialog calls the method for hosting activity, and the DialogFragment itself shows the DialogFragment .

+53
Oct. 16 '15 at 12:27
source share

If you are in Fragment from the support library, call requestPermissions() and your onRequestPermissionsResult() fragment will be returned.

If you call ActivityCompat.requestPermissions() , then this is Activity onRequestPermissionsResult() , which will be back.

+103
Nov 16 '15 at 6:41
source share

This issue seems to be fixed in Android Support Library 23.3.0 and higher.

If you use v4 Support Snippets, nested snippets will now receive callbacks to onRequestPermissionsResult ().

Edit: @AndrewS, here is how you can update.

In your build.gradle (app) file, change the following line to use the latest version of the support library 24.0.0, which is the latest version:

 dependencies { compile 'com.android.support:appcompat-v7:24.0.0' } 
+13
Apr 08 '16 at 9:00
source share

EDIT:

I suggest using the new version of Support Library 23.3.0, because the fixed Google issue does not cause onRequestPermissionsResult , but if for some reason you need to use an older version, see the Original answer below.

ORIGINAL RESPONSE:

I use the following workaround (along with the 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); } } 

Using:

 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); } } 
+5
Mar 04 '16 at 10:52
source share

One thing that helped me was this. When you request permission from a nested fragment, use getParent like this

  fragment.getParentFragment().requestPermissions((new String[] {Manifest.permission.READ_CONTACTS}), requestCode); 

and then override the parent fragment onRequestPermissionResult and check the appropriate request code.

I hope he helps you too.

+4
Nov 23 '15 at 16:03
source share

If you have a problem with a nested fragment, you can request permission from the parent fragment

 getParentFragment().requestPermissions(new String[]{permission}, requestCode); 

and then redirect the callback to the child fragment

 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grants) { List<Fragment> fragments = getChildFragmentManager().getFragments(); if (fragments != null) { for (Fragment fragment : fragments) { if (fragment != null) { fragment.onRequestPermissionsResult(requestCode, permissions, grants); } } } } 
+4
Feb 08 '16 at 11:33
source share

I had this problem without nested fragments, where the activity showed a fragment of the dialog, and the result did not work.

Adding super.onRequestPermissionsResult(requestCode, permissions, grantResults);
to activity onRequestPermissionsResult() solved the problem.

+3
Sep 02 '16 at 20:27
source share

I did it like this:

 public class DialogFragmentSMS extends DialogFragment implements View.OnClickListener { public static DialogFragmentSMS frag; private static View view; private static ViewGroup parent; private EditText editTextMensagem; private String celular; private final static int SMS_REQUEST = 20; public DialogFragmentSMS() { } public static DialogFragmentSMS newInstance(String celular) { Bundle args = new Bundle(); args.putString("celular", celular); frag = new DialogFragmentSMS(); frag.setArguments(args); return frag; } @Override public void onCreate(Bundle saveInstaceState) { super.onCreate(saveInstaceState); } @Override public void onClick(View v) { if (!PermissaoUtils.hasPermission(getActivity(), Manifest.permission.SEND_SMS)) { //PermissaoUtils.requestPermissions(getActivity(), new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST); frag.requestPermissions(new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST); }else{ if (validaCampos()) { SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage("0" + celular, null, editTextMensagem.getText().toString(), null, null); Toast.makeText(getActivity(), R.string.sms_enviado, Toast.LENGTH_SHORT).show(); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); frag.dismiss(); } } } 

Permission of my class

 public class PermissaoUtils { public static boolean useRunTimePermissions() { return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1; } public static boolean hasPermission(Activity activity, String permission) { if (useRunTimePermissions()) { return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; } return true; } public static void requestPermissions(Activity activity, String[] permission, int requestCode) { if (useRunTimePermissions()) { activity.requestPermissions(permission, requestCode); } } } 
0
Apr 02 '17 at 7:48 on
source share

If you look at the documentation for the requestPermissions fragment method, you will find that you still need to declare permissions in your manifest:

enter image description here

If this is not the case, then the own onRequestPermissionsResult fragment will not be called.

Instead, the onRequestPermissionsResult action is onRequestPermissionsResult but will not have any effect.

So permission resolution inside the fragment should be done as follows:

1. Declare permission in your manifest

 <uses-permission android:name="android.permission.CAMERA"/> 

Enter this before the application tag.

2. Check the resolution in your fragment

 if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { requestPermissions( arrayOf(Manifest.permission.CAMERA), REQUEST_CODE_CAMERA_PERMISSION) } 

3. Wait for the resolution result in your fragment

 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { when (requestCode) { REQUEST_CODE_CAMERA_PERMISSION -> { val granted = grantResults.isNotEmpty() && permissions.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && !ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[0]) when (granted) { true -> openCamera() else -> proceedWithoutPermission() } } } 

4. Make sure you do not override the onRequestPermissionsResult action

Overriding the onRequestPermissionsResult activity will cause the fragment to not respond.

0
Oct 24 '18 at 19:34
source share

In addition to the final part of the Nino Handler answer and for those who still have problems with this, make sure that if you override onRequestPermissionsResult in the parent activity / fragment of the dialog fragment, you call super.onRequestPermissionsResult.

I redefined the onRequestPermissionsResult in the parent activity of my dialog fragment, but neglected to call the super method. As soon as I changed it to call the super method, it is properly delegated to onRequestPermissionsResult in my dialog fragment.

0
Dec 02 '18 at 11:24
source share

If you call DialogFragment from a fragment, use this:

 YourDialogFragment dialogFragment = YourDialogFragment.newInstance(); dialogFragment.show(getActivity().getFragmentManager(), YourDialogFragment.TAG); dialogFragment.setParentFragment(this); 

Also write in the snippet:

 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { ... } } 

In YourDialogFragment write an additional method for passing the parent fragment:

 public void setParentFragment(Fragment fragment) { this.fragment = fragment; } 

Later in YourDialogFragment, when requesting permission, it is called:

 if (fragment != null) { fragment.requestPermissions(new String[]{permission}, REQUEST_CODE); } 
-one
Feb 13 '18 at 11:57
source share



All Articles