Izin Android M: Bingung tentang penggunaan fungsi shouldShowRequestPermissionRationale ()


148

Saya telah membahas dokumen resmi tentang model Izin baru di Android M. Ini berbicara tentang shouldShowRequestPermissionRationale()fungsi yang kembali truejika aplikasi telah meminta izin ini sebelumnya dan pengguna menolak permintaan tersebut. Jika pengguna menolak permintaan izin di masa lalu dan memilih opsi Jangan tanya lagi, metode ini kembali false.

Tetapi bagaimana kita bisa membedakan antara dua kasus berikut?

Kasus 1 : Aplikasi ini tidak memiliki izin dan pengguna belum pernah meminta izin sebelumnya. Dalam hal ini, shouldShowRequestPermissionRationale () akan mengembalikan false karena ini adalah pertama kalinya kami bertanya kepada pengguna.

Kasus 2 : Pengguna telah menolak izin dan memilih "Jangan tanya lagi", dalam hal ini juga seharusnyaShowRequestPermissionRationale () akan mengembalikan false.

Saya ingin mengirim pengguna ke halaman pengaturan App dalam Kasus 2. Bagaimana cara membedakan dua kasus ini?


1
Jawaban yang diterima bagus. Sama seperti alternatif, Anda juga bisa menggunakan pref bersama untuk mengetahui apakah aplikasi tersebut telah meminta izin sebelumnya. Hanya melempar itu ke sana kalau-kalau itu lebih berlaku untuk situasi orang lain.
Rockin4Life33

4
Ada juga case 3: Pengguna telah diminta dan diberikan / ditolak izin, tetapi telah menggunakan pengaturan izin untuk kembali ke "tanya setiap waktu". Pengujian menunjukkan shouldShowRequestPermissionRationale()pengembalian salah dalam kasus ini, yang akan melukai kode yang mengandalkan bendera "pernah saya tanyakan sebelumnya".
Logan Pickup

di sini adalah contoh google yang menunjukkan praktik terbaik di permissionsAndroid. github.com/android/permissions-samples
itabdullah

@itabdullah Google contoh kode tidak berguna karena mereka bahkan tidak mempertimbangkan penggunaan yang sangat mungkin dari "apakah pengguna perma-menolak izin terakhir kali". : - / khas
Seseorang Di Suatu Tempat

Jawaban:


172

Setelah M Pratinjau 1, jika dialog ditampilkan untuk pertama kalinya , tidak ada kotak centang Jangan pernah tanya lagi .

Jika pengguna menolak permintaan izin, akan ada kotak centang Jangan tanya lagi di dialog izin saat izin kedua kali diminta.

Jadi logikanya harus seperti ini:

  1. Minta izin:

    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. Periksa apakah izin ditolak atau diberikan pada onRequestPermissionsResult.

    Jika izin ditolak sebelumnya, kali ini akan ada kotak centang Jangan tanya lagi di dialog izin.

    Panggil shouldShowRequestPermissionRationaleuntuk melihat apakah pengguna memeriksa Jangan pernah bertanya lagi . shouldShowRequestPermissionRationalemetode mengembalikan false hanya jika pengguna memilih Never ask again atau kebijakan perangkat melarang aplikasi memiliki izin itu:

    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...
            }
        }
    }

Jadi, Anda tidak perlu melacak jika pengguna memeriksa Jangan pernah bertanya lagi atau tidak.


49
Satu poin klarifikasi, shouldShowRequestPermissionRationale () juga akan mengembalikan false jika pengguna belum pernah diminta meminta izin (yaitu saat pertama kali aplikasi dijalankan). Anda tidak akan mengalami kasus itu jika Anda mengikuti logika dari contoh yang diberikan. Namun kata-katanya, di bawah 2 sedikit menyesatkan.
Ben

15
Saya tidak yakin, ini sepertinya cacat. Bagaimana kita bisa tahu jika ini adalah pertama kalinya pengguna ditanyai? Saya harus melacak jika pengguna ditanya, dan jika dia melakukannya, maka saya harus membalikkan logikanya. Tidak masuk akal bagi saya.
Daniel F

4
Saya pikir itu perlu dicatat bahwa di mana Anda lewat contextdi ActivityCompat.shouldShowRequestPermissionRationale(...)parameter sebenarnya tipe Activity. Mungkin tidak mempengaruhi Anda semua tetapi dalam kasus saya itu mempengaruhi Anda.
aProperFox

7
Logika android ini sangat bodoh! Memaksa saya untuk memanggil shouldcallback DAN menyimpan nilai counter-nya di NVM hanya untuk mengetahui apakah saya perlu meminta permintaan lagi saat aplikasi dibuka! ... wow (facepalm) ... apakah terlalu sulit untuk membuat hanya satu panggilan mengembalikan status enumerasi ??
Shockwaver

