Android M-Berechtigungen: Verwirrt über die Verwendung der Funktion shouldShowRequestPermissionRationale ()

148

Ich habe das offizielle Dokument über das neue Berechtigungsmodell in Android M durchgesehen. Es handelt von der shouldShowRequestPermissionRationale()Funktion, die zurückgegeben wird, truewenn die App diese Berechtigung zuvor angefordert hat und der Benutzer die Anforderung abgelehnt hat. Wenn der Benutzer die Berechtigungsanforderung in der Vergangenheit abgelehnt und die Option Nicht erneut fragen ausgewählt hat, wird diese Methode zurückgegeben false.

Aber wie können wir zwischen den folgenden beiden Fällen unterscheiden?

Fall 1 : Die App hat keine Berechtigung und der Benutzer wurde zuvor nicht nach der Berechtigung gefragt. In diesem Fall gibt shouldShowRequestPermissionRationale () false zurück, da dies das erste Mal ist, dass wir den Benutzer fragen.

Fall 2 : Der Benutzer hat die Berechtigung verweigert und "Nicht erneut fragen" ausgewählt. Auch in diesem Fall sollte shouldShowRequestPermissionRationale () false zurückgeben.

Ich möchte den Benutzer in Fall 2 zur Einstellungsseite der App senden. Wie unterscheide ich diese beiden Fälle?

akshayt23
quelle
1
Die akzeptierte Antwort ist gut. Alternativ können Sie auch eine gemeinsame Voreinstellung verwenden, um festzustellen, ob die App zuvor die Berechtigung angefordert hat. Wirf das einfach raus, falls es für die Situation eines anderen besser geeignet ist.
Rockin4Life33
4
Es gibt auch Fall 3: Der Benutzer wurde um die Berechtigung gebeten und diese erteilt / verweigert, hat jedoch die Berechtigungseinstellungen verwendet, um auf "jedes Mal fragen" zurückzukehren. Das Testen zeigt shouldShowRequestPermissionRationale()in diesem Fall, dass die Rückgabe falsch ist, was jeden Code verletzt, der auf dem Flag "Habe ich vorher gefragt" basiert.
Logan Pickup
Hier ist ein Google-Beispiel, das die Best Practices permissionsfür Android zeigt. github.com/android/permissions-samples
itabdullah

Antworten:

172

Wenn nach M Vorschau 1 der Dialog zum ersten Mal angezeigt wird , gibt es kein Kontrollkästchen Nie wieder fragen .

Wenn der Benutzer die Berechtigungsanforderung ablehnt, wird im Berechtigungsdialog beim zweiten Anfordern der Berechtigung das Kontrollkästchen Nie wieder fragen angezeigt .

Die Logik sollte also so aussehen:

  1. Um Erlaubnis bitten:

    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. Überprüfen Sie, ob die Berechtigung in verweigert oder erteilt wurde onRequestPermissionsResult.

    Wenn die Berechtigung zuvor verweigert wurde, wird dieses Mal im Berechtigungsdialog das Kontrollkästchen Nie wieder fragen angezeigt.

    Rufen Sie shouldShowRequestPermissionRationalean, um zu sehen, ob der Benutzer die Option Nie wieder fragen aktiviert hat . shouldShowRequestPermissionRationaleDie Methode gibt nur dann false zurück, wenn der ausgewählte Benutzer Nie wieder fragen oder die Geräterichtlinie der App diese Berechtigung untersagt:

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

Sie müssen also nicht nachverfolgen, ob ein Benutzer die Option Nie wieder fragen oder nicht aktiviert hat .

