Дозволи на Android M: Плутаються з використанням функції shouldShowRequestPermissionRationale ()


148

Я переглядав офіційний документ про нову модель дозволів в Android M. Він розповідає про shouldShowRequestPermissionRationale()функцію, яка повертається, trueякщо програма раніше вимагала цього дозволу, а користувач відмовив у запиті. Якщо користувач раніше відхилив запит на дозвіл і обрав опцію Не запитувати знову, цей метод повертається false.

Але як ми можемо розмежовувати наступні два випадки?

Випадок 1 : У додатку немає дозволу, і користувач раніше його не запитував. У такому випадку, mustShowRequestPermissionRationale () поверне помилкове значення, оскільки це перший раз, коли ми запитуємо користувача.

Випадок 2 : Користувач відмовив у дозволі та вибрав "Не запитувати знову", і в цьому випадку повиненShowRequestPermissionRationale () поверне помилкове значення.

Я хотів би надіслати користувача на сторінку налаштувань програми у випадку 2. Як я можу розібратися у цих двох випадках?


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

4
Існує також випадок 3: Користувача запитували і надавали / відмовляли у дозволі, але він використовував налаштування дозволу, щоб повернути назад, щоб "запитувати кожен раз". Тестові шоу shouldShowRequestPermissionRationale()в цьому випадку повертають значення false, що зашкодить будь-якому коду, покладаючись на прапор "я вже запитав"
Логан Пікап

ось приклад google, який показує кращі практики permissionsна Android. github.com/android/permissions-samples
itabdullah

@itabdullah Зразок коду Google є марним, оскільки вони навіть не вважали дуже ймовірним випадком використання "чи користувач в останню чергу відмовив у дозволі". : - / типово
хтось десь

Відповіді:


172

Після попереднього перегляду M 1, якщо діалогове вікно відображається вперше , не встановлено прапорець Ніколи не запитувати знову .

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

Тож логіка повинна бути такою:

  1. Запит дозволу:

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
    } else {
        //Do the stuff that requires permission...
    }
  2. Перевірте, чи в дозволі було відмовлено чи надано в onRequestPermissionsResult.

    Якщо дозвіл раніше було відмовлено, цього разу у діалоговому вікні дозволу з’явиться прапорець Ніколи не запитувати знову .

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

    if (grantResults.length > 0){
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //Do the stuff that requires permission...
        }else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                //Show permission explanation dialog...
            }else{
                //Never ask again selected, or device policy prohibits the app from having that permission.
                //So, disable that feature, or fall back to another situation...
            }
        }
    }

Отже, вам не доведеться відслідковувати, чи користувач перевірив ніколи не запитувати більше чи ні.


49
Одним із пунктів уточнення, ifShowRequestPermissionRationale () також поверне помилкове значення, якщо користувача ніколи не запитували про дозвіл (тобто при першому запуску програми). Ви б не стикалися з цим випадком, якщо дотримуєтесь логіки наведеного прикладу. Але формулювання до 2 років трохи не вводить в оману.
Бен

15
Я не впевнений, це здається недоліком. Як ми повинні знати, якщо користувач вперше запитує? Я повинен відстежувати, чи запитували користувача, і якщо він це зробив, я повинен змінити логіку. Це не має для мене сенсу.
Даніель Ф

4
Я думаю, що варто відзначити, що там, де ви переходите contextв ActivityCompat.shouldShowRequestPermissionRationale(...)параметр, насправді є тип Activity. Може не впливати на вас усіх, але в моєму випадку це все одно.
aProperFox

7
Ця логіка андроїда настільки проклята дурна! Він змушує мене викликати shouldзворотний виклик і зберігати його протицільове значення в NVM, просто щоб дізнатися, чи потрібно мені знову запросити запит наступного разу, коли програма відкриється! ... вау (facepalm) ... чи було занадто важко зробити лише один дзвінок, повертаючи перелік статусу ??
Shockwaver

