Autorisations Android M: confus sur l'utilisation de la fonction shouldShowRequestPermissionRationale ()

148

Je parcourais la documentation officielle sur le nouveau modèle d'autorisations dans Android M. Il parle de la shouldShowRequestPermissionRationale()fonction qui revient truesi l'application a demandé cette autorisation précédemment et que l'utilisateur a refusé la demande. Si l'utilisateur a refusé la demande d'autorisation dans le passé et a choisi l'option Ne plus demander, cette méthode retourne false.

Mais comment différencier les deux cas suivants?

Cas 1 : l'application n'a pas d'autorisation et l'autorisation n'a pas été demandée à l'utilisateur auparavant. Dans ce cas, shouldShowRequestPermissionRationale () retournera false car c'est la première fois que nous demandons à l'utilisateur.

Cas 2 : l'utilisateur a refusé l'autorisation et a sélectionné "Ne plus demander", dans ce cas également shouldShowRequestPermissionRationale () retournera false.

Je voudrais envoyer l'utilisateur à la page des paramètres de l'application dans le cas 2. Comment différencier ces deux cas?

akshayt23
la source
1
La réponse acceptée est bonne. Comme alternative, vous pouvez également utiliser une préférence partagée pour savoir si l'application a déjà demandé l'autorisation. Juste jeter ça là-bas au cas où cela serait plus applicable à la situation de quelqu'un d'autre.
Rockin4Life33
4
Il y a aussi un cas 3: l'utilisateur a été demandé et accordé / refusé l'autorisation, mais a utilisé les paramètres d'autorisation pour revenir à «demander à chaque fois». Le test montre que le shouldShowRequestPermissionRationale()retour est faux dans ce cas, ce qui nuira à tout code reposant sur un indicateur "ai-je demandé avant".
Ramassage Logan le
voici un exemple google montrant les meilleures pratiques permissionssur Android. github.com/android/permissions-samples
itabdullah
L'exemple de code de @itabdullah Google est inutile car ils n'ont même pas considéré le cas d'utilisation très probable de "l'utilisateur a-t-il refusé la permission la dernière fois". : - / typique
Someone Somewhere

Réponses:

172

Après M Preview 1, si la boîte de dialogue s'affiche pour la première fois , il n'y a pas de case à cocher Ne plus demander .

Si l'utilisateur refuse la demande d'autorisation, il y aura une case à cocher Ne plus jamais demander dans la boîte de dialogue d'autorisation la deuxième fois que l' autorisation est demandée.

La logique devrait donc être comme ceci:

  1. Demander la permission:

    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. Vérifiez si l'autorisation a été refusée ou accordée dans onRequestPermissionsResult.

    Si l'autorisation a été refusée précédemment, cette fois, il y aura une case à cocher Ne plus jamais demander dans la boîte de dialogue d'autorisation.

    Appelez shouldShowRequestPermissionRationalepour voir si l'utilisateur a coché Ne plus jamais demander . shouldShowRequestPermissionRationaleLa méthode renvoie false uniquement si l'utilisateur a sélectionné Ne plus jamais demander ou si la stratégie de l'appareil interdit à l'application d'avoir cette autorisation:

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

Ainsi, vous n'aurez pas à suivre si un utilisateur a coché Ne plus jamais demander ou non.

CanC
la source
49
Un point de clarification, shouldShowRequestPermissionRationale () retournera également false si l'utilisateur n'a jamais été demandé l'autorisation (c'est-à-dire la première fois que l'application est exécutée). Vous ne vous heurteriez pas à ce cas si vous suivez la logique de l'exemple fourni. Mais le libellé sous 2 est un peu trompeur.
Ben
15
Je ne suis pas sûr, cela semble défectueux. Comment sommes-nous censés savoir si c'est la première fois que l'utilisateur est invité? Je dois savoir si l'utilisateur a été demandé, et s'il l'a fait, alors je dois inverser la logique. Cela n'a aucun sens pour moi.
Daniel F
4
Je pense qu'il est intéressant de noter que lorsque vous passez contextdans ActivityCompat.shouldShowRequestPermissionRationale(...)le paramètre est en fait de type Activity. Peut ne pas vous affecter tous mais dans mon cas c'est le cas.
aProperFox
7
Cette logique androïde est tellement stupide! Cela me force à appeler le shoulddans le rappel ET à enregistrer sa contre-valeur dans NVM juste pour savoir si j'ai besoin de demander à nouveau la demande la prochaine fois que l'application s'ouvre! ... wow (facepalm) ... était-ce trop difficile de faire un seul appel retournant une énumération de statut ??
Shockwaver
2
Je pense que c'est un gros échec de Google. La documentation officielle indique que le shouldShowRequestPermissionRationale () doit être appelé avant de vérifier les autorisations (voir developer.android.com/training/permissions/requesting#explain ), mais toutes les réponses dans StackOverflow l'appellent dans onRequestPermissionResult () afin de distinguer si le l'utilisateur a cliqué sur "Ne plus jamais demander" ou non.
Miloš Černilovský
22

