Android M - çalışma zamanı iznini kontrol et - kullanıcının “Bir daha sorma” seçeneğini işaretleyip belirlemediği nasıl belirlenir?


307

Buna göre: http://developer.android.com/preview/features/runtime-permissions.html#coding bir uygulama, daha önce verilmemişse çalışma zamanı izinlerini kontrol edebilir ve izinleri isteyebilir. Aşağıdaki iletişim kutusu görüntülenecektir:

resim açıklamasını buraya girin

Kullanıcının önemli bir izni reddetmesi durumunda, imo bir uygulama, iznin neden gerekli olduğunu ve etkinin azalmasının ne olduğunu açıklamalıdır. Bu iletişim kutusunun iki seçeneği vardır:

  1. tekrar deneyin (izin tekrar istenir)
  2. reddet (uygulama bu izin olmadan çalışacaktır).

Never ask againAncak kullanıcı kontrol ederse , özellikle kullanıcı daha önce bir kez reddetmişse, açıklamalı ikinci iletişim kutusu gösterilmemelidir. Şimdi soru şu: Uygulamam kullanıcının kontrol edip etmediğini nasıl biliyor Never ask again? IMO onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)bana bu bilgiyi vermiyor.

İkinci bir soru şudur: Google'ın izin iletişim kutusuna uygulamanın neden izne ihtiyacı olduğunu açıklayan özel bir mesaj eklemeyi planlıyor mu? Bu şekilde kesinlikle daha iyi bir ux yapmak için asla ikinci bir iletişim olmazdı.


9
"Google'ın izin iletişim kutusuna uygulamanın neden izne ihtiyacı olduğunu açıklayan özel bir mesaj eklemeyi planlıyor mu?" - M izin sistemi hakkındaki Google I | O sunumunda, soru ve cevap bölümünde sorulan birisini hatırlıyorum ve cevap, bunun hakkında düşünüyor olmasıydı.
CommonsWare

1
Bunu kendim test etmedim, ancak belgeler Activity.shouldShowRequestPermissionRationale (String) hakkında söylüyor: Uygulama daha önce bu izni isterse ve kullanıcı isteği reddederse, bu yöntem true değerini döndürür. Bu, muhtemelen izne neden ihtiyacınız olduğunu kullanıcıya açıklamanız gerektiğini gösterir. Kullanıcı geçmişte izin isteğini geri çevirdiyse ve izin istek sistemi iletişim kutusundaki Bir daha sorma seçeneğini belirlediyse, bu yöntem false değerini döndürür. Cihaz politikası uygulamanın bu izne sahip olmasını yasakladıysa da yöntem false değerini döndürür.
Korkarım hayır

1
@Fraid: Android M önizleme 2 ile bunu ekledikleri anlaşılıyor: developer.android.com/preview/support.html#preview2-notes ve muhtemelen aradığım şey bu. Şu anda test edemiyorum ama önümüzdeki hafta yapacağım. Umarım yaptığı şeyi yaparsa, bir cevap olarak gönderebilir ve itibar kazanabilirsiniz. Bu arada bu başkalarına yardımcı olabilir: youtube.com/watch?v=f17qe9vZ8RM
Emanuel Moecklin

Tehlikeli İzinler ve Özel İzinler örneği: github.com/henrychuangtw/AndroidRuntimePermission
HenryChuang

1
@Alex geliştiriciler için kesinlikle daha zor ama kullanıcı perspektifinden belirli izinleri verebilme veya reddedebilme mantıklı. Gördüğüm temel sorun, izinlerin ayrıntı düzeyinin çok tutarsız olması ve uygulamanızda yapmaya çalıştığınız şeyle hemen hemen hiçbir ilgisi olmayabilecek bir izin istemenizdir (örneğin, bağlanmak istediğimde kişi izni) Google Drive, kimlik doğrulama amacıyla cihaz hesaplarının bir listesine ihtiyaç duyduğundan ve hesap izninin kişi izin grubunun bir parçası olması nedeniyle).
Emanuel Moecklin

Yanıtlar:


341