2
Я думаю, що це велика невдача від Google. В офіційній документації зазначено, що слід зателефонувати до перевірки дозволів (див. Developer.android.com/training/permissions/requesting#explain ), але всі відповіді в StackOverflow називають його в onRequestPermissionResult (), щоб розрізнити користувач натиснув "Ніколи більше не запитувати" чи ні.
Мілош Черніловський

22

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

public class PermissionUtil {
    /*
    * Check if version is marshmallow and above.
    * Used in deciding to ask runtime permission
    * */
    public static boolean shouldAskPermission() {
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
    }
private static boolean shouldAskPermission(Context context, String permission){
        if (shouldAskPermission()) {
            int permissionResult = ActivityCompat.checkSelfPermission(context, permission);
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true;
            }
        }
        return false;
    }
public static void checkPermission(Context context, String permission, PermissionAskListener listener){
/*
        * If permission is not granted
        * */
        if (shouldAskPermission(context, permission)){
/*
            * If permission denied previously
            * */
            if (((Activity) context).shouldShowRequestPermissionRationale(permission)) {
                listener.onPermissionPreviouslyDenied();
            } else {
                /*
                * Permission denied or first time requested
                * */
if (PreferencesUtil.isFirstTimeAskingPermission(context, permission)) {
                    PreferencesUtil.firstTimeAskingPermission(context, permission, false);
                    listener.onPermissionAsk();
                } else {
                    /*
                    * Handle the feature without permission or ask user to manually allow permission
                    * */
                    listener.onPermissionDisabled();
                }
            }
        } else {
            listener.onPermissionGranted();
        }
    }
/*
    * Callback on various cases on checking permission
    *
    * 1.  Below M, runtime permission not needed. In that case onPermissionGranted() would be called.
    *     If permission is already granted, onPermissionGranted() would be called.
    *
    * 2.  Above M, if the permission is being asked first time onPermissionAsk() would be called.
    *
    * 3.  Above M, if the permission is previously asked but not granted, onPermissionPreviouslyDenied()
    *     would be called.
    *
    * 4.  Above M, if the permission is disabled by device policy or the user checked "Never ask again"
    *     check box on previous request permission, onPermissionDisabled() would be called.
    * */
    public interface PermissionAskListener {
/*
        * Callback to ask permission
        * */
        void onPermissionAsk();
/*
        * Callback on permission denied
        * */
        void onPermissionPreviouslyDenied();
/*
        * Callback on permission "Never show again" checked and denied
        * */
        void onPermissionDisabled();
/*
        * Callback on permission granted
        * */
        void onPermissionGranted();
    }
}

А методи PreferenceUtil такі.

public static void firstTimeAskingPermission(Context context, String permission, boolean isFirstTime){
SharedPreferences sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE;
 sharedPreference.edit().putBoolean(permission, isFirstTime).apply();
 }
public static boolean isFirstTimeAskingPermission(Context context, String permission){
return context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE).getBoolean(permission, true);
}

Тепер все, що вам потрібно, це використовувати метод checkPermission з належними аргументами.

Ось приклад,

PermissionUtil.checkPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    new PermissionUtil.PermissionAskListener() {
                        @Override
                        public void onPermissionAsk() {
                            ActivityCompat.requestPermissions(
                                    thisActivity,
              new String[]{Manifest.permission.READ_CONTACTS},
                            REQUEST_EXTERNAL_STORAGE
                            );
                        }
@Override
                        public void onPermissionPreviouslyDenied() {
                       //show a dialog explaining permission and then request permission
                        }
@Override
                        public void onPermissionDisabled() {
Toast.makeText(context, "Permission Disabled.", Toast.LENGTH_SHORT).show();
                        }
@Override
                        public void onPermissionGranted() {
                            readContacts();
                        }
                    });

Випадок 1: У додатку немає дозволу, і користувач раніше його не запитував. У такому випадку, mustShowRequestPermissionRationale () поверне помилкове значення, оскільки це перший раз, коли ми запитуємо користувача.

Випадок 2: Користувач відмовив у дозволі та вибрав "Не запитувати знову", і в цьому випадку повиненShowRequestPermissionRationale () поверне помилкове значення.

