1. Antes de começar
O Android 10 e o 11 oferecem aos usuários mais controle sobre o acesso dos apps à localização do dispositivo.
Quando um app que opera no Android 11 solicita acesso à localização, os usuários têm quatro opções:
- Permitir o tempo todo
- Permitir durante o uso do app (no Android 10)
- Uma única vez (no Android 11)
- Negar
Android 10

Android 11

Neste codelab, você vai aprender a receber atualizações de localização e como oferecer suporte à localização em qualquer versão do Android, principalmente no Android 10 e 11. Ao final do codelab, você terá um app que segue as práticas recomendadas atuais para recuperar atualizações de local.
Pré-requisitos
- Familiaridade com o desenvolvimento para Android
- Familiaridade com atividades, serviços e permissões
O que você aprenderá
- Siga as práticas recomendadas para localização no Android.
- Processar permissões de localização em primeiro plano (quando o usuário solicita que o app acesse a localização do dispositivo enquanto ele está em uso).
- Modifique um app existente para adicionar suporte à solicitação de acesso à localização. Para isso, adicione código para se inscrever e cancelar a inscrição na localização.
- Adicione suporte ao app para Android 10 e 11 incluindo lógica para acessar a localização em primeiro plano ou durante o uso.
O que é necessário
- Android Studio 3.4 ou mais recente para executar o código
- Um dispositivo/emulador com uma prévia para desenvolvedores do Android 10 e 11
2. Primeiros passos
Clonar o repositório inicial do projeto
Para começar o mais rápido possível, você pode criar com base neste projeto inicial. Se você tiver o Git instalado, basta executar o seguinte comando:
git clone https://github.com/android/codelab-while-in-use-location
Acesse a página do GitHub diretamente.
Se você não tiver o Git, faça o download do projeto como um arquivo ZIP:
Importar o projeto
Abra o Android Studio, selecione Open an existing Android Studio project na tela inicial e abra o diretório do projeto.
Após o carregamento do projeto, você verá um alerta informando que o Git não está rastreando todas as mudanças locais. Clique em Ignorar. Você não enviará mudanças ao repositório Git.
No canto superior esquerdo da janela do projeto, você verá algo semelhante à imagem abaixo se estiver na visualização Android. Se você estiver na visualização Project, precisará expandi-la para ver a mesma coisa.

Há duas pastas (base e complete). Cada uma é conhecida como um "módulo".
O Android Studio pode levar vários segundos para compilar o projeto em segundo plano pela primeira vez. Durante esse período, você verá a seguinte mensagem na barra de status, na parte de baixo do Android Studio:

Aguarde até que o Android Studio termine de indexar e criar o projeto antes de fazer mudanças no código. Isso permitirá que o Android Studio extraia todos os componentes necessários.
Se você receber uma mensagem que diz Atualizar para que as mudanças de idioma entrem em vigor? ou algo semelhante, selecione Sim.
Entender o projeto inicial
Você já pode solicitar a localização no app. Use o módulo base como ponto de partida. Em cada etapa, adicione código ao módulo base. Quando você terminar este codelab, o código no módulo base vai corresponder ao conteúdo do módulo complete. O módulo complete pode ser usado para verificar seu trabalho ou para consulta em caso de problemas.
Os principais componentes incluem:
MainActivity: interface para o usuário permitir que o app acesse a localização do dispositivoLocationService: serviço que se inscreve e cancela a inscrição em mudanças de localização e se promove a um serviço em primeiro plano (com uma notificação) se o usuário sair da atividade do app. Adicione o código de local aqui.Util: adiciona funções de extensão para a classeLocatione salva a localização emSharedPreferences(camada de dados simplificada).
Configuração do emulador
Para saber como configurar um emulador do Android, consulte Executar em um emulador.
Executar o projeto inicial
Execute o app.
- Conecte o dispositivo Android ao computador ou inicie um emulador. Verifique se o dispositivo está executando o Android 10 ou uma versão mais recente.
- Na barra de ferramentas, selecione a configuração
baseno seletor suspenso e clique em Executar:

- Observe o seguinte app aparecer no seu dispositivo:

