onRequestPermissionsResult не вызывается в фрагменте диалогового окна
я начал работать над разрешением Android M runtime. Здесь я столкнулся с проблемой, что если requestPermissions вызывается из Dialog Fragment класса onRequestPermissionsResult не вызывается в той же Dialog fragment класса. Но если requestPermissions вызывается из Activity класса или Fragment класса onRequestPermissionsResult метод вызывается в том же классе.
вот мой пример кода:
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;
}
}
вот в коде я звоню requestPermissions метод Dialog Fragment класса. Так что я ожидаю получить результат в том же класс.
любая помощь приветствуется. Заранее спасибо!
EDIT:
Здесь я добавляю больше деталей, так что это будет более полезно для других.
Ранее я использовал getChildFragmentManager (), чтобы показать DialogFragment.
ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getChildFragmentManager(), "Contact Picker");
, А Как @CommonWare попросил меня использовать activity, чтобы показать DialogFragment. Я сделал следующие изменения, и это работает.
ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker");
9 ответов:
появляется ошибка в Android, где вложенные фрагменты не поддерживают
onRequestPermissionsResult()обратный. ДляDialogFragment, обходной путь, по-видимому, состоит в том, чтобы фрагмент, желающий показать диалог, вызывал метод на хостинге activity, и activity показывает .
если вы находитесь внутри
Fragmentиз библиотеки поддержки, вызовrequestPermissions()непосредственно, и ваш фрагментonRequestPermissionsResult()будет называться обратной.если вы называете
ActivityCompat.requestPermissions(), потомActivity' sonRequestPermissionsResult()это будет вызвано обратно.
этой вопрос кажется, исправлена в Библиотека Поддержки Android 23.3.0 и выше версий.
Если вы используете фрагменты поддержки v4, вложенные фрагменты теперь будут получение обратных вызовов в onRequestPermissionsResult ().
Edit: @AndrewS, вот как вы можете обновить.
в свою сборку.файл gradle (app), измените следующую строку, чтобы использовать последнюю библиотеку поддержки 24.0.0, которая является последней версия:
dependencies { compile 'com.android.support:appcompat-v7:24.0.0' }
EDIT:
Я предлагаю использовать новую версию библиотеки поддержки 23.3.0, потому что Google Исправлена проблема с не вызывая
onRequestPermissionsResult, но если по каким-то причинам вам нужно использовать более старую версию, то см. ответ origin ниже.ОРИГИНАЛЬНЫЙ ОТВЕТ:
Я использую следующий обходной путь (вместе с easyPermissions библиотека):
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); } }использование:
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); } }
Если у вас есть проблемы с вложенным фрагментом, вы можете запросить разрешение от родительского фрагмента
getParentFragment().requestPermissions(new String[]{permission}, requestCode);и потом вперед, обратного вызова, чтобы ребенок фрагмент
@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); } } } }
одна вещь, которая помогла мне в этом. Когда вы запрашиваете разрешение от вложенного фрагмента, используйте getParent как so
fragment.getParentFragment().requestPermissions((new String[] {Manifest.permission.READ_CONTACTS}), requestCode);а затем переопределите Родительский фрагмент onRequestPermissionResult и проверьте соответствующий код запроса.
надеюсь, что это помогает вам.
у меня была эта проблема без вложенных фрагментов, где активность показывала фрагмент диалога, и результат не передавался.
добавлять
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
к деятельностиonRequestPermissionsResult()решается вопрос.
Я сделал это так
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(); } } }Мой Класс Разрешение
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); } } }
если вы вызываете DialogFragment из фрагмента, используйте это:
YourDialogFragment dialogFragment = YourDialogFragment.newInstance(); dialogFragment.show(getActivity().getFragmentManager(), YourDialogFragment.TAG); dialogFragment.setParentFragment(this);также напишите фрагмент:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { ... } }в YourDialogFragment напишите дополнительный метод для передачи родительского фрагмента:
public void setParentFragment(Fragment fragment) { this.fragment = fragment; }позже в YourDialogFragment при запросе разрешений вызовите:
if (fragment != null) { fragment.requestPermissions(new String[]{permission}, REQUEST_CODE); }
Comments