Geliştirici Önizleme 2, uygulama tarafından izinlerin istenmesinde bazı değişiklikler getirir (ayrıca bkz . Http://developer.android.com/preview/support.html#preview2-notes ).

İlk iletişim kutusu şimdi şöyle:

resim açıklamasını buraya girin

"Bir daha asla gösterme" onay kutusu yoktur (geliştirici önizlemesi 1'in aksine). Kullanıcı izni reddederse ve izin uygulama için gerekliyse, uygulamanın bu izni istemesinin nedenini açıklamak için başka bir iletişim kutusu sunabilir, örneğin:

resim açıklamasını buraya girin

Kullanıcı tekrar reddederse, uygulamanın bu izne kesinlikle ihtiyacı varsa kapatılması veya sınırlı işlevlerle çalışmaya devam etmesi gerekir. Kullanıcı yeniden düşünürse (ve yeniden denemeyi seçerse), izin tekrar istenir. Bu sefer bilgi istemi şöyle görünür:

resim açıklamasını buraya girin

"Bir daha sorma" onay kutusu ikinci kez görüntülendiğinde. Kullanıcı tekrar reddederse ve onay kutusu işaretliyse başka bir şey olmamalıdır. Onay kutusunun işaretlenip işaretlenmediği Activity.shouldShowRequestPermissionRationale (String) kullanılarak belirlenebilir, örneğin:

if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {...

Android dokümantasyonu böyle diyor ( https://developer.android.com/training/permissions/requesting.html ):

Ek açıklama sağlamanız gereken durumları bulmanıza yardımcı olmak için, sistem Activity.shouldShowRequestPermissionRationale (String) yöntemini sağlar. Uygulama daha önce bu izni isterse ve kullanıcı isteği reddederse, bu yöntem true değerini döndürür. Bu, muhtemelen izne neden ihtiyacınız olduğunu kullanıcıya açıklamanız gerektiğini gösterir.

Kullanıcı geçmişte izin isteğini geri çevirdiyse ve izin istek sistemi iletişim kutusundaki Bir daha sorma seçeneğini belirlediyse, bu yöntem false değerini döndürür. Cihaz politikası uygulamanın bu izne sahip olmasını yasakladıysa da yöntem false değerini döndürür.

Kullanıcının "bir daha asla sorma" seçeneğini reddetmiş olup olmadığını bilmek için, kullanıcı izin vermediğinde onRequestPermissionsResult öğenizde shouldShowRequestPermissionRationale yöntemini tekrar kontrol edebilirsiniz .

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION) {
        // for each permission check if the user granted/denied them
        // you may want to group the rationale in a single dialog,
        // this is just an example
        for (int i = 0, len = permissions.length; i < len; i++) {
            String permission = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
            // user rejected the permission
                boolean showRationale = shouldShowRequestPermissionRationale( permission );
                if (! showRationale) {
                    // user also CHECKED "never ask again"
                    // you can either enable some fall back,
                    // disable features of your app
                    // or open another dialog explaining
                    // again the permission and directing to
                    // the app setting
                } else if (Manifest.permission.WRITE_CONTACTS.equals(permission)) {
                    showRationale(permission, R.string.permission_denied_contacts);
                    // user did NOT check "never ask again"
                    // this is a good place to explain the user
                    // why you need the permission and ask if he wants
                    // to accept it (the rationale)
                } else if ( /* possibly check more permissions...*/ ) {
                }
            }
        }
    }
}

Uygulama ayarınızı şu kodla açabilirsiniz:

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);

Kullanıcıyı doğrudan Yetkilendirme sayfasına göndermenin bir yolu yoktur.


30
Kullanıcı "Bir daha asla sorma" seçili olup olmadığını kontrol etmek için false için shouldShowRequestPermissionRationale () yönteminin dönüş değerini doğruladım. Ama aynı zamanda ilk kez izin istediğinde değerini yanlış olarak alıyorum. Bu nedenle, kullanıcı "Bir daha asla sorma" onay kutusunu seçtiyse veya ayırt edemezse ayırt edemiyorum. Lütfen önermek ??
Sagar Trehan

32
Anladığım kadarıyla üç durumda shouldShowRationalePermissionRationale () yöntemi false değerini döndürür: 1. İzin almadan önce bu yöntemi ilk kez çağırırsak. 2. Kullanıcı "Bir daha sorma" seçeneğini belirlerse ve izin vermezse. 3. Cihaz politikası uygulamanın bu izni almasını yasaklarsa
Sagar Trehan

24
Hepsi iyi ... ama biz, geliştiriciler, gerçekten kullanıcının "bir daha sorma" dediğini bilmeliyiz. Bir özelliğe erişmek için güzel bir düğmem var. Kullanıcı ilk tıklattığında: gerekçe sormalı mı? hayır, izin isteyin. Kullanıcı reddediyor. Kullanıcı düğmeyi tekrar tıkla: mantık? Evet! Gerekçeyi göster, kullanıcı Tamam deyin, sonra inkar edin ve bir daha asla sormayın (tamam o bir aptal, ancak kullanıcılar genellikle). Daha sonra kullanıcı düğmeye tekrar basın, gerekçe? hayır, izin isteyin, kullanıcı için hiçbir şey olmuyor. Kullanıcıya söylemek için gerçekten bir yola ihtiyacım var: hey man bu özelliği istiyorsanız şimdi uygulama ayarlarına gidin ve izin verin.
Daniele Segato

4
Great @EmanuelMoecklin, Google Dokümantasyonundan şimdi daha iyi: D
Daniele Segato

4
OnRequestPermissionsResult, siz izin istemedikçe çağrılmaz. İzin ilk istendiğinde "Bir daha sorma" onay kutusu olmadığından, shouldShowRequestPermissionRationale True değerini döndürür (izin istendi, ancak bir daha sorma). Sonuç olarak, kullanıcı izni ilk kez reddettiğinde ancak bundan sonra sadece onay kutusu işaretlenmediğinde mantık gösterilir.
Emanuel Moecklin

95

Kontrol shouldShowRequestPermissionRationale()edebilirsiniz onRequestPermissionsResult().

shouldShowRequestPermissionRationale https://youtu.be/C8lUdPVSzDk?t=2m23s

İzin verilip verilmediğini kontrol edin onRequestPermissionsResult(). Eğer değil sonra kontrol shouldShowRequestPermissionRationale().

  1. Bu yöntem geri dönerse true, bu özel iznin neden gerekli olduğuna dair bir açıklama gösterin. Sonra tekrar kullanıcının seçimine bağlı olarak requestPermissions().
  2. Geri dönerse false, izin verilmediğini ve uygulamanın daha fazla ilerleyemediğini veya belirli bir özelliğin devre dışı bırakıldığını gösteren bir hata mesajı gösterin.