Nenhuma informação de local aparece na tela de saída. Isso porque você ainda não adicionou o código do local.
3. Adicionar local
Conceitos
O foco deste codelab é mostrar como receber atualizações de localização e, eventualmente, oferecer suporte ao Android 10 e ao Android 11.
No entanto, antes de começar a programar, é bom revisar o básico.
Tipos de acesso à localização
Você deve se lembrar das quatro opções diferentes de acesso à localização do início do codelab. Confira o que eles significam:
- Permitir durante o uso do app
- Essa é a opção recomendada para a maioria dos apps. Também conhecido como acesso "durante o uso" ou "somente em primeiro plano", essa opção foi adicionada no Android 10 e permite que os desenvolvedores recuperem a localização somente enquanto o app está sendo usado ativamente. Um app é considerado ativo se uma das seguintes condições for verdadeira:
- Uma atividade está visível.
- Um serviço em primeiro plano está sendo executado com uma notificação em andamento.
- Apenas uma vez
- Adicionada no Android 11, essa opção é igual a Permitir durante o uso do app, mas por um período limitado. Para mais informações, consulte Permissões únicas.
- Negar
- Essa opção impede o acesso às informações de local.
- Permitir o tempo todo
- Essa opção permite o acesso à localização o tempo todo, mas requer uma permissão extra para o Android 10 e versões mais recentes. Você também precisa ter um caso de uso válido e obedecer às políticas de local. Não vamos abordar essa opção neste codelab, porque é um caso de uso mais raro. No entanto, se você tiver um caso de uso válido e quiser entender como processar corretamente a localização o tempo todo, incluindo o acesso à localização em segundo plano, consulte o exemplo LocationUpdatesBackgroundKotlin.
Serviços, serviços em primeiro plano e vinculação
Para oferecer suporte total às atualizações de localização Permitir somente durante o uso do app, você precisa considerar quando o usuário sai do app. Se quiser continuar recebendo atualizações nessa situação, crie um Service em primeiro plano e o associe a um Notification.
Além disso, se você quiser usar o mesmo Service para solicitar atualizações de localização quando o app estiver visível e quando o usuário sair dele, será necessário vincular/desvincular esse Service ao elemento da interface.
Como este codelab se concentra apenas em receber atualizações de localização, você pode encontrar todo o código necessário na classe ForegroundOnlyLocationService.kt. Navegue pela classe e pelo MainActivity.kt para ver como eles funcionam juntos.
Para mais informações, consulte Visão geral dos serviços e Visão geral dos serviços vinculados.
Permissões
Para receber atualizações de localização de um NETWORK_PROVIDER ou GPS_PROVIDER, é preciso solicitar a permissão do usuário declarando a permissão ACCESS_COARSE_LOCATION ou ACCESS_FINE_LOCATION, respectivamente, no arquivo de manifesto do Android. Sem essas permissões, o app não poderá solicitar acesso à localização no tempo de execução.
Essas permissões abrangem os casos Apenas uma vez e Permitir durante o uso do app quando o app é usado em um dispositivo com Android 10 ou mais recente.
Local
O app pode acessar o conjunto de serviços de localização compatíveis por meio de classes no pacote com.google.android.gms.location.
Confira as principais classes:
FusedLocationProviderClient- Esse é o componente central do framework de localização. Depois de criado, ele é usado para solicitar atualizações de localização e receber o último local conhecido.
LocationRequest- É um objeto de dados que contém parâmetros de Qualidade de Serviço para solicitações (Intervalos de atualizações, Prioridades e acurácia). Ele é transmitido para o
FusedLocationProviderClientquando você solicita atualizações de local. LocationCallback- Usado para receber notificações quando a localização do dispositivo muda ou não pode mais ser determinada. Isso é transmitido como um
LocationResultem que você pode receber oLocationpara salvar no seu banco de dados.
Agora que você tem uma ideia básica do que está fazendo, comece a programar.
4. Adicionar recursos de local
Este codelab se concentra na opção de localização mais comum: Permitir durante o uso do app.
Para receber atualizações de local, o app precisa ter uma atividade visível ou um serviço em execução em primeiro plano (com uma notificação).
Permissões
O objetivo deste codelab é mostrar como receber atualizações de localização, não como solicitar permissões de localização. Por isso, o código baseado em permissões já está escrito para você. Pule se você já entender.
Confira a seguir os destaques das permissões (nenhuma ação é necessária para esta parte):
- Declare qual permissão você usa no
AndroidManifest.xml. - Antes de tentar acessar informações de localização, verifique se o usuário deu permissão para isso. Se o app ainda não tiver recebido permissão, solicite o acesso.
- Processar a escolha de permissão do usuário. (Você pode ver esse código em
MainActivity.kt.)
Se você pesquisar TODO: Step 1.0, Review Permissions em AndroidManifest.xml ou MainActivity.kt, vai encontrar todo o código escrito para permissões.
Para mais informações, consulte Visão geral das permissões.
Agora, comece a escrever um código de local.
Confira as principais variáveis necessárias para atualizações de local
No módulo base, procure TODO: Step 1.1, Review variables no
arquivo ForegroundOnlyLocationService.kt.
Nenhuma ação é necessária nesta etapa. Basta analisar o bloco de código a seguir, junto com os comentários, para entender as principais classes e variáveis usadas para receber atualizações de local.
// 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
Analise a inicialização do FusedLocationProviderClient
No módulo base, procure TODO: Step 1.2, Review the FusedLocationProviderClient no arquivo ForegroundOnlyLocationService.kt. O código vai ficar assim:
// TODO: Step 1.2, Review the FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
Como mencionado nos comentários anteriores, essa é a classe principal para receber atualizações de local. A variável já está inicializada para você, mas é importante revisar o código para entender como ela é inicializada. Você vai adicionar algum código aqui mais tarde para solicitar atualizações de localização.
Inicializar o LocationRequest
- No módulo
base, procureTODO: Step 1.3, Create a LocationRequestno arquivoForegroundOnlyLocationService.kt. - Adicione o seguinte código após o comentário.
O código de inicialização LocationRequest adiciona os parâmetros extras de qualidade de serviço necessários para sua solicitação (intervalos, tempo máximo de espera e prioridade).
// 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
}
- Leia os comentários para entender como cada um funciona.
Inicializar o LocationCallback
- No módulo
base, procureTODO: Step 1.4, Initialize the LocationCallbackno arquivoForegroundOnlyLocationService.kt. - Adicione o seguinte código após o comentário.
// 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))
}
}
}
O LocationCallback que você cria aqui é o callback que o FusedLocationProviderClient vai chamar quando uma nova atualização do local estiver disponível.
No callback, primeiro receba o local mais recente usando um objeto LocationResult. Depois disso, notifique seu Activity sobre o novo local usando uma transmissão local (se estiver ativa) ou atualize o Notification se esse serviço estiver sendo executado como um Service em primeiro plano.
- Leia os comentários para entender o que cada parte faz.
Inscrever-se para receber notificações sobre mudanças de local
Agora que você inicializou tudo, precisa informar ao FusedLocationProviderClient que quer receber atualizações.
- No módulo
base, procureStep 1.5, Subscribe to location changesno arquivoForegroundOnlyLocationService.kt. - Adicione o seguinte código após o comentário.
// TODO: Step 1.5, Subscribe to location changes.
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
A chamada requestLocationUpdates() informa ao FusedLocationProviderClient que você quer receber atualizações de local.
Você provavelmente reconhece os LocationRequest e LocationCallback que definiu anteriormente. Eles informam ao FusedLocationProviderClient os parâmetros de qualidade de serviço da sua solicitação e o que ele deve chamar quando tiver uma atualização. Por fim, o objeto Looper especifica a linha de execução para o callback.
Você também pode notar que esse código está dentro de uma instrução try/catch. Esse método exige um bloco porque um SecurityException ocorre quando o app não tem permissão para acessar informações de localização.
Cancelar a inscrição em mudanças de local
Quando o app não precisar mais de acesso às informações de localização, é importante cancelar a inscrição nas atualizações de localização.
- No módulo
base, procureTODO: Step 1.6, Unsubscribe to location changesno arquivoForegroundOnlyLocationService.kt. - Adicione o seguinte código após o comentário.
// 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.")
}
}
O método removeLocationUpdates() configura uma tarefa para informar ao FusedLocationProviderClient que você não quer mais receber atualizações de localização do seu LocationCallback. O addOnCompleteListener() fornece o callback para conclusão e executa o Task.
Assim como na etapa anterior, você pode ter notado que esse código está em uma instrução try/catch. Esse método exige um bloco porque um SecurityException ocorre quando o app não tem permissão para acessar informações de localização.
Talvez você se pergunte quando os métodos que contêm o código de inscrição/cancelamento de inscrição são chamados. Eles são acionados na classe principal quando o usuário toca no botão. Se quiser ver, confira a classe MainActivity.kt.
Executar app
Execute o app no Android Studio e teste o botão de localização.
As informações de local vão aparecer na tela de saída. Este é um app totalmente funcional para o Android 9.


