Exemple de permissions d’exécution Android

Bienvenue dans l’exemple de permissions au moment de l’exécution d’Android. Avec l’introduction de Android 6.0 Marshmallow, Google a changé la façon dont les permissions sont gérées par l’application. Dans ce tutoriel, nous allons examiner les nouvelles permissions d’exécution d’Android qui ont été introduites et comment les gérer. Si elles ne sont pas correctement gérées, elles peuvent provoquer des plantages d’applications.

Qu’est-ce que les permissions d’exécution d’Android?

Avec l’introduction d’Android 6.0 (SDK 23), les utilisateurs sont invités à donner certaines permissions spécifiques au moment de l’exécution lorsqu’elles deviennent nécessaires à l’utilisation. La première question qui nous vient à l’esprit est donc – Les anciennes applications fonctionneront-elles sur Android Marshmallow? La réponse est oui si le targetSdkVersion est 22 ou moins. Ainsi, les permissions d’exécution d’Android sont compatibles avec les versions précédentes. Cela ne signifie pas pour autant que nous pouvons travailler avec l’ancien modèle de permissions en fixant la version du sdk à 22. Un utilisateur utilisant Marshmallow peut révoquer les permissions dangereuses (nous discuterons des permissions dangereuses et normales plus tard) à partir des Paramètres->Applications->Permissions. Dans le cas où nous essayons d’appeler une fonction qui nécessite une permission que l’utilisateur n’a pas encore accordée, la fonction va soudainement lancer une Exception(java.lang.SecurityException) qui entraînera le plantage de l’application. Il est donc nécessaire de mettre en œuvre ce nouveau modèle de permissions d’Android dans notre application.

Permissions dangereuses et normales pour Android

Android définit certaines autorisations comme dangereuses et d’autres comme normales. La caractéristique commune des deux types est qu’elles doivent être définies dans le fichier Manifeste. À partir d’Android 6.0, seules les autorisations dangereuses sont vérifiées à l’exécution, les autorisations normales ne le sont pas. Un exemple d’autorisation normale est android.permission.INTERNET. Les autorisations dangereuses sont regroupées par catégories pour faciliter la compréhension de l’utilisateur sur ce qu’il autorise l’application à faire. Si l’utilisateur accepte une autorisation dans un groupe/catégorie, il accepte l’ensemble du groupe. Un exemple d’autorisation dangereuse est android.permission.FINE_LOCATION et android.permission.COARSE_LOCATION. Activer l’une quelconque des autorisations de localisation active toutes les autorisations de localisation.

Demande d’autorisations d’exécution Android

La méthode requestPermissions(String[] permissions, int requestCode); est une méthode publique utilisée pour demander des autorisations dangereuses. Nous pouvons demander plusieurs autorisations dangereuses en passant un tableau de chaînes de caractères contenant les autorisations. Note : Les autorisations Android appartenant à deux groupes différents entraîneraient l’affichage d’une boîte de dialogue individuelle pour chacune d’entre elles. S’ils appartiennent au même groupe, alors seule une boîte de dialogue serait affichée. Les résultats des demandes seront transmis à la méthode onRequestPermissionResult. Exemple : Disons que nous voulons accéder à l’appareil photo et à la localisation dans notre application. Les deux sont des autorisations dangereuses. Nous afficherons une boîte de dialogue demandant l’accès à ces autorisations lors du lancement de l’application. Ajoutons les autorisations dans un tableau de chaînes de caractères et appelons la méthode requestPermissions comme indiqué ci-dessous :

String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};

int permsRequestCode = 200; 
requestPermissions(perms, permsRequestCode);

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

    switch(permsRequestCode){

        case 200:

            boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
            boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;

            break;

    }

}

