Negli anni mi sono creato un flusso abbastanza preciso per richiedere i permessi che, bene o male funziona per tutti i casi. Seguendo questi passi, non dovreste avere problemi:
-
La mia App ha i permessi?
-
SI: (es. ) mostra la posizione dell’utente sulla mappa, oppure (altro esempio) mostra il bottone “Scatta foto”
-
NO: in questo ramo andremo a controllare se c’e’ bisogno di mostrare il Dialog per la richiesta ulteriore di permessi, perche’ l’utente l’ha negata prima in modo non definitivo. Qui ci viene in aiuto il metodo , shouldShowRequestPermissionRationale() del Context o ActivityCompat
-
Se c’è bisogno di mostrarlo, lo faro’, dando una spiegazione sul fatto che avendo negato i permessi precedentemente la mia App non potrà utilizzare certe funzionalità, dando una ulteriore possibilità di concessione di permessi
-
Se non cè bisogno di Rationale allora andremo direttamente a richiedere i permessi con il dialog di sistema.
-
-
fun checkPermissions() { // Controlliamo se i permessi sono stati concessi... if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Permessi non concessi // Dobbiamo mostrare una spiegazione? if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.ACCESS_FINE_LOCATION)) { // Mostra una spiegazione del perchè la mancanza di questi permessi // può negare alcune funzionalità. Questa spiegazione può essere // data con un semplice AlertDialog(). Alla riposta positiva (l'utente // accetta di dare i permessi) andremo a richiedere i permessi con // le istruzioni predefiniti (es. ActivityCompat.requestPermissions([...]) // come mostrato qui sotto } else { // Nessuna spiegazione da dare, richiediamo direttamente i permessi ActivityCompat.requestPermissions(thisActivity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSIONS) //REQUEST_LOCATION_PERMISSIONS è una costante che andremo ad utilizzare // nel metodo onRequestPermissionsResults([...]) per analizzare i risultati // ed agire di conseguenza } } else { // Fantastico, abbiamo già i permessi, possiamo fare tutti i danni che vogliamo :D } }
Il flusso che vi ho descritto qua sopra può essere considerato abbastanza “standard”, ovvero può adattarsi a qualsiasi tipo di permesso. Il concetto, per concludere, è piuttosto semplice, quindi: Ho i permessi? Si: faccio le mie cose. No? Guardo se devo richiederli di nuovo, altrimenti mi rassegno ?
Ultimo e non ultimo, il metodo …
override fun onRequestPermissionsResults([...])
… in cui andremo ad esaminare se i permessi sono stati concessi ed eventualmente attivare / disattivare / far partire alcune funzionalità
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { REQUEST_LOCATION_PERMISSIONS -> { map?.uiSettings.isMyLocationButtonEnabled = false if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { button_position_on_me.visibility = View.VISIBLE map.isMyLocationEnabled = true } else { button_position_on_me.visibility = View.GONE map.isMyLocationEnabled = false Snackbar.make( view!!, getString(R.string.gps_permissions_not_granted), Snackbar.LENGTH_INDEFINITE ) .setAction(android.R.string.ok) { checkLocationPermissions() } .show() } } } }
Quindi, ricapitolando, ecco alcuni punti che potrebbero chiarirvi dei dubbi:
- Leggetevi la Documentazione ufficiale. Questa, per quanto prolissa (e forse anche un tantino confusa), può nella maggior parte dei casi risolvere il problema che vi sta assillando. Soprattutto date un’occhiata ai Livellli di protezione, in modo da capire se e quando richiedere o meno il coinvolgimento dell’utente della vostra fantastica App, in modo che il funzionamento sia garantito.
- Una volta capito come dovrebbero funzionare, cercate di assimilare un concetto di base. Di per sé la richiesta di un’autorizzazione è un’operazione parecchio invasiva, soprattutto perché, ad oggi, moltissimi utenti sono diffidenti nel dare autorizzazioni alle App perché si sentono “controllati”. Quindi si deve cercare di pensare al flusso dell’App in modo che guidi il più possibile a questa operazione avendo già coinvolto l’utente. Vi faccio un esempio: se la vostra App prevede l’utilizzo del salvataggio di documenti nella memoria del telefono, è necessario che l’utente sia coinvolto nel flusso della richiesta dei permessi *SE E SOLO SE* sta tentando di effettuare questa operazione di salvataggio. Ovvero, a meno che la funzionalità principale dell’App non sia proprio il salvataggio di documenti, sarebbe opportuno chiedere i permessi all’utente solo quando questo sta salvando un documento ed i permessi non sono stati accordati. Perché dico questo? Poniamo il caso che un’App che sto progettando abbia bisogno di 3 tipi di permessi espliciti: Fotocamera, Salvataggio files e Localizzazione GPS. Ora, se sono pigro (sbagliando), chiedo tutti i permessi subito, all’apertura dell’App, in modo da “togliermi subito il sassolino dalla scarpa”. Ovviamente non c’è niente di più sbagliato, oppure giusto per togliersi di mezzo subito una bella fetta di utilizzatori potenziali dell’App. Ci sono utenti a cui non da fastidio rispondere alla domanda “Vuoi concedere i permessi di localizzazione?” nonostante non ci sia neanche una mappa caricata nell’Activity attuale, ci sono invece utenti che non appena vedono le finestre di richiesta permessi si insospettiscono e chiudono / disinstallano l’App al volo.
- Prima di chiedere un’autorizzazione e mostrare il dialog di sistema per richiedere i permessi date sempre una spiegazione del perché e come andrete ad utilizzare quelle funzionalità. Ad esempio, se la vostra App ha una mappa in cui si vuole visualizzare il classico puntino blu della posizione dell’utente, è necessario richiedere i permessi di localizzazione. Per questo, la prima volta che si apre l’App, sarebbe bene spiegare, in un OnBoarding oppure in un dialog quando la mappa è caricata, il perché andremo a chiedere i permessi. Un AlertDialog che dice “Se vuoi vedere la tua posizione mostrata sulla mappa è necessario che tu accetti la richiesta di concedere l’accesso ai permessi di localizzazione all’APP. Vuoi continuare?“. SOLO a questo punto e se l’utente accetta, mostreremo il dialog di sistema.
Alla prossima, gente! PS: dimenticavo, se i permessi vengono richiesti in un Fragment piuttosto che in un’Activity, ricordatevi di implementare il metodo onRequestPermissionsResults([…]) e di richiamare il super.onRequestPermissionsResults() nell’Activity, altrimenti potrete attendere la chiamata al onRequestPermissionsResults([..]) del Fragment fino alla notte dei tempi a venire.