Aşağıda örnek kod verilmiştir.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case STORAGE_PERMISSION_REQUEST:
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted :)
                downloadFile();
            } else {
                // permission was not granted
                if (getActivity() == null) {
                    return;
                }
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    showStoragePermissionRationale();
                } else {
                    Snackbar snackbar = Snackbar.make(getView(), getResources().getString(R.string.message_no_storage_permission_snackbar), Snackbar.LENGTH_LONG);
                    snackbar.setAction(getResources().getString(R.string.settings), new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (getActivity() == null) {
                                return;
                            }
                            Intent intent = new Intent();
                            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
                            intent.setData(uri);
                            OrderDetailFragment.this.startActivity(intent);
                        }
                    });
                    snackbar.show();
                }
            }
            break;
    }
}

Görünüşe göre, google maps tam olarak konum izni için bunu yapıyor.


Resim ve Youtube bağlantısı için teşekkürler. Kendi cevabımla aşağı yukarı eşleşiyor. Sorunun, shouldShowRequestPermissionRationale yöntemine sahip olmayan yalnızca geliştirici önizlemesi 1 kullanılabilir olduğunda sorulduğunu belirtmek gerekir.
Emanuel Moecklin

android yeni ve ben bu onRequestPermissionsResult () yöntemi binmek istiyorum. ama bir süper tip yöntemi uygulamak gerekir hata alıyorum. Bunu nasıl kullanacağınızı söyleyebilir misiniz
Andrain

39

Mevcut izin durumunu kontrol etmek için güzel ve kolay bir yöntem:

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

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

    @PermissionStatus 
    public static int getPermissionStatus(Activity activity, String androidPermissionName) {
        if(ContextCompat.checkSelfPermission(activity, androidPermissionName) != PackageManager.PERMISSION_GRANTED) {
            if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermissionName)){
                return BLOCKED_OR_NEVER_ASKED;
            }
            return DENIED;
        }
        return GRANTED;
    }

Dikkat: kullanıcı, kullanıcı istemi aracılığıyla izni kabul etmeden / reddetmeden önce (sdk 23+ cihazlarda) BLOCKED_OR_NEVER_ASKED ilk uygulama başlangıcını döndürür

Güncelleme:

Android desteği kütüphane şimdi de çok benzer bir sınıf var gibi görünüyor android.support.v4.content.PermissionCheckerbir içeriyor checkSelfPermission()hangi döner:

public static final int PERMISSION_GRANTED = 0;
public static final int PERMISSION_DENIED = -1;
public static final int PERMISSION_DENIED_APP_OP = -2;

1
İlk lansman için, bir booleanı paylaşılan tercihlerde saklıyorum.
Saeid Farivar

5
Bu BLOCKED_OR_NEVER_ASKEDizin henüz istenmediyse her zaman geri döner .
Saket

6
Evet, "BLOCKED_OR_NEVER_ASKED" adının nedeni de bu, son cümleyi de görmek
Patrick Favre

3
android.content.pmzaten tanımlar PERMISSION_GRANTED = 0ve PERMISSION_DENIED = -1. Belki ayarlanmış BLOCKED_OR_NEVER_ASKED = PERMISSION_DENIED - 1falan?
samis

Bkz mVck ihtar işlemek için aşağıdaki 'ın cevabı.
samis

28

Kullanıcı "Bir daha sorma" olarak işaretledikten sonra soru tekrar görüntülenemez. Ancak kullanıcıya daha önce izni reddettiği ve ayarlarda izin vermesi gerektiği açıklanabilir. Ve onu aşağıdaki kodla ayarlara referanslayın:

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {

    if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // now, you have permission go ahead
        // TODO: something

    } else {

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.READ_CALL_LOG)) {
            // now, user has denied permission (but not permanently!)

        } else {

            // now, user has denied permission permanently!

            Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "You have previously declined this permission.\n" +
                "You must approve this permission in \"Permissions\" in the app settings on your device.", Snackbar.LENGTH_LONG).setAction("Settings", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));

            }
        });
        View snackbarView = snackbar.getView();
        TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setMaxLines(5);  //Or as much as you need
        snackbar.show();

        }

    }
    return;
}

androidX'e geçişte android.support.design.R yerine com.google.android.material.R
Ridha Rezzag

26

Birisi için yararlı olabilir: -

Ne fark ettim, biz onRequestPermissionsResult () geri arama yöntemine shouldShowRequestPermissionRationale () bayrağı kontrol, sadece iki durumu gösterir .

Durum 1: -Dönüş doğru: - Kullanıcı İzinleri reddet'i tıkladığında (ilk kez dahil olmak üzere).

Durum 2: -İade yanlış: - kullanıcı "bir daha asla sormaz" ı seçerse.

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


2
Bu, kullanıcının bir daha sorma seçeneğini seçip seçmediğini algılamanın doğru yoludur.
Muhammed Babar

Ah, buradaki anahtar onRequestPermissionsResult, aslında izin istediğinde değil, bunu ele almanızdır.
Joshua Pinter

26

Sen belirleyebilir izni olmadığını kontrol ederek bunu gerekçe içine gösterilecek olan onRequestPermissionsResult()geri çağırma yöntemiyle. Bir daha asla sorulmayacak bir izin bulduysanız , kullanıcılardan ayarlardan izin vermelerini isteyebilirsiniz.

