Autorizzazioni in Xamarin.Android

Panoramica

Le applicazioni Android vengono eseguite nella propria sandbox e per motivi di sicurezza non hanno accesso a determinate risorse di sistema o hardware nel dispositivo. L'utente deve concedere in modo esplicito l'autorizzazione all'app prima di poter usare queste risorse. Ad esempio, un'applicazione non può accedere al GPS in un dispositivo senza autorizzazioni esplicite dell'utente. Android genererà un'eccezione Java.Lang.SecurityException se un'app tenta di accedere a una risorsa protetta senza autorizzazione.

Le autorizzazioni vengono dichiarate nel AndroidManifest.xml dallo sviluppatore dell'applicazione quando viene sviluppata l'app. Android ha due flussi di lavoro diversi per ottenere il consenso dell'utente per tali autorizzazioni:

  • Per le app destinate ad Android 5.1 (livello API 22) o inferiori, la richiesta di autorizzazione si è verificata quando l'app è stata installata. Se l'utente non ha concesso le autorizzazioni, l'app non verrà installata. Una volta installata l'app, non è possibile revocare le autorizzazioni, ad eccezione della disinstallazione dell'app.
  • A partire da Android 6.0 (livello API 23), agli utenti è stato assegnato un maggiore controllo sulle autorizzazioni; possono concedere o revocare le autorizzazioni purché l'app sia installata nel dispositivo. Questo screenshot mostra le impostazioni di autorizzazione per l'app Contatti Google. Elenca le varie autorizzazioni e consente all'utente di abilitare o disabilitare le autorizzazioni:

Sample Permissions screen

Le app Android devono verificare in fase di esecuzione per verificare se dispongono dell'autorizzazione per accedere a una risorsa protetta. Se l'app non dispone dell'autorizzazione, deve effettuare richieste usando le nuove API fornite da Android SDK per consentire all'utente di concedere le autorizzazioni. Le autorizzazioni sono suddivise in due categorie:

  • Autorizzazioni normali: si tratta di autorizzazioni che comportano un rischio di sicurezza minimo per la sicurezza o la privacy dell'utente. Android 6.0 concederà automaticamente le autorizzazioni normali al momento dell'installazione. Per un elenco completo delle autorizzazioni normali, consultare la documentazione di Android.
  • Autorizzazioni pericolose: a differenza delle normali autorizzazioni, le autorizzazioni pericolose sono quelle che proteggono la sicurezza o la privacy dell'utente. Questi devono essere concessi in modo esplicito dall'utente. L'invio o la ricezione di un messaggio SMS è un esempio di azione che richiede un'autorizzazione pericolosa.

Importante

La categoria a cui appartiene un'autorizzazione può cambiare nel tempo. È possibile che un'autorizzazione categorizzata come autorizzazione "normale" possa essere elevata nei livelli api futuri a un'autorizzazione pericolosa.

Le autorizzazioni pericolose sono ulteriormente suddivise in gruppi di autorizzazioni. Un gruppo di autorizzazioni conterrà le autorizzazioni correlate logicamente. Quando l'utente concede l'autorizzazione a un membro di un gruppo di autorizzazioni, Android concede automaticamente l'autorizzazione a tutti i membri del gruppo. Ad esempio, il STORAGE gruppo di autorizzazioni contiene sia le autorizzazioni che READ_EXTERNAL_STORAGE .WRITE_EXTERNAL_STORAGE Se l'utente concede l'autorizzazione a READ_EXTERNAL_STORAGE, l'autorizzazione WRITE_EXTERNAL_STORAGE viene concessa automaticamente contemporaneamente.

Prima di richiedere una o più autorizzazioni, è consigliabile fornire una logica per il motivo per cui l'app richiede l'autorizzazione prima di richiedere l'autorizzazione. Una volta compreso il motivo, l'app può richiedere l'autorizzazione all'utente. Comprendendo la logica, l'utente può prendere una decisione informata se desidera concedere l'autorizzazione e comprendere le ripercussioni in caso contrario.

L'intero flusso di lavoro di controllo e richiesta delle autorizzazioni è noto come controllo delle autorizzazioni di runtime e può essere riepilogato nel diagramma seguente:

Run-time permission check flow chart

La libreria di supporto Android esegue il backport di alcune delle nuove API per le autorizzazioni per le versioni precedenti di Android. Queste API con backporting verificheranno automaticamente la versione di Android nel dispositivo, quindi non è necessario eseguire un controllo a livello di API ogni volta.