Я хотів би надіслати користувача на сторінку налаштувань програми у випадку 2. Як я можу розібратися у цих двох випадках?

Ви отримаєте зворотний виклик у OnPermissionAsk для випадку 1 та onPermissionDisabled для випадку 2.

Щасливе кодування :)


Відмінне пояснення брате. Дотримуйтесь точно такої самої процедури. :)
Суміт Джа

Що я повинен заповнити для цієїАктивності? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Мардімар

@Mardymar thisActivity- це не що інше, як YourActivity.this.
мутурай

1
як обробити кілька дозволів і як інтегрувати цей код всередині фрагмента.
Таймур

Що contextти використовуєш? shouldShowRequestPermissionRationale(permission)не існує в Росії android.content.Context. це в ActivityCompat
Хілікус

8

ОНОВЛЕННЯ

Я вважаю , що Канкуні в відповідь нижче є правильним , які повинні бути дотримані. Єдиний спосіб точно знати - це перевірити це в зворотному звороті виклику onRequestPermissionResult, використовуючи shouldShowPermissionRationale.

==

Моя оригінальна відповідь:

Єдиний спосіб, який я знайшов - це самостійно відстежувати, чи це вперше чи ні (наприклад, використання спільних уподобань). Якщо це не перший раз, тоді використовуйте shouldShowRequestPermissionRationale()для розмежування.

Також дивіться: Android M - перевірити дозвіл на виконання - як визначити, чи користувач поставив прапорець "Ніколи більше не запитувати"?


1
Так, навіть я згоден, що метод CanC - це той, якого слід дотримуватися. Я відзначу це як прийняту відповідь.
akshayt23

6

Наскільки я це розумію, shouldShowRequestPermissionRationale () запускає кілька випадків використання під кришкою та повідомляє програму, чи потрібно показувати пояснення щодо запитуваних дозволів чи ні.

Ідея, що стоїть за дозволами на виконання часу, полягає в тому, що більшу частину часу користувач скаже «Так» на запит дозволу. Таким чином користувачеві доведеться робити лише один клік. Звичайно, запит слід використовувати у правильному контексті, тобто запитуючи дозвіл на камеру, коли натискається кнопка "Камера".

Якщо користувач відмовляє у запиті, але через деякий час з’являється і знову натискає кнопку «Камера», у випадку повернення trueShowRequestPermissionRationale () повернеться правдою, тому додаток може показати змістовне пояснення, чому запит на отримання дозволу та чому програма не буде правильно працювати без цього. Зазвичай у цьому діалоговому вікні ви показуєте кнопку, щоб знову відхилити / прийняти рішення пізніше, і кнопку для надання дозволів. Кнопка дозволів на отримання дозволу у діалоговому вікні обґрунтування повинна запустити запит на дозвіл знову. Цього разу користувач також матиме прапорець "Ніколи більше не показувати". Якщо він вирішить вибрати його та відмовити у дозволі ще раз, він повідомить систему Android про те, що користувач та додаток не на одній сторінці. Ця дія матиме два наслідки - якщоShowRequestPermissionRationale () завжди повертатиметься помилково,

Але є й інший можливий сценарій, коли можна використати onRequestPermissionsResult. Наприклад, деякі пристрої можуть мати політику щодо пристрою, яка вимикає камеру (працює для CIA, DARPA тощо). На цих пристроях onRequestPermissionsResult завжди поверне помилковий, а метод requestPermissions () буде мовчазно відхиляти запит.

Ось що я зібрав, слухаючи подкаст з Беном Поєшем - менеджером продуктів в рамках Android.
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html


6

Просто опублікуйте інший варіант, якщо хтось може відчувати себе таким. Ви можете використовувати EasyPermissions, які надав сам Google, щоб, як було сказано, "Спростити системні дозволи Android M".

Тоді вам не доведеться звертатися shouldShowRequestPermissionRationaleбезпосередньо.


чому я не бачив цього проекту доречно :)
Влад

