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 adicionando 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:

Você vai notar que nenhuma informação de localização 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 da estrutura 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 precisão). 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
Revisar 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 nas 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 localização 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 os dados dos usuários seguros, consulte Práticas recomendadas de permissões de apps.
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