Esempio di autorizzazioni di esecuzione Android

Benvenuto all’esempio di permessi di runtime di Android. Con l’introduzione di Android 6.0 Marshmallow, Google ha modificato il modo in cui le app gestiscono i permessi. In questo tutorial esamineremo i nuovi permessi di runtime di Android che sono stati introdotti e come gestirli. Se non vengono gestiti correttamente, possono causare crash dell’applicazione.

Cosa sono i permessi di runtime di Android?

Con l’introduzione di Android 6.0 (SDK 23), agli utenti viene richiesto di concedere alcuni permessi specifici al runtime quando diventano necessari per l’uso. Quindi la prima domanda che ci viene in mente è – Funzioneranno le vecchie app su Android Marshmallow? La risposta è se il targetSdkVersion è 22 o inferiore. Quindi i permessi di runtime di Android supportano la retrocompatibilità. Ora questo non significa che possiamo lavorare con il vecchio modello di permessi impostando la versione sdk su 22. Un utente che utilizza Marshmallow può revocare i permessi pericolosi (discuteremo i permessi pericolosi e normali più tardi) da Impostazioni->App->Permessi. Nel caso in cui tentiamo di chiamare una funzione che richiede un permesso che l’utente non ha ancora concesso, la funzione lancerà improvvisamente un’Eccezione(java.lang.SecurityException) che porterà al crash dell’applicazione. Pertanto, dobbiamo implementare questo nuovo modello di permessi di Android nella nostra applicazione.

Permessi pericolosi e normali degli android

Android definisce alcuni permessi come pericolosi e alcuni come normali. La cosa comune in entrambi i tipi è che devono essere definiti nel file Manifest. Da Android 6.0 solo i permessi pericolosi vengono controllati durante l’esecuzione, i permessi normali no. Un esempio di permesso normale è android.permission.INTERNET. I permessi pericolosi sono raggruppati in categorie che facilitano la comprensione da parte dell’utente su cosa sta permettendo all’applicazione di fare. Se l’utente accetta un permesso in un gruppo/categoria, accetta l’intero gruppo. Un esempio di permesso pericoloso è android.permission.FINE_LOCATION e android.permission.COARSE_LOCATION. Abilitando uno qualsiasi dei permessi relativi alla posizione, si abilitano tutti.

Richiesta di permessi di esecuzione Android

Il metodo `requestPermissions(String[] permissions, int requestCode);` è un metodo pubblico utilizzato per richiedere autorizzazioni pericolose. Possiamo richiedere più autorizzazioni pericolose passando un array di stringhe contenente le autorizzazioni desiderate. Nota: Le autorizzazioni Android appartenenti a due gruppi diversi richiederanno un prompt separato per ciascuno. Se appartengono allo stesso gruppo, verrà visualizzato solo un prompt. I risultati delle richieste saranno passati al metodo `onRequestPermissionResult`. Esempio: supponiamo di voler accedere alla fotocamera e alla posizione nella nostra app. Entrambe sono autorizzazioni pericolose. Visualizzeremo un prompt per richiedere l’accesso a queste autorizzazioni al lancio dell’applicazione. Aggiungiamo le autorizzazioni a un array di stringhe e chiamiamo `requestPermissions` come mostrato di seguito:

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;

    }

}

Ora non vogliamo che l’utente continui ad accettare autorizzazioni che ha già accettato. Anche se l’autorizzazione è stata concessa in precedenza, è necessario verificarla nuovamente per essere sicuri che l’utente non l’abbia successivamente revocata. Per questo è necessario chiamare il seguente metodo per ogni autorizzazione.

checkSelfPermission(String perm);

Restituisce un valore intero di PERMISSION_GRANTED o PERMISSION_DENIED. Nota: Se un utente rifiuta un’autorizzazione critica per l’app, allora `shouldShowRequestPermissionRationale(String permission);` viene utilizzato per spiegare all’utente la necessità dell’autorizzazione. Sviluppiamo un’applicazione che verifichi se l’autorizzazione è già presente. In caso contrario, la richiediamo durante l’esecuzione.

Struttura del Progetto delle Autorizzazioni Runtime di Android

Codice delle Autorizzazioni Runtime di Android

Il file content_main.xml contiene i due pulsanti per controllare e richiedere le autorizzazioni.

<?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>

Il file MainActivity.java è definito come segue.

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

}

Nota: Aggiungi le autorizzazioni che devono essere verificate durante l’esecuzione nel file Manifest sopra il tag dell’applicazione come;

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

Nel codice sopra, le due autorizzazioni controllate e richieste sono CAMERA e LOCATION. Importando il nome completo della classe di autorizzazione statica ci consente di scrivere solo l’oggetto PERMISSION invece del percorso completamente qualificato. checkPermission() chiama checkSelfPermission su ciascuna delle autorizzazioni. requestPermission() chiama ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);. onRequestPermissionsResult controlla se le autorizzazioni sono state concesse o meno. Nel nostro codice, se entrambe le autorizzazioni non sono state concesse, viene visualizzata una finestra di dialogo di avviso che mostra la necessità obbligatoria di richiedere le autorizzazioni. Per fare ciò, viene invocato shouldShowRequestPermissionRationale(String permission), che mostra una finestra di dialogo di avviso sulla necessità delle autorizzazioni. È possibile revocare manualmente le autorizzazioni da Impostazioni->App->Autorizzazioni. Nota: I metodi specifici delle autorizzazioni in esecuzione sono disponibili solo da API 23 in poi. Pertanto, la seguente condizione viene verificata in ciascuno dei metodi :

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

L’output dell’applicazione di esempio sulle autorizzazioni in esecuzione di Android è mostrato di seguito. Questo conclude questo tutorial. Puoi scaricare il progetto finale sulle autorizzazioni in esecuzione di Android dal link qui sotto.

Scarica Progetto Esempio Autorizzazioni in Esecuzione di Android

Riferimento: https://developer.android.com/training/permissions/requesting.html

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