Tam uygulamam aşağıdaki gibi olacaktır. Hem için çalışır tek veya çoklu izin istekleri. Aşağıdakileri kullanın veya doğrudan kütüphanemi kullanın.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(permissions.length == 0){
        return;
    }
    boolean allPermissionsGranted = true;
    if(grantResults.length>0){
        for(int grantResult: grantResults){
            if(grantResult != PackageManager.PERMISSION_GRANTED){
                allPermissionsGranted = false;
                break;
            }
        }
    }
    if(!allPermissionsGranted){
        boolean somePermissionsForeverDenied = false;
        for(String permission: permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
                //denied
                Log.e("denied", permission);
            }else{
                if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
                    //allowed
                    Log.e("allowed", permission);
                } else{
                    //set to never ask again
                    Log.e("set to never ask again", permission);
                    somePermissionsForeverDenied = true;
                }
            }
        }
        if(somePermissionsForeverDenied){
            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
            alertDialogBuilder.setTitle("Permissions Required")
                    .setMessage("You have forcefully denied some of the required permissions " +
                            "for this action. Please open settings, go to permissions and allow them.")
                    .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                    Uri.fromParts("package", getPackageName(), null));
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .setCancelable(false)
                    .create()
                    .show();
        }
    } else {
        switch (requestCode) {
            //act according to the request code used while requesting the permission(s).
        }
    }
}

hii @nabin benim gereksinimim indirme düğmesine (hangi pdf dosyasını indirmek) tıklayın zaman yazma izni kontrol etmek izin vermek ya da bu kodu kullanmak nasıl reddedilir var! bana plz rehberlik edebilirim
Rucha Bhatt Joshi

merhaba @RuchaBhatt Kütüphaneme bir göz atın. Github.com/nabinbhandari/Android- Ödemeler
Nabin Bhandari

15

Tüm "durumları" (ilk kez reddedildi, reddedildi, sadece "Bir Daha Sorma" ya da kalıcı olarak reddedildi) algılamak istiyorsanız aşağıdakileri yapabilirsiniz:

2 boolean yarat

private boolean beforeClickPermissionRat;
private boolean afterClickPermissionRat;

İzin istemeden önce ilkini ayarlayın:

beforeClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

OnRequestPermissionsResult yönteminizde ikincisini ayarlayın:

afterClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE);

OnRequestPermissionsResult () öğesinde ihtiyacınız olan her şeyi yapmak için aşağıdaki "tablo" yu kullanın (yine de izniniz olup olmadığını kontrol ettikten sonra):

// before after
// FALSE  FALSE  =  Was denied permanently, still denied permanently --> App Settings
// FALSE  TRUE   =  First time deny, not denied permanently yet --> Nothing
// TRUE   FALSE  =  Just been permanently denied --> Changing my caption to "Go to app settings to edit permissions"
// TRUE   TRUE   =  Wasn't denied permanently, still not denied permanently --> Nothing

İzin istemeden önce mantığı göstermek istemiyorsanız requestPermissions öğesini çağırmadan önce shouldShowRequestPermissionRationale öğesini kontrol etmenin bir anlamı yoktur. Gerekçeyi yalnızca kullanıcı reddettikten sonra göstermek, günümüzde çoğu uygulamanın bunu nasıl ele aldığı gibi görünüyor.
Emanuel Moecklin

2
@EmanuelMoecklin, bildiğim kadarıyla, zaten reddedilip edilmediğini kontrol etmenin tek yolu (önce ve sonra kontrol ederek, doğruluk masamda açıklandığı gibi) veya ilk kez inkar ederse (benim durumumda kullanıcıyı yönlendiriyorum) kalıcı olarak reddedildiyse uygulama ayarları)
mVck

1
// TRUE FALSEkullanıcı daha önce reddettikten sonra bir izin verdiğinde de gerçekleşir.
samis

11

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öntemleri aşağıdaki gibidir.

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, tek ihtiyacınız * checkPermission * yöntemini uygun argümanlarla kullanmak.

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

Uygulamam kullanıcının "Bir daha sorma" yı kontrol edip etmediğini nasıl biliyor?

Kullanıcı Bir daha sorma seçeneğini işaretlediyseniz , onPermissionDisabled'da geri arama alırsınız .

Mutlu kodlama :)


shouldShowRequestPermissionRationale burada hata var, plz bana yardımcı olabilir misiniz.
Rucha Bhatt Joshi

i bu yöntemi bulamıyorum gerekirSShowRequestPermissionRationale bağlam alamadım olabilir .. ama iyi ben diğer alternatif çözüm bulundu .. Yardım için teşekkür ederim :)
Rucha Bhatt Joshi

1
Benim hatam. shouldShowRequestPermissionRationale, bağlam yoluyla değil, Etkinlik aracılığıyla kullanılabilir. Bu yöntemi çağırmadan önce bağlamı Etkinlik'e aktararak cevabımı güncelledim. Check it out :)
muthuraj

1
Bu, shouldShowRequestPermissionRationalekullanıcıya gönderilen isteği tercih ederek kaydedilen ilk yanlış değeri döndürmenin tek yoludur . Aynı fikre sahiptim ve cevabını buldum. Güzel iş adamı
MatPag

4