2
Saya pikir ini adalah kegagalan besar oleh Google. Dokumentasi resmi menyatakan bahwa shouldShowRequestPermissionRationale () harus dipanggil sebelum memeriksa izin (lihat developer.android.com/training/permissions/requesting#explain ), tetapi semua jawaban di StackOverflow menyebutnya di onRequestPermissionResult () untuk membedakan apakah pengguna mengklik "Never ask again" atau tidak.
Miloš Černilovský

22

Saya memiliki masalah yang sama dan saya mengatasinya. Untuk membuat hidup lebih sederhana, saya menulis kelas util untuk menangani izin runtime.

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();
    }
}

Dan metode PreferenceUtil adalah sebagai berikut.

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

Sekarang, yang Anda butuhkan hanyalah menggunakan metode checkPermission dengan argumen yang tepat.

Berikut ini sebuah contoh,

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();
                        }
                    });

Kasus 1: Aplikasi ini tidak memiliki izin dan pengguna belum pernah meminta izin sebelumnya. Dalam hal ini, shouldShowRequestPermissionRationale () akan mengembalikan false karena ini adalah pertama kalinya kami bertanya kepada pengguna.

Kasus 2: Pengguna telah menolak izin dan memilih "Jangan tanya lagi", dalam hal ini juga seharusnyaShowRequestPermissionRationale () akan mengembalikan false.

Saya ingin mengirim pengguna ke halaman pengaturan App dalam Kasus 2. Bagaimana cara membedakan dua kasus ini?

Anda akan mendapatkan panggilan balik pada onPermissionAsk untuk kasus 1, dan onPermissionDisabled untuk case 2.

Selamat coding :)


Penjelasan yang bagus sekali. Ikuti prosedur yang sama persis dengan Anda. :)
Sumit Jha

Apa yang harus saya isi untuk Aktivitas ini? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Mardymar

@Mardymar thisActivitytidak lain adalah YourActivity.this.
muthuraj

1
bagaimana menangani beberapa izin dan bagaimana mengintegrasikan kode ini di dalam fragmen.
Taimur

Apa contextyang kamu gunakan? shouldShowRequestPermissionRationale(permission)tidak ada di android.content.Context. itu ada di ActivityCompat
Hilikus

9

MEMPERBARUI

Saya percaya bahwa jawaban CanC bawah ini adalah yang benar yang harus diikuti. Satu-satunya cara untuk mengetahui dengan pasti adalah memverifikasi ini di callback onRequestPermissionResult menggunakan shouldShowPermissionRationale.

==

Jawaban asli saya:

Satu-satunya cara yang saya temukan adalah melacak sendiri apakah ini pertama kali atau tidak (misalnya menggunakan preferensi bersama). Jika ini bukan pertama kalinya, gunakanshouldShowRequestPermissionRationale() untuk membedakan.

Lihat juga: Android M - periksa izin runtime - cara menentukan apakah pengguna menandai "Never ask again"?


1
Ya bahkan saya setuju bahwa metode CanC adalah metode yang harus diikuti. Saya akan menandainya sebagai jawaban yang diterima.
akshayt23

6

Cara saya memahaminya, shouldShowRequestPermissionRationale () menjalankan sejumlah kasus penggunaan di bawah tenda, dan memberi tahu aplikasi apakah akan menampilkan penjelasan tentang izin yang diminta atau tidak.

Gagasan di balik izin Run Time adalah bahwa sebagian besar waktu, pengguna akan mengatakan Ya untuk permintaan izin. Dengan begitu pengguna harus melakukan hanya satu klik. Tentu saja permintaan harus digunakan dalam konteks yang benar - yaitu meminta izin Kamera ketika tombol "Kamera" ditekan.

Jika pengguna menolak permintaan, tetapi setelah beberapa waktu muncul dan menekan tombol "Kamera" lagi, seharusnyaShowRequestPermissionRationale () akan kembali benar, sehingga aplikasi dapat menunjukkan beberapa penjelasan yang bermakna mengapa izin diminta, dan mengapa aplikasi tidak akan bekerja dengan baik tanpa itu. Biasanya Anda akan menunjukkan di jendela dialog tombol untuk menolak lagi / memutuskan nanti, dan tombol untuk memberikan izin. Tombol izin izin dalam dialog rasional, harus memulai permintaan izin lagi. Kali ini pengguna juga akan memiliki kotak centang "Jangan tampilkan lagi". Jika dia memutuskan untuk memilihnya, dan menolak izin lagi, itu akan memberi tahu sistem Android bahwa pengguna dan aplikasi tidak berada di halaman yang sama. Tindakan itu akan memiliki dua konsekuensi - shouldShowRequestPermissionRationale () akan selalu mengembalikan false,

Tetapi ada juga skenario lain yang mungkin di mana onRequestPermissionsResult dapat digunakan. Misalnya beberapa perangkat mungkin memiliki kebijakan perangkat yang menonaktifkan kamera (berfungsi untuk CIA, DARPA, dll.). Di perangkat ini, onRequestPermissionsResult akan selalu mengembalikan false, dan metode requestPermissions () akan secara diam-diam menolak permintaan tersebut.