Maintenant, nous ne voulons pas que l’utilisateur continue d’accepter des autorisations qu’il a déjà acceptées. Même si l’autorisation a été précédemment accordée, il est nécessaire de vérifier à nouveau pour être sûr que l’utilisateur n’a pas révoqué cette autorisation ultérieurement. Pour cela, la méthode suivante doit être appelée pour chaque autorisation.

checkSelfPermission(String perm);

Elle renvoie une valeur entière de PERMISSION_GRANTED ou PERMISSION_DENIED. Note : Si un utilisateur refuse une autorisation qui est essentielle dans l’application, alors shouldShowRequestPermissionRationale(String permission); est utilisé pour expliquer à l’utilisateur la nécessité de l’autorisation. Développons une application qui vérifie si l’autorisation est déjà présente. Si ce n’est pas le cas, alors elle est demandée au moment de l’exécution.

Projet Structure des Autorisations d’Exécution Android

Code des Autorisations d’Exécution Android

Le fichier content_main.xml contient les deux boutons pour vérifier et demander les autorisations.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.journaldev.runtimepermissions.MainActivity"
    tools:showIn="@layout/activity_main">
    <Button
        android:id="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Check Permission"/>
    <Button
        android:id="@+id/request_permission"
        android:layout_below="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request Permission"/>
</RelativeLayout>

Le fichier MainActivity.java est défini comme suit.

package com.journaldev.runtimepermissions;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int PERMISSION_REQUEST_CODE = 200;
    private View view;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Button check_permission = (Button) findViewById(R.id.check_permission);
        Button request_permission = (Button) findViewById(R.id.request_permission);
        check_permission.setOnClickListener(this);
        request_permission.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {

        view = v;

        int id = v.getId();
        switch (id) {
            case R.id.check_permission:
                if (checkPermission()) {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                } else {

                    Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
                }
                break;
            case R.id.request_permission:
                if (!checkPermission()) {

                    requestPermission();

                } else {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                }
                break;
        }

    }

    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);

        return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermission() {

        ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0) {

                    boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;

                    if (locationAccepted && cameraAccepted)
                        Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
                    else {

                        Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                                showMessageOKCancel("You need to allow access to both the permissions",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                    requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
                                                            PERMISSION_REQUEST_CODE);
                                                }
                                            }
                                        });
                                return;
                            }
                        }

                    }
                }


                break;
        }
    }


    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

}

Note : Ajoutez les autorisations qui doivent être vérifiées à l’exécution dans le fichier Manifeste au-dessus de la balise d’application comme suit ;

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Dans le code ci-dessus, les deux autorisations vérifiées et demandées sont CAMERA et LOCATION. L’importation du nom de classe d’autorisation statique complet nous permet d’écrire simplement l’objet PERMISSION au lieu du chemin complètement qualifié. checkPermission() appelle checkSelfPermission sur chacune des autorisations. requestPermission() appelle ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);. onRequestPermissionsResult vérifie si les autorisations sont accordées ou non. Dans notre code, si les deux autorisations ne sont pas accordées, une boîte de dialogue d’alerte s’affiche, montrant le besoin obligatoire de demander les autorisations. Pour ce faire, shouldShowRequestPermissionRationale(String permission) est invoqué, ce qui déclenche une boîte de dialogue d’alerte montrant le besoin des autorisations. Vous pouvez révoquer les autorisations manuellement depuis Paramètres->Applications->Autorisations. Note: Les méthodes spécifiques aux autorisations d’exécution sont disponibles uniquement depuis l’API 23. Par conséquent, la condition suivante est vérifiée à chacune des méthodes :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)

L’exemple d’application d’autorisations d’exécution Android en action est donné ci-dessous. Cela marque la fin de ce tutoriel. Vous pouvez télécharger le projet final sur les autorisations d’exécution Android via le lien ci-dessous.

Télécharger le projet d’exemple d’autorisations d’exécution Android

Référence: https://developer.android.com/training/permissions/requesting.html

Source:
https://www.digitalocean.com/community/tutorials/android-runtime-permissions-example