Her izin vakası için tam açıklama

/**
 *    Case 1: User doesn't have permission
 *    Case 2: User has permission
 *
 *    Case 3: User has never seen the permission Dialog
 *    Case 4: User has denied permission once but he din't clicked on "Never Show again" check box
 *    Case 5: User denied the permission and also clicked on the "Never Show again" check box.
 *    Case 6: User has allowed the permission
 *
 */
public void handlePermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // This is Case 1. Now we need to check further if permission was shown before or not

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // This is Case 4.
        } else {
            // This is Case 3. Request for permission here
        }

    } else {
        // This is Case 2. You have permission now you can do anything related to it
    }
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // This is Case 2 (Permission is now granted)
    } else {
        // This is Case 1 again as Permission is not granted by user

        //Now further we check if used denied permanently or not
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // case 4 User has denied permission but not permanently

        } else {
            // case 5. Permission denied permanently.
            // You can open Permission setting's page from here now.
        }

    }
}

4

Rastgele bir iznin istenmesinin engellenip engellenmediğini belirlemek için yararlı bir işlev (Kotlin'de):

private fun isPermissionBlockedFromAsking(activity: Activity, permission: String): Boolean {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED
            && !activity.shouldShowRequestPermissionRationale(permission)
            && PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false)
    }
    return false
}

Bunun kullanılması android.Manifest.permission.READ_PHONE_STATEiçin true, ilk izin isteğinde bulunduğunuzda istediğiniz iznin (ör. ) Adıyla paylaşılan bir tercih boole ayarlanması gerekir .


Açıklama:

Build.VERSION.SDK_INT >= Build.VERSION_CODES.M kodun bir kısmı yalnızca API 23+ düzeyinde çalıştırılabilir.

ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED kontrol etmek için henüz iznimiz yok.

!activity.shouldShowRequestPermissionRationale(permission)kullanıcının uygulamayı tekrar sorup reddetmediğini kontrol etmek için. Bu işlevin tuhaflıkları nedeniyle , aşağıdaki satır da gereklidir.

PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false) önceki satır bu bilgileri döndürmediği için bu, "Asla sorulmamış" ve "Bir daha asla sorma" durumlarını birbirinden ayırmak için kullanılır (ilk izin isteğinde değeri true olarak ayarlamakla birlikte).


4

Kullanıcının 'bir daha asla sorma ' seçeneğini seçip iznini reddetip reddetmediğini kontrol etmek için shouldShowRequestPermissionRationale () yöntemi kullanılabilir. Kod örnekleri bol, bu yüzden böyle bir amaç için nasıl kullanılacağını açıklamak istiyorum, çünkü onun adı ve uygulaması aslında bu daha karmaşık hale getirir düşünüyorum.

Çalışma Zamanında İzin İsteme bölümünde açıklandığı gibi , 'bir daha asla sorma' seçeneği görünürse bu yöntem true değerini döndürür; böylece bir iletişim kutusu ilk kez gösterildiğinde false değerini döndürür, ardından ikinci kez görüntülendiğinde true değerini döndürür ve yalnızca kullanıcı seçeneği seçme iznini reddederse, bu noktada yeniden false değerini döndürür.

Böyle bir vakayı tespit etmek için, false-true-false dizisini algılayabilir veya (daha basit) iletişim kutusunun ilk gösterimini takip eden bir bayrağa sahip olabilirsiniz. Bundan sonra, bu yöntem true veya false değerini döndürür; burada false, seçenek seçildiğinde algılamanızı sağlar.


3

Lütfen bu çözüm için bana taş atmayın.

Bu çalışıyor ama biraz "hacky".

Aradığınızda requestPermissions, geçerli saati kaydedin.

        mAskedPermissionTime = System.currentTimeMillis();

Daha sonra onRequestPermissionsResult

sonuç verilmezse, zamanı tekrar kontrol edin.

 if (System.currentTimeMillis() - mAskedPermissionTime < 100)

Kullanıcı reddet düğmesini bu kadar hızlı tıklayamadığından, geri arama anında olduğundan "bir daha sorma" yı seçtiğini biliyoruz.

Kendi sorumluluğunuzdadır kullanın.


talep edilen iletişim kutusunu 5 dakika görür ve sonra reddedersek ne olur?
saksham

Öyleyse, temel gereksinimi karşılayamıyorsa bunun kullanımı nedir. Bir kod, kabul edilmediği gibi, her durumda tüm gereksinimleri açıkça yerine getirirse bir hack olabilir.
saksham

Evet, bu kötü. Bunun gibi otomatik testçiler bundan daha hızlı tıklamayı
başarabilir

2

Android M'de izin isteği için bir kısayol yazdım. Bu kod ayrıca eski Android sürümleriyle geriye dönük uyumluluğu da ele alıyor.

Tüm çirkin kodu kullanabilir permissions.You talep Etkinlik ayrılıyor takılır ve bir fragman halinde ekstre edilir PermissionRequestManager, aşağıdaki gibidir:

