1. Prima di iniziare
Android 10 e 11 offrono agli utenti un maggiore controllo sull'accesso delle app alle posizioni del dispositivo.
Quando un'app in esecuzione su Android 11 richiede l'accesso alla posizione, gli utenti hanno quattro opzioni:
- Consenti sempre
- Consenti solo mentre l'app è in uso (in Android 10)
- Una sola volta (in Android 11)
- Nega
Android 10

Android 11

In questo codelab, imparerai a ricevere aggiornamenti sulla posizione e a supportare la posizione su qualsiasi versione di Android, in particolare Android 10 e 11. Al termine del codelab, avrai un'app che segue le best practice attuali per il recupero degli aggiornamenti della posizione.
Prerequisiti
- Familiarità con lo sviluppo per Android
- Familiarità con attività, servizi e autorizzazioni
Attività previste
- Segui le best practice per la posizione in Android.
- Gestisci le autorizzazioni di accesso alla posizione in primo piano (quando l'utente richiede che la tua app acceda alla posizione del dispositivo mentre è in uso).
- Modifica un'app esistente per aggiungere il supporto per la richiesta di accesso alla posizione aggiungendo il codice per l'iscrizione e l'annullamento dell'iscrizione alla posizione.
- Aggiungi il supporto all'app per Android 10 e 11 aggiungendo la logica per accedere alla posizione in primo piano o durante l'utilizzo.
Che cosa ti serve
- Android Studio 3.4 o versioni successive per eseguire il codice
- Un dispositivo/emulatore con una versione di anteprima per sviluppatori di Android 10 e 11
2. Per iniziare
Clona il repository del progetto iniziale
Per iniziare il più rapidamente possibile, puoi basarti su questo progetto iniziale. Se hai installato Git, puoi semplicemente eseguire il seguente comando:
git clone https://github.com/android/codelab-while-in-use-location
Visita direttamente la pagina GitHub.
Se non hai Git, puoi scaricare il progetto come file ZIP:
Importare il progetto
Apri Android Studio, seleziona "Apri un progetto Android Studio esistente" dalla schermata di benvenuto e apri la directory del progetto.
Dopo il caricamento del progetto, potresti anche visualizzare un avviso che indica che Git non monitora tutte le modifiche locali. Puoi fare clic su Ignora. Non verrà eseguito il push di alcuna modifica nel repository Git.
Nell'angolo in alto a sinistra della finestra del progetto, dovresti vedere un'immagine simile a quella riportata di seguito se ti trovi nella visualizzazione Android. Se ti trovi nella visualizzazione Progetto, devi espandere il progetto per visualizzare la stessa cosa.

Esistono due cartelle (base e complete). Ciascuna è nota come "modulo".
Tieni presente che Android Studio potrebbe impiegare diversi secondi per compilare il progetto in background per la prima volta. Durante questo periodo, nella barra di stato nella parte inferiore di Android Studio viene visualizzato il seguente messaggio:

Attendi il completamento dell'indicizzazione e della creazione del progetto da parte di Android Studio prima di apportare modifiche al codice. In questo modo, Android Studio potrà recuperare tutti i componenti necessari.
Se viene visualizzato il messaggio Ricaricare per applicare le modifiche alla lingua? o un messaggio simile, seleziona Sì.
Informazioni sul progetto iniziale
La configurazione è completata e puoi richiedere la posizione nell'app. Utilizza il modulo base come punto di partenza. Durante ogni passaggio, aggiungi il codice al modulo base. Al termine di questo codelab, il codice nel modulo base dovrebbe corrispondere ai contenuti del modulo complete. Il modulo complete può essere utilizzato per controllare il tuo lavoro o come riferimento in caso di problemi.
I componenti chiave includono quanto segue:
MainActivity: interfaccia utente che consente all'app di accedere alla posizione del dispositivoLocationService: servizio che si iscrive e annulla l'iscrizione alle modifiche della posizione e si promuove a servizio in primo piano (con una notifica) se l'utente esce dall'attività dell'app. Aggiungi qui il codice della sede.Util: aggiunge funzioni di estensione per la classeLocatione salva la posizione inSharedPreferences(livello dati semplificato).
Configurazione dell'emulatore
Per informazioni sulla configurazione di un emulatore Android, vedi Eseguire su un emulatore.
Esegui il progetto iniziale
Esegui l'app.
- Collega il dispositivo Android al computer o avvia un emulatore. Assicurati che sul dispositivo sia installato Android 10 o versioni successive.
- Nella barra degli strumenti, seleziona la configurazione
basedal selettore a discesa e fai clic su Esegui:

- Nota la seguente app sul tuo dispositivo:

Potresti notare che nella schermata di output non vengono visualizzate informazioni sulla posizione. Questo perché non hai ancora aggiunto il codice della sede.
3. Aggiunta della posizione
Concetti
Lo scopo di questo codelab è mostrarti come ricevere gli aggiornamenti della posizione e, infine, supportare Android 10 e Android 11.
Tuttavia, prima di iniziare a programmare, è opportuno rivedere le nozioni di base.
Tipi di accesso alla posizione
Potresti ricordare le quattro diverse opzioni per l'accesso alla posizione dall'inizio del codelab. Vediamo cosa significano:
- Consenti solo mentre l'app è in uso
- Questa opzione è consigliata per la maggior parte delle app. Conosciuta anche come accesso "durante l'uso" o "solo in primo piano", questa opzione è stata aggiunta in Android 10 e consente agli sviluppatori di recuperare la posizione solo mentre l'app è in uso attivo. Un'app è considerata attiva se è vera una delle seguenti condizioni:
- Un'attività è visibile.
- Un servizio in primo piano è in esecuzione con una notifica continua.
- Solo una volta
- Aggiunta in Android 11, questa opzione è uguale a Consenti solo mentre l'app è in uso, ma per un periodo di tempo limitato. Per ulteriori informazioni, vedi Autorizzazioni temporanee.
- Nega
- Questa opzione impedisce l'accesso alle informazioni sulla posizione.
- Consenti sempre
- Questa opzione consente l'accesso alla posizione in qualsiasi momento, ma richiede un'autorizzazione aggiuntiva per Android 10 e versioni successive. Devi anche assicurarti di avere un caso d'uso valido e di rispettare le norme relative alla posizione. Non tratteremo questa opzione in questo codelab, in quanto si tratta di un caso d'uso più raro. Tuttavia, se hai un caso d'uso valido e vuoi capire come gestire correttamente la posizione sempre attiva, incluso l'accesso alla posizione in background, consulta l'esempio LocationUpdatesBackgroundKotlin.
Servizi, servizi in primo piano e binding
Per supportare completamente gli aggiornamenti della posizione Consenti solo quando l'app è in uso, devi tenere conto di quando l'utente esce dalla tua app. Se vuoi continuare a ricevere aggiornamenti in questa situazione, devi creare un servizio in primo piano Service e associarlo a un Notification.
Inoltre, se vuoi utilizzare lo stesso Service per richiedere aggiornamenti della posizione quando la tua app è visibile e quando l'utente esce dall'app, devi associare/dissociare Service all'elemento UI.
Poiché questo codelab si concentra solo sull'ottenimento degli aggiornamenti della posizione, puoi trovare tutto il codice necessario nella classe ForegroundOnlyLocationService.kt. Puoi sfogliare il corso e il MainActivity.kt per vedere come interagiscono.
Per saperne di più, consulta Panoramica dei servizi e Panoramica dei servizi vincolati.
Autorizzazioni
Per ricevere aggiornamenti sulla posizione da un NETWORK_PROVIDER o da un GPS_PROVIDER, devi richiedere l'autorizzazione dell'utente dichiarando l'autorizzazione ACCESS_COARSE_LOCATION o ACCESS_FINE_LOCATION, rispettivamente, nel file manifest di Android. Senza queste autorizzazioni, la tua app non potrà richiedere l'accesso alla posizione in fase di runtime.
Queste autorizzazioni coprono i casi Solo una volta e Consenti solo mentre l'app è in uso quando la tua app viene utilizzata su un dispositivo con Android 10 o versioni successive.
Località
La tua app può accedere all'insieme di servizi di localizzazione supportati tramite le classi nel pacchetto com.google.android.gms.location.
Esamina le classi principali:
FusedLocationProviderClient- Questo è il componente centrale del framework della posizione. Una volta creato, lo utilizzi per richiedere aggiornamenti della posizione e ottenere l'ultima posizione nota.
LocationRequest- Si tratta di un oggetto dati che contiene parametri di qualità del servizio per le richieste (intervalli per gli aggiornamenti, priorità e precisione). Questo valore viene passato a
FusedLocationProviderClientquando richiedi aggiornamenti della posizione. LocationCallback- Viene utilizzato per ricevere notifiche quando la posizione del dispositivo è cambiata o non può più essere determinata. Viene passato un
LocationResultin cui puoi ottenere l'Locationda salvare nel database.
Ora che hai un'idea di base di cosa fare, inizia a lavorare con il codice.
4. Aggiungere funzionalità di localizzazione
Questo codelab si concentra sull'opzione di localizzazione più comune: Consenti solo mentre l'app è in uso.
Per ricevere aggiornamenti sulla posizione, l'app deve avere un'attività visibile o un servizio in esecuzione in primo piano (con una notifica).
Autorizzazioni
Lo scopo di questo codelab è mostrare come ricevere aggiornamenti sulla posizione, non come richiedere le autorizzazioni di accesso alla posizione, quindi il codice basato sulle autorizzazioni è già scritto. Se hai già compreso il concetto, puoi saltare questa parte.
Di seguito sono riportati i punti salienti delle autorizzazioni (per questa sezione non sono richieste azioni):
- Dichiara quale autorizzazione utilizzi in
AndroidManifest.xml. - Prima di tentare di accedere alle informazioni sulla posizione, controlla se l'utente ha concesso alla tua app l'autorizzazione per farlo. Se la tua app non ha ancora ricevuto l'autorizzazione, richiedi l'accesso.
- Gestire la scelta dell'utente relativa all'autorizzazione. Puoi visualizzare questo codice in
MainActivity.kt.
Se cerchi TODO: Step 1.0, Review Permissions in AndroidManifest.xml o in MainActivity.kt, vedrai tutto il codice scritto per le autorizzazioni.
Per ulteriori informazioni, vedi la Panoramica delle autorizzazioni.
Ora inizia a scrivere un po' di codice di localizzazione.
Esamina le variabili chiave necessarie per gli aggiornamenti della posizione
Nel modulo base, cerca TODO: Step 1.1, Review variables in
ForegroundOnlyLocationService.kt.
In questo passaggio non sono necessarie azioni. Devi solo esaminare il seguente blocco di codice, insieme ai commenti, per comprendere le classi e le variabili chiave che utilizzi per ricevere gli aggiornamenti della posizione.
// TODO: Step 1.1, Review variables (no changes).
// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
// LocationRequest - Requirements for the location updates, i.e., how often you
// should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest
// LocationCallback - Called when FusedLocationProviderClient has a new Location.
private lateinit var locationCallback: LocationCallback
// Used only for local storage of the last known location. Usually, this would be saved to your
// database, but because this is a simplified sample without a full database, we only need the
// last location to create a Notification if the user navigates away from the app.
private var currentLocation: Location? = null
Esaminare l'inizializzazione di FusedLocationProviderClient
Nel modulo base, cerca TODO: Step 1.2, Review the FusedLocationProviderClient nel file ForegroundOnlyLocationService.kt. Il codice dovrebbe essere simile a questo:
// TODO: Step 1.2, Review the FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
Come accennato nei commenti precedenti, questa è la classe principale per ricevere gli aggiornamenti sulla posizione. La variabile è già inizializzata, ma è importante esaminare il codice per capire come viene inizializzata. In un secondo momento aggiungerai qui del codice per richiedere gli aggiornamenti della posizione.
Inizializza LocationRequest
- Nel modulo
base, cercaTODO: Step 1.3, Create a LocationRequestnel fileForegroundOnlyLocationService.kt. - Aggiungi il seguente codice dopo il commento.
Il codice di inizializzazione LocationRequest aggiunge i parametri di qualità del servizio aggiuntivi necessari per la richiesta (intervalli, tempo di attesa massimo e priorità).
// TODO: Step 1.3, Create a LocationRequest.
locationRequest = LocationRequest.create().apply {
// Sets the desired interval for active location updates. This interval is inexact. You
// may not receive updates at all if no location sources are available, or you may
// receive them less frequently than requested. You may also receive updates more
// frequently than requested if other applications are requesting location at a more
// frequent interval.
//
// IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of
// targetSdkVersion) may receive updates less frequently than this interval when the app
// is no longer in the foreground.
interval = TimeUnit.SECONDS.toMillis(60)
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates more frequently than this value.
fastestInterval = TimeUnit.SECONDS.toMillis(30)
// Sets the maximum time when batched location updates are delivered. Updates may be
// delivered sooner than this interval.
maxWaitTime = TimeUnit.MINUTES.toMillis(2)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
- Leggi i commenti per capire come funziona ciascuno.
Inizializza LocationCallback
- Nel modulo
base, cercaTODO: Step 1.4, Initialize the LocationCallbacknel fileForegroundOnlyLocationService.kt. - Aggiungi il seguente codice dopo il commento.
// TODO: Step 1.4, Initialize the LocationCallback.
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
// Normally, you want to save a new location to a database. We are simplifying
// things a bit and just saving it as a local variable, as we only need it again
// if a Notification is created (when the user navigates away from app).
currentLocation = locationResult.lastLocation
// Notify our Activity that a new location was added. Again, if this was a
// production app, the Activity would be listening for changes to a database
// with new locations, but we are simplifying things a bit to focus on just
// learning the location side of things.
val intent = Intent(ACTION_FOREGROUND_ONLY_LOCATION_BROADCAST)
intent.putExtra(EXTRA_LOCATION, currentLocation)
LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)
// Updates notification content if this service is running as a foreground
// service.
if (serviceRunningInForeground) {
notificationManager.notify(
NOTIFICATION_ID,
generateNotification(currentLocation))
}
}
}
Il LocationCallback che crei qui è il callback che FusedLocationProviderClient chiamerà quando sarà disponibile un nuovo aggiornamento della posizione.
Nel callback, prima ottieni l'ultima posizione utilizzando un oggetto LocationResult. Dopodiché, comunichi la nuova posizione al tuo Activity utilizzando una trasmissione locale (se è attiva) o aggiorni il Notification se questo servizio è in esecuzione come Service in primo piano.
- Leggi i commenti per capire a cosa serve ogni parte.
Iscriviti alle modifiche alla sede
Ora che hai inizializzato tutto, devi comunicare a FusedLocationProviderClient che vuoi ricevere gli aggiornamenti.
- Nel modulo
base, cercaStep 1.5, Subscribe to location changesnel fileForegroundOnlyLocationService.kt. - Aggiungi il seguente codice dopo il commento.
// TODO: Step 1.5, Subscribe to location changes.
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
La chiamata requestLocationUpdates() comunica a FusedLocationProviderClient che vuoi ricevere aggiornamenti sulla posizione.
Probabilmente riconoscerai LocationRequest e LocationCallback che hai definito in precedenza. Questi consentono a FusedLocationProviderClient di conoscere i parametri di qualità del servizio per la tua richiesta e cosa deve chiamare quando ha un aggiornamento. Infine, l'oggetto Looper specifica il thread per il callback.
Potresti anche notare che questo codice si trova all'interno di un'istruzione try/catch. Questo metodo richiede un blocco perché si verifica un SecurityException quando l'app non ha l'autorizzazione per accedere alle informazioni sulla posizione.
Annullare l'iscrizione alle modifiche della posizione
Quando l'app non ha più bisogno di accedere ai dati sulla posizione, è importante annullare l'iscrizione agli aggiornamenti sulla posizione.
- Nel modulo
base, cercaTODO: Step 1.6, Unsubscribe to location changesnel fileForegroundOnlyLocationService.kt. - Aggiungi il seguente codice dopo il commento.
// TODO: Step 1.6, Unsubscribe to location changes.
val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(TAG, "Location Callback removed.")
stopSelf()
} else {
Log.d(TAG, "Failed to remove Location Callback.")
}
}
Il metodo removeLocationUpdates() configura un'attività per comunicare a FusedLocationProviderClient che non vuoi più ricevere aggiornamenti sulla posizione del tuo LocationCallback. addOnCompleteListener() fornisce il callback per il completamento ed esegue Task.
Come nel passaggio precedente, potresti aver notato che questo codice si trova all'interno di un'istruzione try/catch. Questo metodo richiede un blocco perché si verifica un SecurityException quando l'app non ha l'autorizzazione per accedere alle informazioni sulla posizione
Potresti chiederti quando vengono chiamati i metodi che contengono il codice di iscrizione/annullamento dell'iscrizione. Vengono attivati nella classe principale quando l'utente tocca il pulsante. Se vuoi vederlo, dai un'occhiata al corso MainActivity.kt.
Esegui l'app
Esegui l'app da Android Studio e prova il pulsante della posizione.
Dovresti visualizzare le informazioni sulla posizione nella schermata di output. Si tratta di un'app completamente funzionale per Android 9.


