Android M İzinleri: shouldShowRequestPermissionRationale () işlevinin kullanımında karışıklık


154

Android M'deki yeni İzinler modeliyle ilgili resmi belgeye bakıyordum . Uygulama daha önce bu izni talep etmiş ve kullanıcı isteği reddetmişse shouldShowRequestPermissionRationale()geri dönen işlevden bahsediyor true. Kullanıcı geçmişte izin isteğini geri çevirdiyse ve Bir daha sorma seçeneğini seçtiyse, bu yöntem geri döner false.

Ancak aşağıdaki iki durumu nasıl ayırt edebiliriz?

Durum 1 : Uygulamanın bir izni yok ve kullanıcıdan daha önce izin istenmemiş. Bu durumda, shouldShowRequestPermissionRationale (), kullanıcıya ilk defa sorduğumuz için yanlış döndürür.

Durum 2 : Kullanıcı izni reddetti ve "Bir daha sorma" seçeneğini seçti, bu durumda daShowRequestPermissionRationale () yanlış döndürecektir.

Kullanıcıyı Durum 2'deki Uygulamanın ayarlar sayfasına göndermek istiyorum. Bu iki durumu nasıl ayırt edebilirim?


1
Kabul edilen cevap güzel. Alternatif olarak, uygulamanın önceden izin isteyip istemediğini öğrenmek için paylaşılan bir tercih de kullanabilirsiniz. Başka birinin durumuna daha uygun olması ihtimaline karşı bunu oraya atıyorum.
Rockin4Life33

4
Durum 3 de var: Kullanıcıdan izin istendi ve izin verildi / reddedildi, ancak izin ayarlarını "her seferinde sor" seçeneğine geri dönmek için kullandı. Test, shouldShowRequestPermissionRationale()bu durumda yanlış döndürür, bu da "daha önce sordum mu" bayrağına bağlı olarak herhangi bir koda zarar verir.
Logan Pickup

İşte permissionsAndroid'deki en iyi uygulamaları gösteren bir Google örneği . github.com/android/permissions-samples
itabdullah

@itabdullah Google'ın örnek kodu, "son seferde kullanıcı izni reddetti mi" şeklindeki kullanım olasılığını dikkate almadıkları için işe yaramaz. : - / tipik
Biri Somewhere

Yanıtlar:


178

M Önizleme 1'den sonra, iletişim kutusu ilk kez görüntüleniyorsa , Bir daha asla sorma onay kutusu yoktur.

Kullanıcı izin talebini reddederse , ikinci kez izin istendiğinde izin iletişim kutusunda bir Daha asla sorma onay kutusu olacaktır .

Öyleyse mantık şöyle olmalı:

  1. İzin isteyin:

    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. İznin reddedilip verilmediğini kontrol edin onRequestPermissionsResult.

    İzin daha önce reddedilmişse, bu kez izin iletişim kutusunda Bir daha asla sorma onay kutusu olacaktır.

    shouldShowRequestPermissionRationaleKullanıcının Bir daha asla sorma seçeneğini işaretleyip işaretlemediğini görmek için arayın . shouldShowRequestPermissionRationaleyöntem yalnızca, kullanıcı Bir daha asla sorma seçeneğini belirlediğinde veya cihaz politikası uygulamanın bu izne sahip olmasını yasakladığında yanlış döndürür :

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

Böylece, bir kullanıcının bir daha asla sorma ya da sorma seçeneğini işaretleyip işaretlemediğini izlemeniz gerekmez.


53
Açıklığa kavuşturmak için bir nokta, shouldShowRequestPermissionRationale (), kullanıcıdan hiçbir zaman izin istenmemişse (yani, uygulama ilk çalıştırıldığında) da false değerini döndürür. Verilen örneğin mantığını izlerseniz bu durumla karşılaşmazsınız. Ancak 2'nin altındaki ifade biraz yanıltıcıdır.
Ben

15
Emin değilim, bu kusurlu görünüyor. Kullanıcıya ilk defa sorulduğunu nasıl bileceğiz? Kullanıcıya sorulup sorulmadığını izlemem gerekiyor ve yaptıysa, mantığı tersine çevirmem gerekiyor. Bana mantıklı gelmiyor.
Daniel F