Questo documento illustra come aggiungere autorizzazioni a un'applicazione Xamarin.Android e come le app destinate ad Android 6.0 (livello API 23) o versioni successive devono eseguire un controllo delle autorizzazioni di runtime.

Nota

È possibile che le autorizzazioni per l'hardware influiscano sul modo in cui l'app viene filtrata da Google Play. Ad esempio, se l'app richiede l'autorizzazione per la fotocamera, Google Play non mostrerà l'app in Google Play Store in un dispositivo in cui non è installata una fotocamera.

Requisiti

È consigliabile che i progetti Xamarin.Android includano il pacchetto NuGet Xamarin.Android.Support.Compat . Questo pacchetto eseguirà il backport delle API specifiche per le versioni precedenti di Android, fornendo un'interfaccia comune senza la necessità di controllare costantemente la versione di Android in cui è in esecuzione l'app.

Richiesta di autorizzazioni di sistema

Il primo passaggio nell'uso delle autorizzazioni Android consiste nel dichiarare le autorizzazioni nel file manifesto Android. Questa operazione deve essere eseguita indipendentemente dal livello API di destinazione dell'app.

Le app destinate ad Android 6.0 o versione successiva non possono presupporre che, poiché l'utente ha concesso l'autorizzazione in passato, l'autorizzazione sarà valida la volta successiva. Un'app destinata ad Android 6.0 deve sempre eseguire un controllo delle autorizzazioni di runtime. Le app destinate ad Android 5.1 o versioni precedenti non devono eseguire un controllo delle autorizzazioni di runtime.

Nota

Le applicazioni devono richiedere solo le autorizzazioni necessarie.

Dichiarazione di autorizzazioni nel manifesto

Le autorizzazioni vengono aggiunte al AndroidManifest.xml con l'elemento uses-permission . Ad esempio, se un'applicazione deve individuare la posizione del dispositivo, richiede autorizzazioni per la posizione corretta e il percorso del corso. Al manifesto vengono aggiunti i due elementi seguenti:

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

È possibile dichiarare le autorizzazioni usando il supporto dello strumento integrato in Visual Studio:

  1. Fare doppio clic su Proprietà nella Esplora soluzioni e selezionare la scheda Manifesto Android nel Finestra Proprietà:

    Required permissions in the Android Manifest tab

  2. Se l'applicazione non dispone già di un AndroidManifest.xml, fare clic su Nessun AndroidManifest.xml trovato. Fare clic per aggiungerne uno come illustrato di seguito:

    No AndroidManifest.xml message

  3. Selezionare le autorizzazioni necessarie per l'applicazione dall'elenco Autorizzazioni necessarie e salvare:

    Example CAMERA permissions selected

Xamarin.Android aggiungerà automaticamente alcune autorizzazioni in fase di compilazione alle compilazioni di debug. In questo modo il debug dell'applicazione sarà più semplice. In particolare, due autorizzazioni rilevanti sono INTERNET e READ_EXTERNAL_STORAGE. Queste autorizzazioni impostate automaticamente non verranno abilitate nell'elenco Autorizzazioni necessarie. Le build di versione, tuttavia, usano solo le autorizzazioni impostate in modo esplicito nell'elenco Autorizzazioni necessarie.

Per le app destinate ad Android 5.1 (livello API 22) o inferiore, non è necessario eseguire altre operazioni. Le app che verranno eseguite in Android 6.0 (API 23 livello 23) o versioni successive devono procedere alla sezione successiva su come eseguire i controlli delle autorizzazioni di runtime.

Controlli delle autorizzazioni di runtime in Android 6.0

Il ContextCompat.CheckSelfPermission metodo (disponibile con la libreria di supporto Android) viene usato per verificare se è stata concessa un'autorizzazione specifica. Questo metodo restituirà un'enumerazione Android.Content.PM.Permission con uno dei due valori seguenti:

  • Permission.Granted : è stata concessa l'autorizzazione specificata.
  • Permission.Denied : l'autorizzazione specificata non è stata concessa.

Questo frammento di codice è un esempio di come verificare la presenza dell'autorizzazione Fotocamera in un'attività:

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == (int)Permission.Granted) 
{
    // We have permission, go ahead and use the camera.
} 
else 
{
    // Camera permission is not granted. If necessary display rationale & request.
}