CanC
quelle
48
Ein Punkt der Klarstellung: sollte ShowRequestPermissionRationale () auch false zurückgeben, wenn der Benutzer noch nie nach der Berechtigung gefragt wurde (dh wenn die Anwendung zum ersten Mal ausgeführt wird). Sie würden in diesen Fall nicht geraten, wenn Sie der Logik des angegebenen Beispiels folgen. Aber der Wortlaut unter 2 ist etwas irreführend.
Ben
1
@Canc sehr schöne Erklärung. Danke :)
AndoAiron
14
Ich bin nicht sicher, das scheint fehlerhaft. Woher sollen wir wissen, ob der Benutzer zum ersten Mal gefragt wird? Ich muss nachverfolgen, ob der Benutzer gefragt wurde, und wenn er es getan hat, muss ich die Logik umkehren. Macht für mich keinen Sinn.
Daniel F
4
Ich denke , es ist erwähnenswert , dass , wenn Sie übergeben contextin ActivityCompat.shouldShowRequestPermissionRationale(...)dem Parameter tatsächlich vom Typ ist Activity. Kann Sie nicht alle betreffen, aber in meinem Fall tut es.
aProperFox
7
Diese Android-Logik ist so verdammt dumm! Es zwingt mich, shouldden Rückruf aufzurufen UND seinen Zählerwert in NVM zu speichern, um zu wissen, ob ich die Anfrage beim nächsten Öffnen der App erneut auffordern muss! ... wow (facepalm) ... war es zu schwierig, nur einen Anruf zu tätigen, der eine Statusaufzählung zurückgibt?
Shockwaver
22

Ich hatte das gleiche Problem und habe es herausgefunden. Um das Leben viel einfacher zu machen, habe ich eine util-Klasse geschrieben, um Laufzeitberechtigungen zu verarbeiten.

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

Die PreferenceUtil- Methoden lauten wie folgt.

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

Jetzt müssen Sie nur noch die Methode checkPermission mit den richtigen Argumenten verwenden.

Hier ist ein Beispiel,

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

Fall 1: Die App hat keine Berechtigung und der Benutzer wurde zuvor nicht nach der Berechtigung gefragt. In diesem Fall gibt shouldShowRequestPermissionRationale () false zurück, da dies das erste Mal ist, dass wir den Benutzer fragen.

Fall 2: Der Benutzer hat die Berechtigung verweigert und "Nicht erneut fragen" ausgewählt. Auch in diesem Fall sollte shouldShowRequestPermissionRationale () false zurückgeben.

Ich möchte den Benutzer in Fall 2 zur Einstellungsseite der App senden. Wie unterscheide ich diese beiden Fälle?

Sie erhalten einen Rückruf für onPermissionAsk für Fall 1 und onPermissionDisabled für Fall 2.

Viel Spaß beim Codieren :)

Muthuraj
quelle
Hervorragende Erklärung, Bruder. Befolgen Sie genau das gleiche Verfahren. :)
Sumit Jha
Was fülle ich für diese Aktivität aus? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Mardymar
@Mardymar thisActivityist nichts anderes als YourActivity.this.
Muthuraj
1
wie man mit mehreren Berechtigungen umgeht und wie man diesen Code in ein Fragment integriert.
Taimur
Welche Art von verwenden contextSie? shouldShowRequestPermissionRationale(permission)existiert nicht in android.content.Context. es ist in ActivityCompat
Hilikus
8

AKTUALISIEREN

Ich glaube, dass die Antwort von CanC unten die richtige ist, die befolgt werden sollte. Die einzige Möglichkeit, dies sicher zu wissen, besteht darin, dies im Rückruf onRequestPermissionResult mithilfe von shouldShowPermissionRationale zu überprüfen.

==

Meine ursprüngliche Antwort:

Die einzige Möglichkeit, die ich gefunden habe, besteht darin, selbst zu verfolgen, ob dies das erste Mal ist oder nicht (z. B. mithilfe gemeinsamer Einstellungen). Wenn es nicht das erste Mal ist, verwenden Sie shouldShowRequestPermissionRationale()zur Unterscheidung.

Siehe auch: Android M - Laufzeitberechtigung prüfen - Wie kann festgestellt werden, ob der Benutzer "Nie wieder fragen" aktiviert hat?

Alex Florescu
quelle
1
Ja, auch ich stimme zu, dass die Methode von CanC diejenige ist, die befolgt werden sollte. Ich werde es als akzeptierte Antwort markieren.
Akshayt23
6