new PermissionRequestManager()
        // We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change 
        // the PermissionReuqestManager class
        .withActivity(this)

        // List all permissions you need
        .withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR)

        // This Runnable is called whenever the request was successfull
        .withSuccessHandler(new Runnable() {
            @Override
            public void run() {
                // Do something with your permissions!
                // This is called after the user has granted all 
                // permissions, we are one a older platform where 
                // the user does not need to grant permissions 
                // manually, or all permissions are already granted

            }
        })

        // Optional, called when the user did not grant all permissions
        .withFailureHandler(new Runnable() {
            @Override
            public void run() {
                // This is called if the user has rejected one or all of the requested permissions
                L.e(this.getClass().getSimpleName(), "Unable to request permission");

            }
        })

        // After calling this, the user is prompted to grant the rights
        .request();

Bir göz atın: https://gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa


2
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
            if (grantResults.length > 0) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    // Denied
                } else {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                        // To what you want
                    } else {
                       // Bob never checked click
                    }
                }
            }
        }
    }
}

2

Bu basit izin kitaplığını deneyin. İzinle ilgili tüm işlemleri 3 kolay adımda gerçekleştirecektir. Zamanımı kurtardı. İzinle ilgili tüm çalışmaları 15 dakikada tamamlayabilirsiniz .

Reddetebilir, Bu bir daha asla isteyemez, İzin için uygulama ayarlarını çağırabilir, Rasyonel bir mesaj verebilir, Reddedilen bir mesaj verebilir, Kabul edilen izinlerin bir listesini verebilir, Reddedilenlerin bir listesini verebilir izinler vb.

https://github.com/ParkSangGwon/TedPermission

1.Adım: Bağımlılığınızı ekleyin

dependencies {
     compile 'gun0912.ted:tedpermission:2.1.1'
     //check the above link for latest libraries
}

2. Adım: İzinleri sorun

TedPermission.with(this)
    .setPermissionListener(permissionlistener)
    .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
    .setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.ACCESS_FINE_LOCATION)
    .check();

3. Adım: İzin yanıtını işleme

PermissionListener permissionlistener = new PermissionListener() {
    @Override
    public void onPermissionGranted() {
        Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPermissionDenied(ArrayList<String> deniedPermissions) {
        Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
    }
};

Harika.
Zamanımı

Güzel, kullanımı kolay
Uray Febri

2

güzel dinleyebilirsiniz.

dinleyici

interface PermissionListener {
    fun onNeedPermission()
    fun onPermissionPreviouslyDenied(numberDenyPermission: Int)
    fun onPermissionDisabledPermanently(numberDenyPermission: Int)
    fun onPermissionGranted()
}

İzin için MainClass

class PermissionUtil {

    private val PREFS_FILENAME = "permission"
    private val TAG = "PermissionUtil"

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val permissionResult = ActivityCompat.checkSelfPermission(context, permission)
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true
            }
        }
        return false
    }

    fun checkPermission(context: Context, permission: String, listener: PermissionListener) {

        Log.i(TAG, "CheckPermission for $permission")

        if (shouldAskPermission(context, permission)) {

            // Load history permission
            val sharedPreference = context.getSharedPreferences(PREFS_FILENAME, 0)
            val numberShowPermissionDialog = sharedPreference.getInt(permission, 0)

            if (numberShowPermissionDialog == 0) {

                (context as? Activity)?.let {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(it, permission)) {
                        Log.e(TAG, "User has denied permission but not permanently")
                        listener.onPermissionPreviouslyDenied(numberShowPermissionDialog)
                    } else {
                        Log.e(TAG, "Permission denied permanently.")
                        listener.onPermissionDisabledPermanently(numberShowPermissionDialog)
                    }
                } ?: kotlin.run {
                    listener.onNeedPermission()
                }

            } else {
                // Is FirstTime
                listener.onNeedPermission()
            }


            // Save history permission
            sharedPreference.edit().putInt(permission, numberShowPermissionDialog + 1).apply()


        } else {
            listener.onPermissionGranted()
        }

    }
}

Bu şekilde kullanılır

      PermissionUtil().checkPermission(this, Manifest.permission.ACCESS_FINE_LOCATION,
                object : PermissionListener {
                    override fun onNeedPermission() {
                        log("---------------------->onNeedPermission")

//                            ActivityCompat.requestPermissions(this@SplashActivity,
//                                    Array(1) { Manifest.permission.ACCESS_FINE_LOCATION },
//                                    118)

                    }

                    override fun onPermissionPreviouslyDenied(numberDenyPermission: Int) {
                        log("---------------------->onPermissionPreviouslyDenied")
                    }

                    override fun onPermissionDisabledPermanently(numberDenyPermission: Int) {
                        log("---------------------->onPermissionDisabled")
                    }

                    override fun onPermissionGranted() {
                        log("---------------------->onPermissionGranted")
                    }

                })

etkinlik veya fragmnet'teki onRequestPermissionsResult öğesini geçersiz kıl

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
 if (requestCode == 118) {
        if (permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocationInMap()
        }
        }
    }

1

Bunun yerine onRequestPermissionsResult(), yanlış duruma düşerken tekrar izin isteğinde PERMISSION_DENIED olarak geri çağrı alacaksınızshouldShowRequestPermissionRationale()

Android doc'dan:

Sistem kullanıcıdan izin vermesini istediğinde, kullanıcıya sistemden bu izni tekrar istememesini söyleme seçeneği vardır. Bu durumda, bir uygulama requestPermissions()bu izni tekrar istemek için kullandığında , sistem isteği hemen reddeder. Sistem, onRequestPermissionsResult()geri arama yönteminizi çağırır PERMISSION_DENIEDve kullanıcı isteğinizi tekrar açıkça reddederse olduğu gibi geçer . Bu requestPermissions(), aradığınızda, kullanıcıyla herhangi bir doğrudan etkileşimin gerçekleştiğini varsayamayacağınız anlamına gelir .