4
Ben bunu geçen nerede belirterek değer olduğunu düşünüyorum contextiçinde ActivityCompat.shouldShowRequestPermissionRationale(...)parametresinin aslında tiptedir Activity. Hepinizi etkilemeyebilir ama benim durumumda etkiliyor.
aProperFox

9
Bu android mantığı çok aptalca! Beni geri aramada aramaya shouldVE NVM'deki sayaç değerini kaydetmeye zorlar, sadece uygulamanın bir sonraki açılışında isteği tekrar sormam gerekip gerekmediğini bilmek için! ... wow (facepalm) ... bir durum numaralandırması döndüren yalnızca bir çağrı yapmak çok mu zordu ??
Shockwaver

4
Bunun Google tarafından büyük bir başarısızlık olduğunu düşünüyorum. Resmi belgeler, shouldShowRequestPermissionRationale () 'nin izinler kontrol edilmeden önce çağrılması gerektiğini belirtir (bkz. Developer.android.com/training/permissions/requesting#explain ), ancak StackOverflow'daki tüm yanıtlar, onRequestPermissionResult () içinde kullanıcı "Bir daha asla sorma" seçeneğini tıkladı veya tıklamadı.
Miloš Černilovský

22

Aynı sorunu yaşadım ve anladım. Hayatı daha basit hale getirmek için, çalışma zamanı izinlerini işlemek için bir util sınıfı yazdım.

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

Ve PreferenceUtil yöntemler aşağıdaki gibi bulunmaktadır.

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

Şimdi, ihtiyacınız olan tek şey checkPermission yöntemini uygun argümanlarla kullanmaktır.

İşte bir örnek,

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

Durum 1: Uygulamanın bir izni yok ve kullanıcıdan daha önce izin istenmemiş. Bu durumda, shouldShowRequestPermissionRationale (), kullanıcıya ilk defa sorduğumuz için yanlış döndürür.

Durum 2: Kullanıcı izni reddetti ve "Bir daha sorma" seçeneğini seçti, bu durumda daShowRequestPermissionRationale () yanlış döndürecektir.

Kullanıcıyı Durum 2'deki Uygulamanın ayarlar sayfasına göndermek istiyorum. Bu iki durumu nasıl ayırt edebilirim?

Üzerinde geri arama alırsınız onPermissionAsk durumda 1 ve onPermissionDisabled durumda 2 için.

Mutlu kodlamalar :)


Mükemmel açıklama kardeşim. Aynı prosedürü izledim. :)
Sumit Jha

Bu Aktivite için ne doldurmalıyım? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Mardymar

@Mardymar thisActivitybaşka bir şey değil YourActivity.this.
muthuraj

1
birden çok iznin nasıl işleneceği ve bu kodun parça içine nasıl entegre edileceği.
Taimur

Ne tür contextkullanıyorsun? shouldShowRequestPermissionRationale(permission)içinde mevcut değil android.content.Context. bu ActivityCompat
Hilikus

9

GÜNCELLEME

CanC'nin aşağıdaki cevabının takip edilmesi gereken doğru cevap olduğuna inanıyorum . Kesin olarak bilmenin tek yolu, shouldShowPermissionRationale kullanarak bunu onRequestPermissionResult geri aramasında doğrulamaktır.

==

Orijinal cevabım:

Bulduğum tek yol, bunun ilk kez olup olmadığını kendi başınıza takip etmektir (örneğin, paylaşılan tercihleri ​​kullanarak). İlk sefer değilse, shouldShowRequestPermissionRationale()ayırt etmek için kullanın .

Ayrıca bkz .: Android M - çalışma zamanı iznini kontrol edin - kullanıcının "Bir daha asla sorma" seçeneğini işaretleyip işaretlemediğini nasıl belirleyebilirim?


1
Evet, ben bile CanC'nin yönteminin izlenmesi gereken yöntem olduğuna katılıyorum. Bunu kabul edilen cevap olarak işaretleyeceğim.
akshayt23

6

Anladığım kadarıyla shouldShowRequestPermissionRationale (), başlık altında bir dizi kullanım durumu çalıştırıyor ve istenen izinler hakkında bir açıklama gösterip göstermeyeceğini uygulamaya bildiriyor.

Çalışma Süresi izinlerinin arkasındaki fikir, kullanıcının çoğu zaman izin isteğine Evet diyecek olmasıdır. Bu şekilde kullanıcının yalnızca bir tıklama yapması gerekecektir. Elbette talep doğru bağlamda kullanılmalıdır - yani "Kamera" düğmesine basıldığında Kamera izni istemek.