5. Compatibilidade com o Android 10
Nesta seção, você vai adicionar suporte ao Android 10.
Seu app já se inscreve para receber notificações de mudanças de local, então não há muito trabalho a fazer.
Na verdade, basta especificar que o serviço em primeiro plano é usado para fins de localização.
SDK de destino 29
- No módulo
base, procureTODO: Step 2.1, Target Android 10 and then Android 11.no arquivobuild.gradle. - Faça estas mudanças:
- Defina
targetSdkVersioncomo29.
O código vai ficar assim:
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"
}
...
}
Depois disso, você vai precisar sincronizar o projeto. Clique em Sync Now.

Depois disso, seu app estará quase pronto para o Android 10.
Adicionar tipo de serviço em primeiro plano
No Android 10, é necessário incluir o tipo do serviço em primeiro plano se você precisar de acesso à localização durante o uso. No seu caso, ela está sendo usada para receber informações de localização.
No módulo base, pesquise TODO: 2.2, Add foreground service type no arquivo AndroidManifest.xml e adicione o seguinte código ao elemento <service>:
android:foregroundServiceType="location"
O código vai ficar assim:
<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>
Pronto! Seu app oferece suporte à localização do Android 10 "durante o uso" seguindo as práticas recomendadas para localização no Android.
Executar app
Execute o app no Android Studio e teste o botão de localização.
Tudo vai funcionar como antes, mas agora no Android 10. Se você não aceitou as permissões de locais antes, a tela de permissão vai aparecer agora.