J'ai eu le même problème et je l'ai compris. Pour simplifier la vie, j'ai écrit une classe util pour gérer les autorisations d'exécution.

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

Et les méthodes PreferenceUtil sont les suivantes.

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

Maintenant, tout ce dont vous avez besoin est d'utiliser la méthode checkPermission avec les arguments appropriés.

Voici un exemple,

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

Cas 1: l'application n'a pas d'autorisation et l'autorisation n'a pas été demandée à l'utilisateur auparavant. Dans ce cas, shouldShowRequestPermissionRationale () retournera false car c'est la première fois que nous demandons à l'utilisateur.

Cas 2: l'utilisateur a refusé l'autorisation et a sélectionné "Ne plus demander", dans ce cas également shouldShowRequestPermissionRationale () retournera false.

Je voudrais envoyer l'utilisateur à la page des paramètres de l'application dans le cas 2. Comment faire pour différencier ces deux cas?

Vous obtiendrez un rappel sur onPermissionAsk pour le cas 1 et onPermissionDisabled pour le cas 2.

Bon codage :)

muthuraj
la source
Excellente explication bro. Suivez exactement la même procédure. :)
Sumit Jha
Que dois-je remplir pour cette activité? public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, ... .
Mardymar le
@Mardymar thisActivityn'est rien d'autre que YourActivity.this.
muthuraj
1
comment gérer plusieurs autorisations et comment intégrer ce code à l'intérieur d'un fragment.
Taimur
Quel genre d' contextutilisez-vous? shouldShowRequestPermissionRationale(permission)n'existe pas dans android.content.Context. il est dans ActivityCompat
Hilikus
9

METTRE À JOUR

Je crois que la réponse de CanC ci-dessous est la bonne à suivre. Le seul moyen d'en être sûr est de le vérifier dans le rappel onRequestPermissionResult à l'aide de shouldShowPermissionRationale.

==

Ma réponse originale:

Le seul moyen que j'ai trouvé est de savoir par vous-même si c'est la première fois ou non (par exemple en utilisant les préférences partagées). Si ce n'est pas la première fois, utilisez shouldShowRequestPermissionRationale()pour différencier.

Voir aussi: Android M - vérifier l'autorisation d'exécution - comment déterminer si l'utilisateur a coché "Ne plus jamais demander"?

Alex Florescu
la source
1
Oui, même je conviens que la méthode de CanC est celle qui devrait être suivie. Je vais le marquer comme la réponse acceptée.
akshayt23
6

D'après ce que je comprends, shouldShowRequestPermissionRationale () exécute un certain nombre de cas d'utilisation sous le capot et notifie à l'application si elle doit ou non afficher une explication sur les autorisations demandées.

L'idée derrière les autorisations d'exécution est que la plupart du temps, l'utilisateur dira Oui à la demande d'autorisation. De cette façon, l'utilisateur n'aura qu'à faire un seul clic. Bien sûr, la demande doit être utilisée dans le bon contexte - c'est-à-dire demander l'autorisation de la caméra lorsque le bouton "Caméra" est enfoncé.

Si l'utilisateur refuse la demande, mais après un certain temps, il appuie à nouveau sur le bouton "Appareil photo", shouldShowRequestPermissionRationale () retournera true, afin que l'application puisse montrer une explication significative pourquoi l'autorisation est demandée et pourquoi l'application ne le sera pas fonctionne correctement sans elle. Normalement, vous afficherez dans cette fenêtre de dialogue un bouton pour refuser à nouveau / décider plus tard, et un bouton pour accorder les autorisations. Le bouton Accorder les autorisations dans la boîte de dialogue de justification doit relancer la demande d'autorisation. Cette fois, l'utilisateur aura également une case à cocher "Ne plus afficher". S'il décidait de le sélectionner et de refuser à nouveau l'autorisation, il informerait le système Android que l'utilisateur et l'application ne sont pas sur la même page. Cette action aurait deux conséquences - shouldShowRequestPermissionRationale () retournera toujours false,

Mais il existe également un autre scénario possible dans lequel onRequestPermissionsResult pourrait être utilisé. Par exemple, certains périphériques peuvent avoir une politique de périphérique qui désactive la caméra (fonctionne pour CIA, DARPA, etc.). Sur ces appareils, onRequestPermissionsResult retournera toujours false, et la méthode requestPermissions () refusera silencieusement la demande.

C'est ce que j'ai compris en écoutant le podcast avec Ben Poiesz - un chef de produit sur le framework Android.
http://androidbackstage.blogspot.jp/2015/08/episode-33-permission-mission.html