5. Supporto di Android 10
In questa sezione aggiungi il supporto per Android 10.
La tua app è già abbonata alle modifiche della posizione, quindi non c'è molto da fare.
Infatti, tutto ciò che devi fare è specificare che il servizio in primo piano viene utilizzato per scopi di localizzazione.
SDK target 29
- Nel modulo
base, cercaTODO: Step 2.1, Target Android 10 and then Android 11.nel filebuild.gradle. - Apporta queste modifiche:
- Imposta
targetSdkVersionsu29.
Il codice dovrebbe essere simile a questo:
android {
// TODO: Step 2.1, Target Android 10 and then Android 11.
compileSdkVersion 29
defaultConfig {
applicationId "com.example.android.whileinuselocation"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
...
}
Dopodiché, ti verrà chiesto di sincronizzare il progetto. Fai clic su Sincronizza ora.

Dopodiché, la tua app è quasi pronta per Android 10.
Aggiungere il tipo di servizio in primo piano
In Android 10, devi includere il tipo di servizio in primo piano se hai bisogno dell'accesso alla posizione durante l'uso. Nel tuo caso, viene utilizzato per ottenere informazioni sulla posizione.
Nel modulo base, cerca TODO: 2.2, Add foreground service type in AndroidManifest.xml e aggiungi il seguente codice all'elemento <service>:
android:foregroundServiceType="location"
Il codice dovrebbe essere simile a questo:
<application>
...
<!-- Foreground services in Android 10+ require type. -->
<!-- TODO: 2.2, Add foreground service type. -->
<service
android:name="com.example.android.whileinuselocation.ForegroundOnlyLocationService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="location" />
</application>
È tutto. La tua app supporta la posizione di Android 10 per l'utilizzo seguendo le best practice per la posizione in Android.
Esegui l'app
Esegui l'app da Android Studio e prova il pulsante della posizione.
Tutto dovrebbe funzionare come prima, ma ora funziona su Android 10. Se in precedenza non hai accettato le autorizzazioni per le posizioni, ora dovresti visualizzare la schermata delle autorizzazioni.



6. Supporto di Android 11
In questa sezione, scegli come target Android 11.
Ottime notizie: non devi apportare modifiche ad alcun file, ad eccezione del file build.gradle.
SDK target 11
- Nel modulo
base, cercaTODO: Step 2.1, Target SDKnel filebuild.gradle. - Apporta queste modifiche:
- Da
compileSdkVersiona30 - Da
targetSdkVersiona30
Il codice dovrebbe essere simile a questo:
android {
TODO: Step 2.1, Target Android 10 and then Android 11.
compileSdkVersion 30
defaultConfig {
applicationId "com.example.android.whileinuselocation"
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
...
}
Dopodiché, ti verrà chiesto di sincronizzare il progetto. Fai clic su Sincronizza ora.

A questo punto, la tua app è pronta per Android 11.
Esegui l'app
Esegui l'app da Android Studio e prova a fare clic sul pulsante.
Tutto dovrebbe funzionare come prima, ma ora funziona su Android 11. Se in precedenza non hai accettato le autorizzazioni per le posizioni, ora dovresti visualizzare la schermata delle autorizzazioni.


7. Strategie di localizzazione per Android
Se controlli e richiedi le autorizzazioni di accesso alla posizione nei modi mostrati in questo codelab, la tua app può tenere traccia correttamente del suo livello di accesso alla posizione del dispositivo.
Questa pagina elenca alcune best practice chiave relative alle autorizzazioni di localizzazione. Per saperne di più su come proteggere i dati degli utenti, consulta Best practice per le autorizzazioni delle app.
Richiedi solo le autorizzazioni di cui hai bisogno
Chiedi le autorizzazioni solo quando necessario. Ad esempio:
- Non richiedere un'autorizzazione di accesso alla posizione all'avvio dell'app, a meno che non sia assolutamente necessario.
- Se la tua app ha come target Android 10 o versioni successive e hai un servizio in primo piano, dichiara un
foregroundServiceTypedi"location"nel manifest. - Non richiedere le autorizzazioni di accesso alla posizione in background, a meno che tu non abbia un caso d'uso valido, come descritto in Accesso più sicuro e trasparente alla posizione dell'utente.
Supportare la degradazione controllata se l'autorizzazione non viene concessa
Per mantenere una buona esperienza utente, progetta la tua app in modo che possa gestire correttamente le seguenti situazioni:
- La tua app non ha accesso alle informazioni sulla posizione.
- La tua app non ha accesso alle informazioni sulla posizione quando viene eseguita in background.
8. Complimenti
Hai imparato a ricevere aggiornamenti sulla posizione in Android, tenendo a mente le best practice.
Scopri di più
- Esempio completo per l'utilizzo della localizzazione in background se hai un caso d'uso valido
- Richiedere aggiornamenti della posizione