È consigliabile informare l'utente del motivo per cui è necessaria un'autorizzazione per un'applicazione in modo che sia possibile prendere una decisione informata per concedere l'autorizzazione. Un esempio di questo è un'app che scatta foto e tag geografiche. È chiaro all'utente che l'autorizzazione della fotocamera è necessaria, ma potrebbe non essere chiaro perché l'app necessita anche della posizione del dispositivo. La logica dovrebbe visualizzare un messaggio per aiutare l'utente a capire perché l'autorizzazione di posizione è auspicabile e che l'autorizzazione della fotocamera è necessaria.

Il ActivityCompat.ShouldShowRequestPermissionRationale metodo viene usato per determinare se la logica deve essere visualizzata all'utente. Questo metodo restituirà true se deve essere visualizzata la logica di una determinata autorizzazione. Questo screenshot mostra un esempio di snackbar visualizzato da un'applicazione che spiega perché l'app deve conoscere la posizione del dispositivo:

Rationale for location

Se l'utente concede l'autorizzazione, è necessario chiamare il ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int requestCode) metodo . Questo metodo richiede i parametri seguenti:

  • activity : attività che richiede le autorizzazioni e che deve essere informata da Android dei risultati.
  • permissions : elenco delle autorizzazioni richieste.
  • requestCode : valore intero usato per trovare le corrispondenze con i risultati della richiesta di autorizzazione a una RequestPermissions chiamata. Questo valore deve essere maggiore di zero.

Questo frammento di codice è un esempio dei due metodi illustrati. Prima di tutto, viene effettuato un controllo per determinare se deve essere visualizzata la logica dell'autorizzazione. Se la logica deve essere mostrata, un snackbar viene visualizzato con la logica. Se l'utente fa clic su OK in Snackbar, l'app richiederà le autorizzazioni. Se l'utente non accetta la logica, l'app non deve continuare a richiedere le autorizzazioni. Se la logica non viene visualizzata, l'attività richiederà l'autorizzazione:

if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation)) 
{
    // Provide an additional rationale to the user if the permission was not granted
    // and the user would benefit from additional context for the use of the permission.
    // For example if the user has previously denied the permission.
    Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");

    var requiredPermissions = new String[] { Manifest.Permission.AccessFineLocation };
    Snackbar.Make(layout, 
                   Resource.String.permission_location_rationale,
                   Snackbar.LengthIndefinite)
            .SetAction(Resource.String.ok, 
                       new Action<View>(delegate(View obj) {
                           ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION);
                       }    
            )
    ).Show();
}
else 
{
    ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.Camera }, REQUEST_LOCATION);
}

RequestPermission può essere chiamato anche se l'utente ha già concesso l'autorizzazione. Le chiamate successive non sono necessarie, ma forniscono all'utente la possibilità di confermare (o revocare) l'autorizzazione. Quando RequestPermission viene chiamato, il controllo viene passato al sistema operativo, che visualizzerà un'interfaccia utente per accettare le autorizzazioni:

Permssion Dialog

Al termine dell'utente, Android restituirà i risultati all'attività tramite un metodo di callback, OnRequestPermissionResult. Questo metodo fa parte dell'interfaccia ActivityCompat.IOnRequestPermissionsResultCallback che deve essere implementata dall'attività. Questa interfaccia ha un singolo metodo, OnRequestPermissionsResult, che verrà richiamato da Android per informare l'attività delle scelte dell'utente. Se l'utente ha concesso l'autorizzazione, l'app può procedere e usare la risorsa protetta. Di seguito è riportato un esempio di come implementare OnRequestPermissionResult :

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    if (requestCode == REQUEST_LOCATION) 
    {
        // Received permission result for camera permission.
        Log.Info(TAG, "Received response for Location permission request.");

        // Check if the only required permission has been granted
        if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
            // Location permission has been granted, okay to retrieve the location of the device.
            Log.Info(TAG, "Location permission has now been granted.");
            Snackbar.Make(layout, Resource.String.permission_available_camera, Snackbar.LengthShort).Show();            
        } 
        else 
        {
            Log.Info(TAG, "Location permission was NOT granted.");
            Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
        }
    } 
    else 
    {
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

Riepilogo

Questa guida ha illustrato come aggiungere e controllare le autorizzazioni in un dispositivo Android. Le differenze nel funzionamento delle autorizzazioni tra le app Android precedenti (livello < API 23) e le nuove app Android (livello > API 22). Ha illustrato come eseguire controlli delle autorizzazioni di runtime in Android 6.0.