6. Compatibilidade com o Android 11
Nesta seção, você vai direcionar o app ao Android 11.
A boa notícia é que você não precisa fazer mudanças em nenhum arquivo, exceto o build.gradle.
SDK de destino 11
- No módulo
base, procureTODO: Step 2.1, Target SDKno arquivobuild.gradle. - Faça estas mudanças:
compileSdkVersiona30targetSdkVersiona30
O código vai ficar assim:
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"
}
...
}
Depois disso, você vai precisar sincronizar o projeto. Clique em Sync Now.

Depois disso, seu app estará pronto para o Android 11.
Executar app
Execute o app no Android Studio e clique no botão.
Tudo vai funcionar como antes, mas agora no Android 11. Se você não aceitou as permissões de locais antes, a tela de permissão vai aparecer agora.


7. Estratégias de localização para Android
Ao verificar e solicitar permissões de localização nas formas apresentadas neste codelab, seu app pode acompanhar o nível de acesso à localização do dispositivo.
Esta página lista algumas práticas recomendadas importantes relacionadas a permissões de localização. Para mais informações sobre como manter a segurança dos dados dos usuários, consulte Práticas recomendadas de permissões do app.
Solicitar somente as permissões necessárias
Solicite permissões somente quando necessário. Exemplo:
- Não solicite uma permissão de localização na inicialização do app, a menos que seja absolutamente necessário.
- Se o app for destinado ao Android 10 ou mais recente e tiver um serviço em primeiro plano, declare um
foregroundServiceTypede"location"no manifesto. - Não solicite permissões de localização em segundo plano, a menos que você tenha um caso de uso válido, conforme descrito em Acesso mais seguro e transparente à localização do usuário.
Compatibilidade com degradação suave se a permissão não for concedida
Para manter uma boa experiência do usuário, projete seu app para que ele possa lidar de maneira eficaz com as seguintes situações:
- Seu app não tem acesso a informações de localização.
- Seu app não tem acesso a informações de localização ao ser executado em segundo plano.
8. Parabéns
Você aprendeu a receber atualizações de localização no Android, seguindo as práticas recomendadas.
Saiba mais
- Exemplo completo de uso da localização em segundo plano se você tiver um caso de uso válido
- Solicitar atualizações de localização