So wie ich es verstehe, sollte shouldShowRequestPermissionRationale () eine Reihe von Anwendungsfällen unter der Haube ausführen und die App benachrichtigen, ob eine Erklärung zu den angeforderten Berechtigungen angezeigt werden soll oder nicht.

Die Idee hinter den Laufzeitberechtigungen ist, dass der Benutzer die Berechtigungsanforderung meistens mit Ja beantwortet. Auf diese Weise muss der Benutzer nur einen Klick ausführen. Natürlich sollte die Anfrage im richtigen Kontext verwendet werden - dh nach der Erlaubnis der Kamera fragen, wenn die Schaltfläche "Kamera" gedrückt wird.

Wenn der Benutzer die Anforderung ablehnt, aber nach einiger Zeit erneut auf die Schaltfläche "Kamera" drückt, gibt shouldShowRequestPermissionRationale () true zurück, sodass die App eine aussagekräftige Erklärung dafür anzeigen kann, warum die Berechtigung angefordert wird und warum die App dies nicht tut ohne es richtig arbeiten. Normalerweise zeigen Sie in diesem Dialogfenster eine Schaltfläche zum erneuten Verweigern / späteren Entscheiden und eine Schaltfläche zum Erteilen der Berechtigungen. Die Schaltfläche zum Erteilen von Berechtigungen im Begründungsdialog sollte die Berechtigungsanforderung erneut starten. Diesmal hat der Benutzer auch das Kontrollkästchen "Nie wieder anzeigen". Sollte er sich entscheiden, es auszuwählen und die Berechtigung erneut zu verweigern, würde dies das Android-System benachrichtigen, dass sich der Benutzer und die App nicht auf derselben Seite befinden. Diese Aktion hätte zwei Konsequenzen: Sollte ShowRequestPermissionRationale () immer false zurückgeben,

Es gibt aber auch ein anderes mögliches Szenario, in dem onRequestPermissionsResult verwendet werden könnte. Beispielsweise verfügen einige Geräte möglicherweise über eine Geräterichtlinie, die die Kamera deaktiviert (für CIA, DARPA usw.). Auf diesen Geräten gibt onRequestPermissionsResult immer false zurück, und die requestPermissions () -Methode lehnt die Anforderung stillschweigend ab.

Das habe ich beim Anhören des Podcasts mit Ben Poiesz - einem Produktmanager im Android-Framework - gesammelt.
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html

Shumoapp
quelle
6

Posten Sie einfach eine andere Option, wenn jemand Lust dazu hat. Sie können EasyPermissions, die von Google selbst bereitgestellt wurden, verwenden, um "die Berechtigungen für Android M-Systeme zu vereinfachen".

Dann müssen Sie nicht shouldShowRequestPermissionRationaledirekt damit umgehen .

Wei WANG
quelle
warum ich dieses Projekt vorher nicht gesehen habe :)
Vlad
Das Problem mit EasyPermissions bleibt nahezu gleich. permissionPermanentlyDeniedInternes Fragen ruft nur an shouldShowPermissionsRationaleund kehrt truezurück, wenn der Benutzer nie aufgefordert wurde, Berechtigungen zu erteilen.
Hgoebl
4

Wenn jemand an einer Kotlin-Lösung interessiert ist, habe ich die @ muthuraj-Antwort überarbeitet, um in Kotlin zu sein. Außerdem wurde es ein wenig modernisiert, einen Vervollständigungsblock anstelle von Zuhörern zu haben.

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

Implementierung

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

Überprüfen Sie diese Implementierung. arbeitet ziemlich gut für mich. Grundsätzlich überprüfen Sie die Berechtigungen in der Methode checkPermissions (), indem Sie eine Liste von Berechtigungen übergeben. Sie überprüfen das Ergebnis der Berechtigungsanforderung auf onRequestPermissionsResult (). Mit der Implementierung können Sie beide Fälle behandeln, wenn der Benutzer "Nie wieder fragen" auswählt oder nicht. In dieser Implementierung hat der Dialog die Option, ihn zur Aktivität "App-Einstellungen" zu führen, falls se "Nie wieder fragen" auswählt.