Проблема з EasyPermissions залишається майже однаковою. Просити permissionPermanentlyDeniedвнутрішньо просто дзвонити shouldShowPermissionsRationaleта повертатися trueу випадку, коли користувачеві ніколи не було запропоновано надавати дозволи.
hgoebl

4

Якщо когось цікавить рішення Котліна, я відремонтував @muthuraj відповідь бути в Котліні. Також трохи модернізували його, щоб мати блок завершення замість слухачів.

PermissionUtil

object PermissionUtil {
    private val PREFS_FILE_NAME = "preference"

    fun firstTimeAskingPermission(context: Context, permission: String, isFirstTime: Boolean) {
        val sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE)
        sharedPreference.preferences.edit().putBoolean(permission,
                isFirstTime).apply()
    }

    fun isFirstTimeAskingPermission(context: Context, permission: String): Boolean {
        val sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE)
        return sharedPreference.preferences.getBoolean(permission,
                true)
    }
}

PermissionHandler

enum class CheckPermissionResult {
    PermissionAsk,
    PermissionPreviouslyDenied,
    PermissionDisabled,
    PermissionGranted
}

typealias PermissionCheckCompletion = (CheckPermissionResult) -> Unit


object PermissionHandler {

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        return ContextCompat.checkSelfPermission(context,
                permission) != PackageManager.PERMISSION_GRANTED
    }

    fun checkPermission(context: Context, permission: String, completion: PermissionCheckCompletion) {
        // If permission is not granted
        if (shouldAskPermission(context, permission)) {
            //If permission denied previously
            if ((context as Activity).shouldShowRequestPermissionRationale(permission)) {
                completion(CheckPermissionResult.PermissionPreviouslyDenied)
            } else {
                // Permission denied or first time requested
                if (PermissionUtil.isFirstTimeAskingPermission(context,
                                permission)) {
                    PermissionUtil.firstTimeAskingPermission(context,
                            permission,
                            false)
                    completion(CheckPermissionResult.PermissionAsk)
                } else {
                    // Handle the feature without permission or ask user to manually allow permission
                    completion(CheckPermissionResult.PermissionDisabled)
                }
            }
        } else {
            completion(CheckPermissionResult.PermissionGranted)
        }
    }
}

Впровадження

PermissionHandler.checkPermission(activity,
                    Manifest.permission.CAMERA) { result ->
                when (result) {
                    CheckPermissionResult.PermissionGranted -> {
                        // openCamera()
                    }
                    CheckPermissionResult.PermissionDisabled -> {
                        // displayAlert(noPermissionAlert)
                    }
                    CheckPermissionResult.PermissionAsk -> {
                        // requestCameraPermissions()
                    }
                    CheckPermissionResult.PermissionPreviouslyDenied -> {
                        // displayAlert(permissionRequestAlert)
                    }
                }
            }

3

Перевірте цю реалізацію. працює досить добре для мене. в основному ви перевіряєте дозволи в методі checkPermissions (), передаючи список дозволів. Ви перевіряєте результат запиту на дозвіл на onRequestPermissionsResult (). Реалізація дозволяє вирішувати обидва випадки, коли користувач вибирає "ніколи не запитувати знову" чи ні. У цій реалізації, у разі вибору "ніколи не запитувати знову", у діалоговому вікні є можливість перейти до дії "Налаштування додатків".

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

