onRequestPermissionsResult не викликається у фрагменті, якщо визначено як фрагмент, так і активність


167

У мене є фрагмент, в якому я рециркулятор і перегляд даних у цьому recilerview за допомогою адаптера recilerview.

Тепер у мене з’являється кнопка в списку перехідника адаптера, натискаючи на яку мені потрібно перевірити дозвіл READ_EXTERNAL_STORAGE в android на наявність нової моделі дозволів в android.

Я створив нову функцію в фрагменті цього адаптера, щоб перевірити, чи надано дозвіл чи ні, і запитати дозвіл, якщо він ще не наданий.

Я передав MyFragment.this як параметр в адаптері і викликав метод фрагмента при натисканні кнопки в адаптері.

Я використовував наведений нижче код для виклику requestPermission у фрагменті.

if(ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED){
       requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                ConstantVariables.READ_EXTERNAL_STORAGE);
    }

Я змінив onRequestPermissionsResultметод у фрагменті, використовуючи наведений нижче код:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case ConstantVariables.READ_EXTERNAL_STORAGE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, proceed to the normal flow.
                startImageUploading();
            } else {}

Але це не викликається, замість цього методу onRequestPermissionsResult цієї активності викликається.

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

Я не можу видалити метод onRequestPermissionsResult діяльності, але хочу викликати метод onRequestPermissionsResult фрагмента, коли я вимагаю дозволу на фрагмент. Як я можу це зробити? Я щось тут роблю не так, будь ласка, допоможіть мені, якщо хтось тут має ідею.


Відповіді:


372

Відредагована відповідь на більш широкі питання

Я думаю, що ви плутаєте метод для фрагмента та активності. Мав подібний випуск у мого проекту минулого місяця. Перевірте, чи є у вас нарешті наступне:

  1. У AppCompatActivity використовуйте метод ActivityCompat.requestpermissions
  2. У фрагменті підтримки v4 ви повинні використовувати requestpermissions
  3. Ловля - це якщо ви викликаєте у своєму фрагменті AppcompatActivity.requestpermissions, тоді зворотний виклик буде діяти, а не фрагмент
  4. Не забудьте зателефонувати super.onRequestPermissionsResultз активності onRequestPermissionsResult.

Подивіться, чи допомагає це.


9
Просто щоб подвійно перевірити, переконайтеся, що у вашій діяльності встановлено
super.onrequestpermissionresult

27
Додаючи super.onrequestpermissionresultв активі onrequestpermissionresult, викликайте фрагмент onrequestpermissionresult, коли я вимагаю дозволу з використанням requestpermissions. Зараз це добре працює, велике спасибі .. :)
Prithniraj Nicyone

1
Super.onrequestpermissionresult відсутній у зворотному виклику активності, що призвело до того, що мій фрагмент зворотного виклику фрагмента не викликався
sakis kaliakoudas

4
requestPermissions () вимагає рівня API 23. Чи існує інше рішення, сумісне для API 21 рівня?
Адам Гурвіц

2
@ msc87 1. у onRequestPermissionsResult діяльності та фрагменту першим рядком має бути: super.onRequestPermissionsResult (requestCode, permissions, grantResults); 2.в фрагменті, де вам визнано дозвіл, не наданий просто запит на виклик Метод дозволу, такий: requestPermissions (новий String [] {Manifest.permission.CALL_PHONE}, MY_PERMISSIONS_REQUEST_CALL_PHONE);
AREF

122

Я попросив дозвіл на розташування фрагмента і в фрагменті, мені потрібно було це змінити:

            ActivityCompat.requestPermissions(getActivity(), new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQ_CODE);

до цього:

            requestPermissions(new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQ_CODE);

тоді в фрагменті викликали onRequestPermissionsResult.


2
Працює як шарм :)
Антоніо Власіч

1
це не працює з kotlin. Ви можете, будь ласка, допоможіть мені для того ж, тут використовується цей запитДопущення (контекст як активність, дозвілList.toTypedArray (), MY_PERMISSIONS_REQUEST)
Arbaz.in

Дякую :), ти економиш мій час
Axrorxo'ja Yodgorov

19

Це поширена помилка, яку роблять люди при кодуванні зефіру.

Перебуваючи в AppCompatActivity, ви повинні використовувати ActivityCompat.requestPermissions; Коли в android.support.v4.app.Fragment, ви повинні використовувати просто requestPermissions (це метод екземпляра android.support.v4.app.Fragment) Якщо ви викликаєте ActivityCompat.requestPermissions в фрагменті, викликається зворотний виклик onRequestPermissionsResult активність, а не фрагмент.

requestPermissions(permissions, PERMISSIONS_CODE);

Якщо ви викликаєте цей код з фрагмента, у нього є власний метод requestPermissions.

Тож базовим поняттям є: Якщо ви перебуваєте в діяльності, тоді телефонуйте

ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.CAMERA},
                            MY_PERMISSIONS_REQUEST_CAMERA);

а якщо у Фрагменті, просто зателефонуйте

requestPermissions(new String[]{Manifest.permission.CAMERA},
                            MY_PERMISSIONS_REQUEST_CAMERA);

Для довідки я отримав відповідь за цим посиланням https://www.coderzheaven.com/2016/10/12/onrequestpermissionsresult-not-called-on-fragments/


6