Itulah yang saya kumpulkan dengan mendengarkan podcast dengan Ben Poiesz - seorang manajer produk pada kerangka Android.
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html


6

Cukup poskan opsi lain, jika ada yang mau. Anda dapat menggunakan EasyPermissions yang disediakan oleh Google sendiri, untuk, sebagaimana dikatakan, "Sederhanakan izin sistem Android M".

Maka Anda tidak harus menangani shouldShowRequestPermissionRationalesecara langsung.


mengapa saya tidak melihat proyek ini sebelumnya :)
Vlad

Masalah dengan EasyPermissions tetap hampir sama. Meminta secara permissionPermanentlyDeniedinternal hanya menelepon shouldShowPermissionsRationaledan kembali truejika pengguna tidak pernah diminta untuk memberikan izin.
hgoebl

4

Jika ada yang tertarik dengan solusi Kotlin, saya refactored jawaban @mururaj berada di Kotlin. Juga sedikit dimodernisasi untuk memiliki blok penyelesaian bukan pendengar.

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)
        }
    }
}

Penerapan

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

3

Periksa implementasi ini. bekerja cukup baik untuk saya. pada dasarnya Anda memeriksa izin dalam metode checkPermissions () melewati daftar izin. Anda memeriksa hasil permintaan izin pada onRequestPermissionsResult (). Implementasinya memungkinkan Anda mengatasi kedua kasus tersebut ketika pengguna memilih "tidak pernah bertanya lagi" atau tidak. Dalam implementasi ini, jika se memilih "tidak pernah bertanya lagi", dialog memiliki opsi untuk membawanya ke Aktivitas Pengaturan Aplikasi.

Semua kode ini ada di dalam fragmen saya. Saya berpikir bahwa akan lebih baik untuk membuat kelas khusus untuk melakukan ini, seperti PermissionManager, tetapi saya tidak yakin tentang itu.

/**
     * 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

Semoga bermanfaat bagi seseorang: -

Apa yang saya perhatikan adalah, jika kita memeriksa flag shouldShowRequestPermissionRationale () untuk metode callback onRequestPermissionsResult (), itu hanya menunjukkan dua negara.

Status 1: -Kembalikan benar: - Kapan saja pengguna mengklik Tolak izin (termasuk saat pertama kali).

Status 2: -Returns false: - jika pengguna memilih "tidak pernah bertanya lagi".

Tautan untuk contoh kerja rinci .


6
itu mengembalikan false untuk pertama kalinya. tidak benar
JoM

Ya, itulah yang saya sebutkan, jika Anda memeriksa tanda di dalam metode panggilan balik onRequestPermissionsResult (), ia akan memiliki dua status saja, khususnya dalam panggilan balik ini.
Nicks

2
Sayangnya, shouldShowRequestPermissionRationale selalu mengembalikan false - terlepas dari apakah pengguna pernah menolak izin atau tidak.
IgorGanapolsky

1

Kita bisa melakukannya dengan cara ini?

@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;
        }
    }
}

Sayangnya, kode ini tidak membedakan antara situasi di mana izin tidak pernah diminta sebelumnya dan di mana "tidak pernah meminta lagi" diperiksa.
Ben

Anda harus menggunakan kombinasi + kelas pembantu izin ini untuk memeriksa apakah izin itu diberikan atau tidak.
Dr. aNdRO

0

shouldShowRequestPermissionRationale untuk izin KHUSUS selalu mengembalikan BENAR SAJA setelah pengguna menolaknya tanpa kotak centang

Kami tertarik pada nilai SALAH

Jadi ada 3 kasus hilang dengan nilai palsu :

1. tidak ada tindakan seperti itu sebelumnya dan sekarang pengguna memutuskan untuk menyetujui atau menolak.

Cukup tentukan preferensi ASKED_PERMISSION_*yang tidak ada sekarang dan akan berlaku pada onRequestPermissionsResultsaat itu dimulai dalam hal setuju atau menolak

Jadi, sementara preferensi ini tidak ada, tidak ada alasan untuk memeriksashouldShowRequestPermissionRationale

2. pengguna mengklik setuju.

Cukup lakukan:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

Yang akan mengembalikan true dan tidak ada alasan untuk memeriksashouldShowRequestPermissionRationale

3. pengguna mengklik tolak dengan kotak centang (diminta kedua kali atau lebih)

Ini WAKTU bekerja dengan shouldShowRequestPermissionRationaleyang akan kembali SALAH

(preferensi ada dan kami tidak memiliki izin)


0

Kode ini meminta pengguna untuk meminta izin selama runtime, jika pengguna mengizinkan, itu menjalankan metode hasil, jika pengguna menolak, ia bertanya lagi dengan discription dengan pengguna deny (itu bertanya lagi dengan instruksi), tetapi jika pengguna memilih tidak pernah bertanya lagi. itu menangani tidak pernah bertanya lagi, menampilkan opsi pengaturan terbuka dengan instruksi.

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;
                }
        }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.