/**
     * responsible for checking if permissions are granted. In case permissions are not granted, the user will be requested and the method returns false. In case we have all permissions, the method return true.
     * The response of the request for the permissions is going to be handled in the onRequestPermissionsResult() method
     * @param permissions list of permissions to be checked if are granted onRequestPermissionsResult().
     * @param requestCode request code to identify this request in
     * @return true case we already have all permissions. false in case we had to prompt the user for it.
     */
    private boolean checkPermissions(List<String> permissions, int requestCode) {
        List<String> permissionsNotGranted = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(getActivity(), permission) != PackageManager.PERMISSION_GRANTED)
                permissionsNotGranted.add(permission);
        }

        //If there is any permission we don't have (it's going to be in permissionsNotGranted List) , we need to request.
        if (!permissionsNotGranted.isEmpty()) {
            requestPermissions(permissionsNotGranted.toArray(new String[permissionsNotGranted.size()]), requestCode);
            return false;
        }
        return true;
    }

    /**
     * called after permissions are requested to the user. This is called always, either
     * has granted or not the permissions.
     * @param requestCode  int code used to identify the request made. Was passed as parameter in the
     *                     requestPermissions() call.
     * @param permissions  Array containing the permissions asked to the user.
     * @param grantResults Array containing the results of the permissions requested to the user.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case YOUR_REQUEST_CODE: {
                boolean anyPermissionDenied = false;
                boolean neverAskAgainSelected = false;
                // Check if any permission asked has been denied
                for (int i = 0; i < grantResults.length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        anyPermissionDenied = true;
                        //check if user select "never ask again" when denying any permission
                        if (!shouldShowRequestPermissionRationale(permissions[i])) {
                            neverAskAgainSelected = true;
                        }
                    }
                }
                if (!anyPermissionDenied) {
                    // All Permissions asked were granted! Yey!
                    // DO YOUR STUFF
                } else {
                    // the user has just denied one or all of the permissions
                    // use this message to explain why he needs to grant these permissions in order to proceed
                    String message = "";
                    DialogInterface.OnClickListener listener = null;
                    if (neverAskAgainSelected) {
                        //This message is displayed after the user has checked never ask again checkbox.
                        message = getString(R.string.permission_denied_never_ask_again_dialog_message);
                        listener = new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //this will be executed if User clicks OK button. This is gonna take the user to the App Settings
                                startAppSettingsConfigActivity();
                            }
                        };
                    } else {
                        //This message is displayed while the user hasn't checked never ask again checkbox.
                        message = getString(R.string.permission_denied_dialog_message);
                    }
                    new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
                            .setMessage(message)
                            .setPositiveButton(getString(R.string.label_Ok), listener)
                            .setNegativeButton(getString(R.string.label_cancel), null)
                            .create()
                            .show();
                }
            }
            break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

    /**
     * start the App Settings Activity so that the user can change
     * settings related to the application such as permissions.
     */
    private void startAppSettingsConfigActivity() {
        final Intent i = new Intent();
        i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        i.addCategory(Intent.CATEGORY_DEFAULT);
        i.setData(Uri.parse("package:" + getActivity().getPackageName()));
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        getActivity().startActivity(i);
    }

2

Може бути корисним для когось: -

Я помітив, що якщо ми перевіримо прапор mustShowRequestPermissionRationale () у методі зворотного виклику onRequestPermissionsResult (), він показує лише два стани.

Стан 1: Повернення істини: - Кожен раз, коли користувач натискає дозволу заборонити (включаючи перший раз).

Стан 2: Повертає помилку: - якщо користувач вибирає "ніколи більше не запитує".

Посилання для детального робочого прикладу .


6
він повертає помилкове в перший раз. неправда
JoM

Так, це те, що я згадував, якщо ви перевіряєте прапор у методі зворотного виклику onRequestPermissionsResult (), він матиме лише два стани, зокрема в цьому зворотному дзвінку.
Нік

2
На жаль, mustShowRequestPermissionRationale завжди повертає помилку - незалежно від того, чи користувач коли-небудь відмовляв у дозволі чи ні.
ІгорГанапольський

1

Ми можемо це зробити таким чином?

@Retention(RetentionPolicy.SOURCE)
@IntDef({GRANTED, DENIED, NEVER})
public @interface PermissionStatus {
}

public static final int GRANTED = 0;
public static final int DENIED = 1;
public static final int NEVER = 2;

@PermissionStatus
public static int getPermissionStatus(Activity activity, String permission) {
    if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
        return DENIED;
    } else {
        if (ActivityCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED) {
            return GRANTED;
        } else {
            return NEVER;
        }
    }
}

На жаль, цей код не розрізняє ситуацію, коли дозвіл ніколи раніше не просили і де перевірено "ніколи більше не вимагати".
Бен-

