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


167

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

Теперь у меня есть кнопка в списке элементов адаптера, щелкнув по которой мне нужно проверить разрешение 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 этого Activity.

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

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


1
Ссылка по ссылке разрешения времени выполнения во фрагменте Это точное решение
Энтони Джексон

Ответы:


373

Отредактированный ответ, чтобы охватить более широкие вопросы

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

  1. В AppCompatActivity используйте метод ActivityCompat.requestpermissions
  2. Во фрагменте поддержки v4 вы должны использовать requestpermissions
  3. Поймайте, если вы вызовете AppcompatActivity.requestpermissions в вашем фрагменте, тогда обратный вызов вступит в действие, а не фрагмент
  4. Обязательно позвоните super.onRequestPermissionsResultс мероприятия onRequestPermissionsResult.

Посмотрите, поможет ли это.


9
Просто дважды проверьте, что у вас есть супер.onrequestpermissionresult, установленный в вашей деятельности
VarunJoshi129

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. во фрагменте, где вы узнаете, что разрешение не предоставлено, просто вызовите метод requestPermission следующим образом: requestPermissions (new 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, можете ли вы помочь мне для того же здесь используется этот requestPermissions (контекст как Activity, licenseList.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
Радж Каннан Iyyappan

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 находится в Activity.
Рев Гронмо

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
Привет user2002721; ваш код может быть верным, но с некоторым контекстом это даст лучший ответ; Например, вы могли бы объяснить, как и почему это предлагаемое изменение решит проблему спрашивающего, возможно, включив ссылку на соответствующую документацию. Это сделало бы его более полезным для них, а также более полезным для других читателей сайта, которые ищут решения для подобных проблем.
Винс Боудрен

Программа может выдать массив за пределами исключения, если вы попытаетесь получить доступ к индексу 0 grantResults, не проверив сначала длину. Это случилось с моей программой. Я отделил оператор if для grantResults как внутренний оператор if, чтобы этого не произошло, и теперь он работает нормально.
Питер Гриффин

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 он просто вернет значение «предоставлено разрешение». Выбор разработчика здесь: для простоты избегайте блока if или избегайте вызова по запросу, когда он не нужен
Psest328

0

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

 fragment.requestPermissions(permissions, PERMISSIONS_CODE);

Разрешения Android M: onRequestPermissionsResult () не вызывается

Запросить время выполнения у v4.Fragment и сделать обратный вызов во 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.