1

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)Asla sorulup sorulmadığını kontrol etmek için yöntemi kullanabilirsiniz .

Daha fazla referans için: Bunu kontrol edin

Birden fazla izin olup olmadığını kontrol etmek için şunu kullanın:

  if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
                            showDialogOK("Service Permissions are required for this app",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            switch (which) {
                                                case DialogInterface.BUTTON_POSITIVE:
                                                    checkAndRequestPermissions();
                                                    break;
                                                case DialogInterface.BUTTON_NEGATIVE:
                                                    // proceed with logic by disabling the related features or quit the app.
                                                    finish();
                                                    break;
                                            }
                                        }
                                    });
                        }
                        //permission is denied (and never ask again is  checked)
                        //shouldShowRequestPermissionRationale will return false
                        else {
                            explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?");
                            //                            //proceed with logic by disabling the related features or quit the app.
                        }

expla () yöntemi

private void explain(String msg){
        final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this);
        dialog.setMessage(msg)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        //  permissionsclass.requestPermission(type,code);
                        startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission")));
                    }
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        finish();
                    }
                });
        dialog.show();
    }

Yukarıdaki kod ayrıca, bir daha asla sorma düğmesini işaretlemişse izin verebileceği yerden uygulama ayarları ekranına yönlendirecektir.


1

Kullanabilirsiniz

shouldShowRequestPermissionRationale()

içeride

onRequestPermissionsResult()

Aşağıdaki örneğe bakın:

Kullanıcı düğmeyi tıkladığında izninin olup olmadığını kontrol edin:

@Override
public void onClick(View v) {
    if (v.getId() == R.id.appCompatBtn_changeProfileCoverPhoto) {
        if (Build.VERSION.SDK_INT < 23) { // API < 23 don't need to ask permission
            navigateTo(MainActivity.class); // Navigate to activity to change photos
        } else {
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                // Permission is not granted yet. Ask for permission...
                requestWriteExternalPermission();
            } else {
                // Permission is already granted, good to go :)
                navigateTo(MainActivity.class);
            }
        } 
    }
}

Kullanıcı izin iletişim kutusunu yanıtladığında onRequestPermissionResult adresine gideceğiz:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == WRITE_EXTERNAL_PERMISSION_REQUEST_CODE) {
        // Case 1. Permission is granted.  
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {  
            if (ContextCompat.checkSelfPermission(SettingsActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                // Before navigating, I still check one more time the permission for good practice.
                navigateTo(MainActivity.class);
            }
        } else { // Case 2. Permission was refused
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                // Case 2.1. shouldShowRequest... returns true because the
                // permission was denied before. If it is the first time the app is running we will 
                // end up in this part of the code. Because he need to deny at least once to get 
                // to onRequestPermissionsResult. 
                Snackbar snackbar = Snackbar.make(findViewById(R.id.relLayout_container), R.string.you_must_verify_permissions_to_send_media, Snackbar.LENGTH_LONG);
                snackbar.setAction("VERIFY", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ActivityCompat.requestPermissions(SettingsActivity.this
                                , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}
                                , WRITE_EXTERNAL_PERMISSION_REQUEST_CODE);
                    }
                });
                snackbar.show();
            } else {
                // Case 2.2. Permission was already denied and the user checked "Never ask again". 
                // Navigate user to settings if he choose to allow this time.
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.instructions_to_turn_on_storage_permission)
                        .setPositiveButton(getString(R.string.settings), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", getPackageName(), null);
                                settingsIntent.setData(uri);
                                startActivityForResult(settingsIntent, 7);
                            }
                        })
                        .setNegativeButton(getString(R.string.not_now), null);
                Dialog dialog = builder.create();
                dialog.show();
            }
        }
    }

}

0

Ayrıca kullanıcının "bir daha asla sorma" yı seçip seçmediğini öğrenmek istiyorum. Çirkin görünümlü bir bayrakla 'neredeyse bir çözüm' elde ettim, ama size nasıl olduğunu söylemeden önce size motivasyonumu anlatacağım:

Başlangıçta işlevsellik referansı izni vermek istiyorum. Kullanıcı bunu kullanıyorsa ve hakları yoksa, 1. iletişim kutusunu yukarıdan ya da 2. ve 3. her ikisinden de alır. Kullanıcı 'Bir daha sorma' seçeneğini belirlediğinde, işlevselliği devre dışı bırakmak ve farklı bir şekilde görüntülemek istiyorum. - Eylemim bir döndürücü metin girişi tarafından tetiklenir, ayrıca görüntülenen etiket metnine '(İzin iptal edildi)' eklemek istiyorum. Bu kullanıcıya gösterir: 'İşlevler var, ancak izin ayarlarım nedeniyle kullanamıyorum.' Ancak, 'Bir daha asla sorma' öğesinin seçilip seçilmediğini kontrol edemediğim için bu mümkün görünmüyor.