Der ganze Code befindet sich in meinem Fragment. Ich dachte, es wäre besser, eine spezielle Klasse dafür zu erstellen, wie einen PermissionManager, aber ich bin mir nicht sicher.

/**
     * 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);
    }
Thiago Saraiva
quelle
2

Kann für jemanden nützlich sein: -

Was mir aufgefallen ist, ist, dass beim Aktivieren des Flags shouldShowRequestPermissionRationale () in der Rückrufmethode onRequestPermissionsResult () nur zwei Zustände angezeigt werden.

Status 1: -Return true: - Jedes Mal, wenn der Benutzer auf Verweigern von Berechtigungen klickt (einschließlich des ersten Males).

Status 2: - Gibt false zurück: - Wenn der Benutzer "Nie wieder fragen" auswählt.

Link für detailliertes Arbeitsbeispiel .

Nicks
quelle
6
es gibt zum ersten Mal false zurück . nicht wahr
JoM
Ja, das habe ich erwähnt. Wenn Sie das Flag in der Rückrufmethode onRequestPermissionsResult () aktivieren, hat es nur zwei Zustände, insbesondere in diesem Rückruf.
Nicks
2
Leider sollte shouldShowRequestPermissionRationale immer false zurückgeben - unabhängig davon, ob der Benutzer die Berechtigung jemals verweigert hat oder nicht.
IgorGanapolsky
1

Können wir das so machen?

@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;
        }
    }
}
Dr. aNdRO
quelle
Leider unterscheidet dieser Code nicht zwischen einer Situation, in der die Berechtigung noch nie angefordert wurde und in der die Option "Nie wieder anfordern" aktiviert wurde.
Ben
Sie sollten die Kombination dieser + der Berechtigungshilfeklasse verwenden, um zu überprüfen, ob die Berechtigung erteilt wurde oder nicht.
Dr. aNdRO
0

shouldShowRequestPermissionRationale Für die SPECIAL-Berechtigung wird immer NUR TRUE zurückgegeben, nachdem der Benutzer dies ohne Kontrollkästchen verweigert hat

Wir sind an FALSE Wert interessiert

Es gehen also 3 Fälle mit falschem Wert verloren:

1. Bisher gab es keine solche Aktion, und jetzt entscheidet sich der Benutzer, zuzustimmen oder abzulehnen.

Einfach eine Präferenz definieren , ASKED_PERMISSION_*die jetzt nicht mehr existiert und wäre wahr in onRequestPermissionsResultauf es auf jeden Fall starten ist von zustimmen oder ablehnen

Obwohl diese Einstellung nicht vorhanden ist, gibt es keinen Grund, dies zu überprüfenshouldShowRequestPermissionRationale

2. Benutzer klickte auf zustimmen.

Einfach machen:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

Was true zurückgibt und es keinen Grund gibt, dies zu überprüfenshouldShowRequestPermissionRationale

3. Der Benutzer hat mit dem Kontrollkästchen Verweigern geklickt (zweite oder längere Zeit gefragt).

Es ist DIE ZEIT zu arbeiten, mit shouldShowRequestPermissionRationaleder FALSE zurückgegeben wird

(Präferenz besteht und wir haben keine Erlaubnis)

Vlad
quelle
0

Dieser Code fordert den Benutzer auf, zur Laufzeit um Erlaubnis zu bitten. Wenn der Benutzer dies zulässt, führt er die Ergebnismethode aus. Wenn der Benutzer dies verweigert, fragt er erneut mit der Beschreibung mit dem Benutzer verweigern (er fragt erneut mit Anweisungen), aber wenn der Benutzer wählt, fragen Sie nie wieder. es behandelt nie wieder fragen, zeigt offene Einstellungsoption mit Anweisungen an.

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;
                }
        }
}
Abhishek Garg
quelle