Метод requestPermissionsна фрагментах вимагає рівня API 23 або вище.
Якщо ваш додаток націлений на нижчу версію, яку ви можете використовувати

FragmentCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            ConstantVariables.READ_EXTERNAL_STORAGE);

Спочатку потрібно додати залежність support-v13:

implementation "com.android.support:support-v13:$supportLibVersion"

FragmentCompat застаріло з версії 27.1.0
Радж-каннан Іяппан

6

змінити це:

ActivityCompat.requestPermissions(
    activity,
    arrayOf(Manifest.permission.READ_CONTACTS),
    PERMISSIONS_REQUEST_READ_CONTACTS
)

до цього :

requestPermissions(
     arrayOf(Manifest.permission.READ_CONTACTS),
     PERMISSIONS_REQUEST_READ_CONTACTS
)

Нижній призначений для використання у фрагменті (onRequestPermissionsResult викликається у фрагменті), версія ActivityCompat використовується для використання, коли onRequestPermissionsResult розміщений у Діяльності.
Roar Grønmo

1
private void showContacts() {
 if (getActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
         != PackageManager.PERMISSION_GRANTED) {
     requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
             PERMISSIONS_REQUEST_READ_STORAGE);
 } else {
     doShowContacts();
 }
}

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

змінити дозвіл


2
Привіт користувачу2002721; ваш код може бути правильним, але з деяким контекстом він би краще відповів; наприклад, ви можете пояснити, як і чому ця запропонована зміна вирішить проблему запитувача, можливо, включивши посилання на відповідну документацію. Це зробило б їх більш корисними, а також більш корисними для інших читачів сайтів, які шукають рішення подібних проблем.
Вінс Боудрен

Програма може викинути масив поза винятками за межі, якщо ви спробуєте отримати доступ до індексу 0 GranResults, не перевіряючи попередньо довжину. Це сталося з моєю програмою. Я відокремив оператор if для grantResults як внутрішній, якщо оператор, щоб запобігти цьому, і він працює нормально.
Пітер Гриффін

1

Ця прийнята відповідь не працює для мене, тому я знайшов власне рішення, пояснене нижче:

1.Перше я створив метод у фрагменті:

public static void MyOnRequestPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
        if (requestCode == 1 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Log.d(TAG, "Permission: true");
        } else {
            Log.d(TAG, "permission: false");
        }
}

2.І потім зателефонувавши їй до основної діяльності:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(requestCode ==1){
        SignupFragment.MyOnRequestPermissionResult(requestCode, permissions, grantResults);
    }
}

І це працює ...


0

Переконайтеся, що як PERMISSION_REQUEST_CODEу onRequestPermissionsResultвашому , так і всередині нього Fragmentміститься однакове значення.


0

Для tragetSDK 28 спрацює перевірка SDK (> 23) та запит дозволу з фрагмента. Помилка ActivityCompat.requestPermissions (якщо встановити код запиту нижче 65536, з'явиться діалогове вікно дозволу, і якщо користувач дозволить дозвіл, дозволи надаються, але зворотний виклик не відбудеться. Але якщо встановити вище 65536, ActivityCompat.requestPermissions буде я не знаю, що міркувати за цією логікою. Може бути помилка чи навмисна).

Робочий код:

  if (Build.VERSION.SDK_INT >= 23) {
                        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_ACCESS_REQUEST);
                    }

не потрібно робити перевірку версій. у версіях нижче 23 він просто поверне значення "наданий дозвіл". Вибір розробника тут: уникайте блоку "якщо" для простоти або уникайте виклику запиту, коли він не потрібен
Psest328

0

Якщо ви працюєте з Kotlin, вам слід точно вказати, що ви викликаєте метод фрагмента, а не активність

 fragment.requestPermissions(permissions, PERMISSIONS_CODE);

Дозволи на Android M: onRequestPermissionsResult () не викликається

Попросіть дозволів на виконання від v4.Fragment та поверніть виклик, перейдіть до фрагмента?


0

У мене було те саме питання. Ваш фрагмент можна ініціалізувати з макета діяльності. Щось схоже на те:

main_activty.xml

<fragment
    android:id="@+id/fragment"
    android:name="com.exampe.SomeFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Це питання було вирішено для мене, коли я використовував FragmentTransactionзамість цього


0

в API нижче 23 ви можете створити інтерфейс в діяльності, потім реалізувати його в дочірньому фрагменті, і коли ви отримаєте запит на отримання дозволу, результат буде передати його реалізованому інтерфейсу в фрагменті. Це так просто :)


0

ви можете зателефонувати нижче за методом Fragment

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
                doActionBecauseNowYouCanBro();
            } else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
                showWhyRequestPermissionsAndDontBlockUserItsCalledManners();
            }
            return;
    }
    // Other 'case' lines to check for other
    // permissions this app might request.

}

-5

Ця проблема насправді була викликана NestedFragments. В основному більшість фрагментів ми розширюємо HostedFragment, який, у свою чергу, розширює CompatFragment. Наявність цих вкладених фрагментів спричинило проблеми, які врешті-решт були вирішені іншим розробником проекту.

Він робив такі матеріали на низькому рівні, як перемикання бітів, щоб це працювало, тому я не надто впевнений у фактичному остаточному рішенні


3
Замість того , щоб копіювати відповідь, ви могли б просто дати посилання - stackoverflow.com/a/33081173/630833
jayeffkay
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.