it-swarm.com.ru

onRequestPermissionsResult не вызывается во фрагменте диалога

Я начал работать на Android M разрешение времени выполнения. Здесь я сталкиваюсь с проблемой, что если 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. Так что я ожидаю получить результат в том же классе.

Любая помощь приветствуется. Заранее спасибо!


Правка: Здесь я добавляю больше деталей, чтобы они были более полезны для других . Ранее я использовал getChildFragmentManager (), чтобы показать DialogFragment.

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

Но As @CommonWare попросил меня использовать активность, чтобы показать DialogFragment. Я сделал следующие изменения, и это работает.

ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker");
53
Dhaval Patel

Похоже, что ошибка в Android , где вложенные фрагменты не поддерживают обратный вызов onRequestPermissionsResult(). Для DialogFragment обходной путь, по-видимому, заключается в том, что фрагмент, показывающий, что диалоговое окно вызывает метод в операции хостинга, и действие отображает сам DialogFragment.

54
CommonsWare

Если вы находитесь внутри Fragment из библиотеки поддержки, вызовите requestPermissions() напрямую, и ваш фрагмент будет вызван onRequestPermissionsResult() .

Если вы вызываете ActivityCompat.requestPermissions() , то Activity's onRequestPermissionsResult() будет вызываться обратно.

105
minipif

Эта проблема , кажется, исправлена ​​в Android Support Library 23.3.0 и более поздних версиях.

Если вы используете фрагменты Support v4, вложенные фрагменты теперь будут получать обратные вызовы onRequestPermissionsResult ().

Правка: @AndrewS, вот как вы можете обновить.

В файле build.gradle (app) измените следующую строку, чтобы использовать последнюю версию библиотеки поддержки 24.0.0, которая является самой последней версией:

dependencies {
    compile 'com.Android.support:appcompat-v7:24.0.0'
}
13
Yogesh Umesh Vaity

Правка:

Я предлагаю использовать новую версию библиотеки поддержки 23.3.0, потому что Google исправил проблему, при которой не вызывался onRequestPermissionsResult , но если по каким-то причинам вам нужно использовать более старую версию, то см. Исходный ответ ниже.

ОРИГИНАЛЬНЫЙ ОТВЕТ:

Я использую следующий обходной путь (вместе с 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);
    }
}

Использование:

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
Oleksandr

Если у вас есть проблема с вложенным фрагментом, вы можете запросить разрешение у родительского фрагмента.

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);
            }
        }
    }
}
4
Artem

У меня была эта проблема без вложенных фрагментов, когда действие показывало фрагмент диалога, а результат не передавался. 

Добавление 
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
.__ к действию onRequestPermissionsResult() решил проблему.

4
Eric B.

Одна вещь, которая помогла мне, была это. Когда вы запрашиваете разрешение у вложенного фрагмента, используйте getParent так

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

а затем переопределите родительский фрагмент onRequestPermissionResult и проверьте соответствующий requestCode.

Надеюсь, это поможет вам.

4
udit

Если вы посмотрите документацию метода фрагмента requestPermissions, вы обнаружите, что вам все еще нужно объявить разрешения в вашем манифесте:

 enter image description here

Если это не так, собственный фрагмент onRequestPermissionsResult не будет вызван.

Вместо этого вызывается onRequestPermissionsResult действия, но он не будет иметь никакого эффекта.

Поэтому получение разрешения из фрагмента должно быть сделано следующим образом:

1. Объявите разрешение в вашем манифесте

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

Введите это перед тегом приложения.

2. Проверьте разрешение в вашем фрагменте

if (ActivityCompat.checkSelfPermission(context, permission) 
        != PackageManager.PERMISSION_GRANTED) {

    requestPermissions(
        arrayOf(Manifest.permission.CAMERA), 
        REQUEST_CODE_CAMERA_PERMISSION)
}

3. Дождитесь разрешения разрешения в вашем фрагменте

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. Убедитесь, что вы не переопределяетеonRequestPermissionsResult действия

Переопределение onRequestPermissionsResult действия приведет к тому, что фрагмент не будет реагировать.

1
Nino Handler

Я сделал это так

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);
        }
    }
}
0
Leonardo Inhoqui

В дополнение к конечной части ответа Nino Handler и для всех, у кого все еще есть проблемы с этим, убедитесь, что если вы переопределяете onRequestPermissionsResult в родительском действии/фрагменте вашего фрагмента диалога, вы вызываете super.onRequestPermissionsResult там.

Я переопределял onRequestPermissionsResult в родительской активности моего фрагмента диалога, но не воспользовался для вызова там супер-метода. Как только я изменил его, чтобы вызвать супер метод, он должным образом делегировался в onRequestPermissionsResult в моем фрагменте диалога.

0
D.J.M. Francis