Shumoapp
la source
6

Publiez simplement une autre option, si vous en avez envie. Vous pouvez utiliser EasyPermissions qui a été fourni par Google lui-même, pour, comme dit, "Simplifier les autorisations système Android M".

Ensuite, vous n'avez pas à gérer shouldShowRequestPermissionRationaledirectement.

Wei WANG
la source
pourquoi je n'ai pas vu ce projet auparavant :)
Vlad
Le problème avec EasyPermissions reste presque le même. Demander en permissionPermanentlyDeniedinterne n'appelle shouldShowPermissionsRationaleet renvoie que truedans le cas où l'utilisateur n'a jamais été invité à accorder des autorisations.
hgoebl
4

Si quelqu'un est intéressé par une solution Kotlin, j'ai refacturé la réponse @muthuraj pour être à Kotlin. Également modernisé un peu pour avoir un bloc de complétion au lieu d'écouteurs.

AutorisationUtil

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

la mise en oeuvre

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

Vérifiez cette implémentation. fonctionne plutôt bien pour moi. en gros, vous vérifiez les autorisations dans la méthode checkPermissions () en passant une liste d'autorisations. Vous vérifiez le résultat de la demande d'autorisation sur onRequestPermissionsResult (). L'implémentation vous permet de traiter les deux cas lorsque l'utilisateur sélectionne "ne plus jamais demander" ou non. Dans cette implémentation, au cas où se sélectionnerait "ne plus jamais demander", la boîte de dialogue a une option pour l'amener à l'activité Paramètres de l'application.

Tout ce code est à l'intérieur de mon fragment. Je pensais qu'il serait préférable de créer une classe spécialisée pour ce faire, comme un PermissionManager, mais je n'en suis pas sûr.

/**
     * 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
la source
2

Peut être utile pour quelqu'un: -

Ce que j'ai remarqué, c'est que si nous vérifions l'indicateur shouldShowRequestPermissionRationale () dans la méthode de rappel onRequestPermissionsResult (), il n'affiche que deux états.

État 1: -Retour vrai: - Chaque fois que l'utilisateur clique sur Refuser les autorisations (y compris la toute première fois).

État 2: -Retourne faux: - si l'utilisateur sélectionne «ne plus jamais demander».

Lien pour un exemple de travail détaillé .

Entailles
la source
6
il renvoie false pour la toute première fois. pas vrai
JoM
Oui, c'est ce que j'ai mentionné, si vous cochez l'indicateur dans la méthode de rappel onRequestPermissionsResult (), il n'aura que deux états, en particulier dans ce rappel.
Nicks
2
Malheureusement, shouldShowRequestPermissionRationale retourne toujours false - que l'utilisateur ait refusé ou non l'autorisation.
IgorGanapolsky
1

On peut le faire de cette façon?

@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
la source
Malheureusement, ce code ne fait pas la distinction entre une situation où l'autorisation n'a jamais été demandée auparavant et où «ne plus jamais demander» a été vérifié.
Ben
vous devez utiliser la combinaison de ceci + la classe d'assistance d'autorisation pour vérifier si l'autorisation est accordée ou non.
Dr aNdRO
0

shouldShowRequestPermissionRationale pour l'autorisation SPECIALE, retournez toujours TRUE UNIQUEMENT après que l'utilisateur l'a refusé sans case à cocher

Nous sommes intéressés par la valeur FAUX

Il y a donc 3 cas perdus avec une fausse valeur:

1. il n'y avait pas une telle action auparavant et maintenant l'utilisateur décide d'accepter ou de refuser.

Définissez simplement une préférence ASKED_PERMISSION_*qui n'existe pas maintenant et qui serait vraie dès onRequestPermissionsResultson début dans tous les cas d'accord ou de refus

Donc, même si cette préférence n'existe pas, il n'y a aucune raison de vérifiershouldShowRequestPermissionRationale

2. l' utilisateur a cliqué sur accepter.

Faites simplement:

checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

Ce qui retournera vrai et il n'y a aucune raison de vérifiershouldShowRequestPermissionRationale

3. l' utilisateur a cliqué sur refuser avec la case à cocher (deuxième fois ou plus demandé)

C'est LE TEMPS de travailler avec shouldShowRequestPermissionRationalequi retournera FAUX

(la préférence existe et nous n'avons pas d'autorisation)

Vlad
la source
0

Ce code demande à l'utilisateur de demander l'autorisation pendant l'exécution, si l'utilisateur l'autorise, il exécute la méthode de résultat, si l'utilisateur refuse, il demande à nouveau avec discription avec l'utilisateur refuse (il demande à nouveau avec des instructions), mais si l'utilisateur choisit de ne plus jamais demander. il gère ne plus jamais demander, affiche l'option des paramètres ouverts avec des instructions.

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
la source