Kullanıcı isteği reddederse, ancak bir süre sonra tekrar "Kamera" düğmesine basarsa, shouldShowRequestPermissionRationale () true değerini döndürür, böylece uygulama, iznin neden istendiğini ve uygulamanın neden istemediğini anlamlı bir açıklama gösterebilir. onsuz düzgün çalışın. Normalde, bu iletişim penceresinde tekrar reddetmek / daha sonra karar vermek için bir düğme ve izinleri vermek için bir düğme gösterirsiniz. Gerekçe iletişim kutusundaki izinleri ver düğmesi, izin talebini yeniden başlatmalıdır. Bu kez kullanıcı ayrıca "Bir daha asla gösterme" onay kutusuna sahip olacaktır. Seçmeye karar verir ve izni tekrar reddederse, Android sistemine kullanıcı ve uygulamanın aynı sayfada olmadığını bildirir. Bu eylemin iki sonucu olacaktır - shouldShowRequestPermissionRationale () her zaman false döndürür,

Ancak onRequestPermissionsResult'un kullanılabileceği başka bir olası senaryo da vardır. Örneğin, bazı cihazlarda kamerayı devre dışı bırakan bir cihaz politikası olabilir (CIA, DARPA, vb. İçin çalışır). Bu cihazlarda onRequestPermissionsResult her zaman yanlış döndürür ve requestPermissions () yöntemi isteği sessizce reddeder.

Android çerçevesinde bir ürün yöneticisi olan Ben Poiesz ile podcast'i dinleyerek topladığım şey buydu.
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html


6

İsteyen varsa başka bir seçenek yayınlayın. "Android M sistem izinlerini basitleştirmek" için Google'ın kendisi tarafından sağlanan EasyPermissions programını kullanabilirsiniz .

O zaman shouldShowRequestPermissionRationaledoğrudan halletmek zorunda değilsin .


neden bu projeyi önceden görmedim :)
Vlad

EasyPermissions ile ilgili sorun neredeyse aynı kalıyor. permissionPermanentlyDeniedDahili olarak sormak , kullanıcının hiçbir zaman izin vermesinin istenmediği durumda sadece arar shouldShowPermissionsRationaleve geri döner true.
hgoebl

4

Bir Kotlin çözümüyle ilgilenen varsa, @muthuraj yanıtını Kotlin'de olacak şekilde yeniden düzenledim. Ayrıca, dinleyiciler yerine bir tamamlama bloğuna sahip olacak şekilde biraz modernize edildi.

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

Uygulama

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

3

Bu uygulamayı kontrol edin. benim için oldukça iyi çalışıyor. temelde checkPermissions () yöntemindeki izinleri bir izinler listesini ileterek kontrol edersiniz. İzin isteğinin sonucunu onRequestPermissionsResult () üzerinde kontrol edersiniz. Uygulama, kullanıcı "bir daha asla sorma" seçeneğini seçip seçmediğinde her iki durumu da ele almanıza olanak tanır. Bu uygulamada, se'nin "bir daha asla sorma" seçeneğini seçmesi durumunda, iletişim kutusunda onu Uygulama Ayarları Etkinliğine götürme seçeneği vardır.

Bütün bu kod, parçamın içinde. Bunu yapmak için bir PermissionManager gibi özel bir sınıf oluşturmanın daha iyi olacağını düşünüyordum, ama bundan emin değilim.

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

Birisi için yararlı olabilir: -

Fark ettiğim şey, onRequestPermissionsResult () geri çağrı yönteminde shouldShowRequestPermissionRationale () bayrağını kontrol edersek, yalnızca iki durum gösterir.

Durum 1: -Return true: - Kullanıcı izinleri Reddet'i tıkladığında (ilk sefer dahil).

Durum 2: -Yanlış döner: - kullanıcı "bir daha asla sormaz" ı seçerse.

Ayrıntılı çalışma örneği için bağlantı .


6
ilk kez yanlış döndürür . doğru değil
JoM

Evet, bahsettiğim şey bu, onRequestPermissionsResult () geri çağrı yöntemindeki bayrağı kontrol ederseniz, özellikle bu geri aramada yalnızca iki duruma sahip olacaktır.
Nicks