вам слід використовувати комбінацію цього + класу помічників дозволів, щоб перевірити, чи надано дозвіл чи ні.
д-р aNdRO

0

shouldShowRequestPermissionRationale для СПЕЦІАЛЬНОГО дозволу завжди повертайте ПРАВИЛЬНО ТОЛЬКО після того, як користувач відмовив це без прапорця

Нас цікавить значення FALSE

Отже, 3 випадки втрачені з помилковим значенням:

1. раніше не було такої дії, і тепер користувач вирішує погодитись або відмовити.

Просто визначте вподобання, ASKED_PERMISSION_*яке зараз не існує, і було б істинним в onRequestPermissionsResultйого запуску, у будь-якому випадку погодитись або заперечити

Тож як цей параметр не існує, немає підстав для перевіркиshouldShowRequestPermissionRationale

2. користувач натиснув згоду.

Просто робіть:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

Що поверне правду, і немає підстав для перевіркиshouldShowRequestPermissionRationale

3. Користувач натиснув заперечення за допомогою прапорець (другий або більше запитаних разів)

Це ЧАС для роботи з shouldShowRequestPermissionRationaleякої буде повертати FALSE

(налаштування існує, і ми не маємо дозволу)


0

Цей код просить користувача запитувати дозвіл під час виконання, якщо користувач дозволяє, він виконує метод результатів, якщо користувач заперечує, він запитує знову з описом з користувачем deny (він запитує знову з інструкціями), але якщо користувач вибере ніколи не запитувати більше. він обробляє більше ніколи не запитувати, відобразити параметр відкритих налаштувань з інструкціями.

public String storagePermissions = Manifest.permission.READ_EXTERNAL_STORAGE;   
private static final int REQUEST_ACCESS =101;  

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      if(checkSelfPermission(storagePermissions)== PackageManager.PERMISSION_GRANTED){
          result();    // result  is your block of code 
      }else {
          requestPermissions(new String[]{storagePermissions},REQUEST_ACCESS);
      }

    }
    else{
        result();    //so if user is lower than api verison M, no permission is requested
    } 

}

 private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setTitle("Hi User..")
            .setPositiveButton("Ok", okListener)
            .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {        //idea calling showMessage funtion again
                    Snackbar mySnackbar = Snackbar.make( findViewById(R.id.coordinatorlayout),"You Press Cancel.. ", Snackbar.LENGTH_INDEFINITE);
                    mySnackbar.setAction("Exit", new cancelButton());
                    mySnackbar.show();

                }
            })
            .create()
            .show();
}


private void result(){
          //your code
}

    @RequiresApi(api = Build.VERSION_CODES.M)
public class NeverAskAgain implements View.OnClickListener{
    @Override
    public void onClick(View view)
    {
        goToSettings();
    }
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void goToSettings() {
    Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
    finish();
    myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
    myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivityForResult(myAppSettings, REQUEST_APP_SETTINGS);
}
public class cancelButton implements View.OnClickListener{
    @Override
    public void onClick(View view){
        Toast.makeText(MainActivity.this,"To use this app , you must grant storage permission",Toast.LENGTH_SHORT);
        finish();
    }
    }


 @Override
@RequiresApi(api = Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode,permissions,grantResults);

    switch(requestCode) {
        case REQUEST_ACCESS:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission is granted
                    result();
                    break;
                }
                else if (!shouldShowRequestPermissionRationale(permissions[0])){
                    showMessageOKCancel("You choose Never Ask Again,option",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Snackbar mySnackbar = Snackbar.make(findViewById(R.id.coordinatorlayout), "Permission=>Storage=>On", Snackbar.LENGTH_INDEFINITE);
                        mySnackbar.setAction("Settings", new NeverAskAgain());
                        mySnackbar.show();
                    }
                     });
                    break;
                }
                else {
                    showMessageOKCancel("You Denid permission Request..",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(new String[]{storagePermissions}, REQUEST_ACCESS);
                        }
                    });
                    break;
                }
        }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.