Qualunque applicazione installata su un dispositivo, necessita di chiedere all'utente l'autorizzazione da usare servizi, sensori o funzionalità del sistema esterni all'applicazione stessa.
Esempi di permessi sono la necessità di accedere alla Rete, inviare messaggi o accedere alla fotocamera. In Android a definizione dei permessi necessari all'applicazione per poter funzionare avviene mediante i tag uses-permission
all'interno del file AndroidManifest.xml
.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...." >
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application>
...
</application>
...
</manifest>
Fino alla versione 6.0 di Android, i permessi necessari ad un'applicazione venivano richiesti durante la fase di installazione. A partire dalla versione 6.0 le cose sono cambiate: i permessi vengono richiesti poco prima di essere effettivamente utilizzati. L'utente può consentire o non consentire tali autorizzazioni. Le applicazioni devono essere in grado, dove possibile, di poter continuare ad operare anche senza di essi.
Dal punto di vista dell'utente questo cambio di gestione dei permessi fornisce maggior chiarezza in quanto consente di sapere quando e quali permessi sono effettivamente utilizzati dall'applicazione.
Dal punto di vista dello sviluppatore, questo cambio di gestione comporta qualche grattacapo in più: quando l'applicazione ha necessità di sfruttare un permesso deve verificare il fatto che l'utente non abbia già autorizzato il suo utilizzo, visualizzare eventualmente una dialog per informare perché si ha necessità di tale permesso e infine gestire l'esito della richiesta effettuata mediante dialog.
Consideriamo ora il caso di una App con un'activity che richiede l'uso della fotocamera. Il flusso logico riportato in figura 2 può essere tradotto nel seguente codice:
// Siamo in un'activity
/**
Metodo associato all'evento click di un pulsante che richiede l'uso della CAMERA
*/
public void showCamera() {
// permesso già concesso?
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
PackageManager.PERMISSION_GRANTED) {
// Bisogna visualizzare dialog per richiedere il permesso?
if (ActivityCompat.shouldShowRequestPermissionRationale(context,
Manifest.permission.CAMERA)) {
// TODO richiedere nuovamente permesso
} else {
// possiamo richiedere il permesso
ActivityCompat.requestPermissions(thisActivity, new String[] {
Manifest.permission.CAMERA }, MY_PERMISSIONS_REQUEST_CAMERA);
// la richiesta del permesso viene gestito
}
} else {
// utilizza permesso
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CAMERA: {
// Se la richiesta è stata cancellata, l'array result è vuoto
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// utilizza permesso
} else {
// gestisci permesso negato
}
return;
}
// altri casi
}
}
// codice di ritorno in caseo
public static int MY_PERMISSIONS_REQUEST_CAMERA=100;
Come si può vedere dal codice sopra riportato, la gestione dei permessi si articola in diversi step e introduce sicuramente maggiore complessità nel codice delle activity o dei fragment che devono richiedere permessi.
Permission Dispatcher
Anche per questo tipo di problema, c'è una soluzione decisamente più semplice: PermissionsDispatcher: una libreria Open Source scritta in Java e disponibile su Github il cui scopo è, nell'ambito dello sviluppo di applicazioni per Android, semplificare la gestione dei permessi a runtime mediante l'uso di annotazioni e di un processore di annotazioni.