2
Ne yazık ki, shouldShowRequestPermissionRationale her zaman yanlış döndürür - kullanıcı izni reddetmiş olsun ya da olmasın.
IgorGanapolsky

1

Bu şekilde yapabilir miyiz?

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

Maalesef bu kod, iznin daha önce hiç talep edilmediği ve "bir daha asla talep etme" seçeneğinin işaretlendiği bir durum arasında ayrım yapmaz.
Ben

İznin verilip verilmediğini kontrol etmek için bu + izin yardımcı sınıfının kombinasyonunu kullanmalısınız.
Dr Andro

0

shouldShowRequestPermissionRationale ÖZEL izin için her zaman YALNIZCA kullanıcı onay kutusu olmadan reddettikten sonra DOĞRU döndür

YANLIŞ değerle ilgileniyoruz

Yani yanlış değerle kaybedilen 3 vaka var :

1. Daha önce böyle bir işlem yoktu ve şimdi kullanıcı kabul etmeye veya reddetmeye karar veriyor.

Basitçe bir tercih tanımlamak ASKED_PERMISSION_*şimdi yok ve olacağını doğrudur içinde onRequestPermissionsResultbunun her durumda başlangıç oluyor katılıyorum ya da reddetmek

Yani bu tercih mevcut olmasa da kontrol etmek için bir neden yokshouldShowRequestPermissionRationale

2. kullanıcı kabul etti.

Yapmanız gereken sadece:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

Hangisi doğru dönecek ve kontrol etmek için bir neden yokshouldShowRequestPermissionRationale

3. kullanıcı onay kutusuyla reddet'i tıkladı (ikinci veya daha fazla kez soruldu)

O var ZAMAN ile işe shouldShowRequestPermissionRationalehangi dönecektir YANLIŞ

(tercih var ve iznimiz yok)


0

Bu kod, çalıştırma sırasında kullanıcıdan izin istemesini ister, eğer kullanıcı izin verirse, sonuç yöntemini çalıştırır, eğer kullanıcı reddederse, kullanıcı reddiyle açıklama ile tekrar sorar (talimatlarla tekrar sorar), ancak kullanıcı bir daha asla sormayı seçerse. bir daha asla sorma, talimatlarla birlikte açık ayarlar seçeneğini görüntüler.

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

0
public void requestPermission(View view){
        if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            if(ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)){

//The Alert Dialog before asking for the second time to help the user understand  why he needs to give permission.

                AlertDialog alert = new AlertDialog.Builder(this).setMessage("Without the permissions you cannot run the application")
                        .setCancelable(false)
                        .setPositiveButton("Okay, I understand", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
                            }
                        }).setNegativeButton("No, Exit the App", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        System.exit(2);
                    }
                }).create();
                alert.setTitle("ALERTY");
                alert.show();
//End of the alert Dialog
            }
            else{
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
            }
        }
        else {
            textView.setText("Permission Is Already Granted");
        }
    }
    /*
     The shouldShowRequestPermissionRationale() function returns true if the app has requested this permission
     previously and the user denied the request.If the user turned down the permission request in the past and chose
     the Don't ask again option, this method returns false.
      */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode == REQUEST_FINE_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                textView.setText("Hooray! on Request Permissions Grantred");
            }
            else{
                //Since the user has choosen the don't ask again option,
                if(!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)){

//Alert Dialog that will take user to settings where he can manually give the permissions
                    AlertDialog alert = new AlertDialog.Builder(this).setMessage("You have permanently disabled the permission ")
                            .setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                             openSettings();
                        }
                    }).setNegativeButton("Don't Go",null).setCancelable(false).create();
                  alert.setTitle("Give permission manually");
                  alert.show();
 // End of the Alert Dialog
                }
                else{
                    textView.setText("Permission has been denied the 1st time");
                }
            }
        }
    }

Bu openSettings yöntemidir.

    public void openSettings(){
        Intent intent = new Intent();

        Uri uri = Uri.fromParts("package",this.getPackageName(),null);
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri);
        startActivity(intent);
    }

Niyeti, kullanıcının daha önce izinleri manuel olarak verebileceği Bir daha gösterme düğmesini işaretlemiş olması durumunda ayarlar sayfasına yönlendirilecek şekilde oluşturdum .
Arpit Anand
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.