İşlevlerimin her zaman etkin bir izin denetimi ile etkinleştirilmesini sağlayarak yaşayabileceğim bir çözüme geldim. Olumsuz bir yanıt durumunda onRequestPermissionsResult () 'de bir Tost mesajı gösteriyorum ama sadece benim özel rasyonel pop-up göstermediysem. Eğer kullanıcı 'Bir daha asla sorma' seçeneğini seçtiyse, sadece bir tost mesajı alır. Kullanıcı 'bir daha asla sorma' seçeneğini seçmek istemiyorsa, yalnızca özel mantığı ve işletim sistemi tarafından izin isteği pop-up penceresini alır, ancak arka arkaya üç bildirim çok fazla acı çekeceğinden tost değildir.


0

Kamera için dinamik izin uygulamam gerekiyor. 3 olası durum olduğunda: 1. İzin ver, 2. Reddedildi, 3. Bir daha sorma.

 @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    for (String permission : permissions) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permission)) {
            //denied
            Log.e("denied", permission);
        } else {
            if (ActivityCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED) {
                //allowed
                Log.e("allowed", permission);
            } else {
                //set to never ask again
                Log.e("set to never ask again", permission);
                //do something here.
            }
        }
    }
    if (requestCode != MaterialBarcodeScanner.RC_HANDLE_CAMERA_PERM) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        return;
    }
    if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
        return;
    } else {
        //set to never ask again
        Log.e("set to never ask again", permissions[0]);
    }
    DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
        }
    };
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle("Error")
            .setMessage(R.string.no_camera_permission)
            .setPositiveButton(android.R.string.ok, listener)
            .show();


}

private void insertDummyContactWrapper() {
        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.CAMERA},
                    REQUEST_CODE_ASK_PERMISSIONS);
            return;
        }
        mScannerView.setResultHandler(this);
        mScannerView.startCamera(mCameraId);
        mScannerView.setFlash(mFlash);
        mScannerView.setAutoFocus(mAutoFocus);
    }

private int checkSelfPermission(String camera) {
    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        return REQUEST_CODE_ASK_PERMISSIONS;
    } else {
        return REQUEST_NOT_CODE_ASK_PERMISSIONS;
    }
}

0

Yukarıdaki mVck yanıtında genişleyen aşağıdaki mantık, bir daha asla bir daha sorma 'nın belirli bir İzin İsteği için kontrol edilip edilmediğini belirler:

bool bStorage = grantResults[0] == Permission.Granted;
bool bNeverAskForStorage =
    !bStorage && (
        _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
        _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
    );

Aşağıdan alıntılanmış (tam örnek için bu cevaba bakınız )

private bool _bStorageRationaleBefore;
private bool _bStorageRationaleAfter;        
private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2;
//private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1;
private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0;

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode)
    {
        case ANDROID_PERMISSION_REQUEST_CODE__SDCARD:               
            _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
            bool bStorage = grantResults[0] == Permission.Granted;
            bool bNeverAskForStorage =
                !bStorage && (
                    _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
                    _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
                );      
            break;                
    }
}

private List<string> GetRequiredPermissions(out int requestCode)
{
    // Android v6 requires explicit permission granting from user at runtime for security reasons            
    requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0
    List<string> requiredPermissions = new List<string>();

    _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
    Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage);
    //if(extStoragePerm == Permission.Denied)
    if (writeExternalStoragePerm != Permission.Granted)
    {
        requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD;
        requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
    }

    return requiredPermissions;
}

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

        // Android v6 requires explicit permission granting from user at runtime for security reasons
        int requestCode;
        List<string> requiredPermissions = GetRequiredPermissions(out requestCode);
        if (requiredPermissions != null && requiredPermissions.Count > 0)
        {
            if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD)                    
            {
                _savedInstanceState = savedInstanceState;
                RequestPermissions(requiredPermissions.ToArray(), requestCode);
                return;
            }
        }
    }            

    OnCreate2(savedInstanceState);
}


0

Soruyu tam olarak cevaplamak için, kullanıcı "Bir Daha Asla Sorma" ya bastığında ne olur?

Geçersiz kılınan yöntem / işlev

onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)

GrantResult dizisi Boş olarak çıkıyor, böylece orada bir şeyler yapabilirsiniz? Ama en iyi uygulama değil.

"Bir daha asla sorma" nasıl ele alınır?

READ_EXTERNAL_STORAGE izni gerektiren Fragment ile çalışıyorum.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        when {
            isReadPermissionsGranted() -> {

                /**
                 * Permissions has been Granted
                 */

                getDirectories()
            }

            isPermissionDeniedBefore() -> {

                /**
                 * User has denied before, explain why we need the permission and ask again
                 */

                updateUIForDeniedPermissions()
                checkIfPermissionIsGrantedNow()

            }
            else -> {

                /**
                 * Need to ask For Permissions, First Time
                 */

                checkIfPermissionIsGrantedNow()

                /**
                 * If user selects, "Dont Ask Again" it will never ask again! so just update the UI for Denied Permissions
                 */

                updateUIForDeniedPermissions()

            }
        }
    }

Diğer işlevler önemsizdir.

// Is Read Write Permissions Granted
fun isReadWritePermissionGranted(context: Context): Boolean {
    return (ContextCompat.checkSelfPermission(
        context as Activity,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED) and
            (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED)
}

fun isReadPermissionDenied(context: Context) : Boolean {
    return ActivityCompat.shouldShowRequestPermissionRationale(
        context as Activity,
        PermissionsUtils.READ_EXTERNAL_STORAGE_PERMISSIONS)
}
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.