Le permission

25 maggio 2016

Un’applicazione Android vive in all’interno di una sandbox, ovvero un ambiente chiuso in cui l’applicazione opera in maniera sostanzialmente isolata dal resto del sistema. Talvolta, però, può essere necessario che essa debba “uscire” da questa gabbia per accedere a informazioni, funzionalità o apparati hardware del dispositivo. Per far sì che l’app acceda a tali servizi, essa deve possedere alcuni “permessi” speciali – le cosiddette permission – che è necessario dichiarare espressamente nel file AndroidManifest.xml. Ogni permission viene dichiarata tramite il tag <uses-permission>, da collocare al di fuori del nodo <application>:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="...." >
    <uses-permission android:name="android.permission.INTERNET" />
    <application>
      ...
      ...
    </application>
    ...
</manifest>

Fatto ciò, il sistema operativo saprà quali attività particolari l’app dovrà svolgere, e potrà concederle il permesso di effettuarle. Prima dell’installazione dell’app, infatti, l’utente viene sempre avvisato delle permission richieste dall’app: se accetta di installarla, accetta che il suo sistema operativo conceda tali permessi “speciali” all’app.

Tipi di permission

Le permission Android vengono suddivise in due grosse famiglie:

  • permission normal, che non mettono cioè a rischio la privacy dell’utente, tra le quali troviamo:
    • accesso alla Rete (android.permission.INTERNET, verifica dello stato della rete (android.permission.ACCESS_NETWORK_STATE) e accesso alle informazioni sulle reti Wi-Fi (android.permission.ACCESS_WIFI_STATE);
    • accesso a particolari tecnologie per la connettività: android.permission.BLUETOOTH, android.permission.BLUETOOTH_ADMIN o android.permission.NFC;
    • invio di un Intent per l’impostazione di un allarme: com.android.alarm.permission.SET_ALARM;
    • gestione della vibrazione (android.permission.VIBRATE) o del WaveLock per il controllo dello stand-by (android.permission.WAVE_LOCK);
    • molte altre: una lista completa è disponibile sulla documentazione ufficiale.
  • permission dangerous, potenzialmente più lesive della riservatezza degli utenti, come quelle riguardanti:
    • la localizzazione: android.permission.ACCESS_FINE_LOCATION e android.permission.ACCESS_COARSE_LOCATION;
    • il calendario: android.permission.READ_CALENDAR e android.permission.WRITE_CALENDAR;
    • i contatti: android.permission.READ_CONTACTS e android.permission.WRITE_CONTACTS;
    • attività telefoniche: ad esempio, android.permission.READ_PHONE_STATE e android.permission.SEND_SMS;
    • accesso ai file: android.permission.READ_EXTERNAL_STORAGE e android.permission.WRITE_EXTERNAL_STORAGE.

Android 6: nuova gestione delle permission

La gestione delle permission è cambiata radicalmente in Android 6 (ovvero dalla versione 23 delle API). A partire da questa versione, infattti, le permission dangerous dovranno essere accettate dall’utente al momento del primo utilizzo e tale permesso potrà essere revocato in qualsiasi momento, accedendo alle impostazioni dell’app. Questo determina un regime di gestione delle attività critiche più flessibile e più protettivo nei confronti dell’utente, ma che richiede agli sviluppatori una gestione più accurata delle eccezioni.

Ciò che cambia sul piano della progettazione è che l’app, in prospettiva, potrebbe avere più comportamenti: uno in cui tutte le permission dangerous sono state concesse dall’utente, altri in cui una o più di esse sono state negate o revocate. L’app, dal canto suo, dovrebbe essere in grado di lavorare correttamente in tutti i casi, semmai disattivando le funzionalità che necessitano delle permission negate. Per sviluppare app moderne, quindi, è necessario gestire le permission a runtime, verificando se esse siano revocate o meno, nonchè richiedendo all’utente di abilitarle.

La classe ContextCompat, inclusa nella libreria di supporto, mette a disposizione un metodo per effettuare questo tipo di controllo:

int statoPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);

dove this rappresenta la nostra Activity (che fungerà da Context). Il valore della variabile intera statoPermission sarà confrontato con le costanti PackageManager.PERMISSION_GRANTED oppure PackageManager.PERMISSION_DENIED che equivalgono, rispettivamente, alla concessione del permesso o al suo diniego.

Per fare in modo che le nostre app funzionino su versioni Android con API 23 o superiori dovremo verificare la disponibilità di una permission prima di utilizzare il metodo che ne ha bisogno, e qualora essa non fosse disponibile dovremo chiedere all’utente di acconsentire lanciando un apposito Intent. Per far comparire una finestra di dialogo che richieda l’accettazione della permission, si può usare il seguente codice Java:

ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ID_RICHIESTA_PERMISSION);

Abbbiamo così passato un array di stringhe contenente le permission che dovranno essere accettate, ed una costante intera che noi abbiamo chiamato ID_RICHIESTA_PERMISSION, che permetterà di identificare la specifica richiesta che abbiamo inoltrato. Apparirà così una finestra di dialogo di questo tipo:

Figura 1. Richiesta di permission (click per ingrandire)

Richiesta di permission

Il risultato sarà inviato inviato ad un metodo che noi predisporremo:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case ID_RICHIESTA_PERMISSION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
			
				// permission concessa: eseguiamo il codice

            } else {

                // permission negata: provvediamo in qualche maniera
            }
            return;
        }
    }
}

Il metodo riceverà tre elementi: il codice della richiesta (utile per riconoscere a cosa sta rispondendo), l’array delle permission e l’array dei risultati (che conterrà in ogni posizione se la permission è stata accettata o meno). In base al controllo di quest’ultimo capiremo il da farsi: possiamo eseguire il codice o dobbiamo ovviare facendo qualcos’altro.

Riepilogando, quella che segue è la struttura di controllo da usare per far sì che l’utente acconsenta a svolgere attività soggette ad una permission dangerous. Si noti che viene controllato anche il metodo shouldShowRequestPermissionRationale, che verifica se sia il caso di fornire all’utente ulteriori informazioni rispetto alla permission richiesta e all’uso che l’app deve farne:

// controlliamo se la permission è concessa 
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

	// se arriviamo qui è perchè la permission non è stata ancora concessa
	if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
		// mostriamo ulteriori informazioni all'utente riguardante l'uso della permission nell'app ed eventualmente richiediamo la permission
    } else {
	
		// se siamo qui è perchè non si è mostrata alcuna spiegazione all'utente, richiesta di permission
		ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, ID_RICHIESTA_PERMISSION);
    }
}

L’utente sarà sempre padrone di revocare le permission dangerous concesse, semplicemente agendo sul controllo che apparirà tra le impostazioni dell’app:

Figura 2. Revoca di una permission (click per ingrandire)

Revoca di una permission
Tutte le lezioni

1 ... 11 12 13 ... 80

Se vuoi aggiornamenti su Le permission inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Le permission

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy