1. Introdução
Levamos nossos smartphones para todos os lugares, mas até agora, era difícil para os apps ajustar a experiência ao ambiente e à atividade em constante mudança de um usuário.
Antes, os desenvolvedores gastavam um tempo valioso de engenharia combinando vários indicadores (localização, sensor etc.) para determinar quando uma atividade como caminhar ou dirigir havia começado ou terminado. Pior ainda, quando os apps verificam de forma independente e contínua as mudanças na atividade do usuário, a duração da bateria é afetada.
A API Activity Recognition Transition resolve esses problemas fornecendo uma API simples que faz todo o processamento para você e informa apenas o que realmente importa: quando a atividade de um usuário mudou. Seu app simplesmente assina uma transição nas atividades de interesse, e a API notifica você sobre as mudanças.
Por exemplo, um app de mensagens pode perguntar "me avise quando o usuário entrar ou sair de um veículo" para definir o status dele como ocupado. Da mesma forma, um app de detecção de estacionamento pode perguntar: "me avise quando o usuário sair de um veículo e começar a caminhar" para salvar o local de estacionamento do usuário.
Neste codelab, você vai aprender a usar a API Activity Recognition Transition para determinar quando um usuário inicia/para uma atividade como caminhar ou correr.
Pré-requisitos
Familiaridade com o desenvolvimento para Android e com callbacks.
O que você vai aprender
- Como se inscrever para transições de atividades
- Processamento desses eventos
- Cancelar a inscrição das transições de atividade quando elas não forem mais necessárias
O que é necessário
- Android Studio Bumblebee
- Um dispositivo ou emulador Android
2. Como começar
Clonar o repositório inicial do projeto
Para começar o mais rápido possível, preparamos um projeto inicial para você desenvolver. Caso você tenha o git instalado, basta executar o comando abaixo. Para verificar se o git está instalado, digite git --version na linha de comando ou terminal e veja se ele é executado corretamente.
git clone https://github.com/android/codelab-activity_transitionapi
Se você não tiver o git, faça o download do projeto como um arquivo ZIP:
Importar o projeto
Inicie o Android Studio, selecione "Open an existing Android Studio project" na tela inicial e abra o diretório do projeto.
Depois que o projeto for carregado, você poderá ver um alerta informando que o Git não está rastreando todas as mudanças locais. Clique em Ignorar ou no X no canto superior direito. 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á dois ícones de pasta (base e complete). Cada um deles é conhecido como "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á um ícone de carregamento na barra de status, que fica na parte de baixo do Android Studio:

Recomendamos aguardar até que isso termine antes de fazer mudanças no código. Isso permitirá que o Android Studio extraia todos os componentes necessários.
Além disso, se você receber uma mensagem que diz "Reload for language changes to take effect?" ou algo semelhante, selecione "Yes".
Entender o projeto inicial
Está tudo pronto para você adicionar o reconhecimento de atividade. Usaremos o módulo base, que é o ponto de partida para este codelab. Em outras palavras, você adicionará um código de cada etapa a base.
O módulo complete pode ser usado para verificar seu trabalho ou para consulta em caso de problemas.
Visão geral dos componentes principais:
MainActivity: contém todo o código necessário para o reconhecimento de atividades.
Configuração do emulador
Se precisar de ajuda para configurar um emulador do Android, consulte o artigo Executar o app.
Executar o projeto inicial
Vamos executar o app.
- Conecte o dispositivo Android ao computador ou inicie um emulador.
- Na barra de ferramentas, selecione a configuração
baseno seletor suspenso e clique no botão de triângulo verde (Executar) ao lado dele:

- O aplicativo abaixo vai aparecer:

- O app não faz nada além de imprimir uma mensagem. Agora vamos adicionar o reconhecimento de atividade.
Resumo
Nesta etapa, você aprendeu sobre:
- Configuração geral do codelab.
- Os conceitos básicos do nosso app.
- Como implantar o app.
3. Revisar a biblioteca e adicionar permissão ao manifesto
Para usar a API Transition no seu app, você precisa declarar uma dependência à API Google Location and Activity Recognition e especificar a permissão com.google.android.gms.permission.ACTIVITY_RECOGNITION no manifesto do app.
- Pesquise TODO: Review play services library required for reconhecimento de atividade no arquivo build.gradle. Não há ações nessa etapa (etapa 1). Basta analisar a dependência declarada de que precisamos. Ele vai ter esta aparência:
// TODO: Review play services library required for activity recognition.
implementation 'com.google.android.gms:play-services-location:19.0.1'
- No módulo
base, pesquise TODO: Add both activity recognition permissions to the manifest no arquivoAndroidManifest.xmle adicione o código abaixo ao elemento<manifest>.
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Agora, seu código ficará assim:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
...
</manifest>
Como é possível ver nos comentários, é necessário adicionar uma segunda permissão para o Android 10. Isso é necessário para a permissão de execução adicionada na versão 29 da API.
Pronto! Agora seu app é compatível com reconhecimento de atividade. Basta adicionar o código para receber as informações.
Executar app
Execute o app no Android Studio. Ele deve ter exatamente a mesma aparência. Ainda não adicionamos nenhum código para rastrear transições. Isso será feito na próxima seção.
4. Verificar/solicitar permissões de execução no Android
Embora tenhamos permissão para a versão 28 e anteriores da API, precisamos oferecer suporte a permissões de tempo de execução na versão 29 e posteriores:
- No
MainActivity.java, vamos verificar se o usuário está no Android 10 (29) ou em uma versão mais recente e, se estiver, vamos verificar as permissões de reconhecimento de atividade. - Se as permissões não forem concedidas, vamos enviar o usuário para uma tela de apresentação (
PermissionRationalActivity.java) explicando por que o app precisa da permissão e permitindo que ele a aprove.
Revisar o código que verifica a versão do Android
No módulo base, pesquise TODO: Review check for devices with Android 10 (29+) em MainActivity.java. Você verá este snippet de código.
Não há ações para esta seção.
// TODO: Review check for devices with Android 10 (29+).
private boolean runningQOrLater =
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;
Como dito antes, você precisa de aprovação para a permissão de execução android.permission.ACTIVITY_RECOGNITION no Android 10 e versões mais recentes. Usamos essa verificação simples para decidir se precisamos ou não verificar as permissões de execução.
Revisar a verificação de permissão de execução para reconhecimento de atividade, se necessário
No módulo base, pesquise TODO: Review permission check for 29+ em MainActivity.java. Você verá este snippet de código.
Não há ações para esta seção.
// TODO: Review permission check for 29+.
if (runningQOrLater) {
return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACTIVITY_RECOGNITION
);
} else {
return true;
}
Usamos a variável criada na etapa anterior para verificar se precisamos conferir as permissões de execução.
Para Q e versões mais recentes, verificamos e retornamos o resultado da permissão de execução. Isso faz parte de um método maior chamado activityRecognitionPermissionApproved(), que informa ao desenvolvedor em uma chamada simples se precisamos solicitar uma permissão ou não.
Solicitar permissões de execução e ativar/desativar transições de reconhecimento de atividade
No módulo base, pesquise TODO: Enable/Disable Monitoramento de atividade and ask for permissions if needed em MainActivity.java. Adicione o código abaixo após o comentário.
// TODO: Enable/Disable activity tracking and ask for permissions if needed.
if (activityRecognitionPermissionApproved()) {
if (activityTrackingEnabled) {
disableActivityTransitions();
} else {
enableActivityTransitions();
}
} else {
// Request permission and start activity for result. If the permission is approved, we
// want to make sure we start activity recognition tracking.
Intent startIntent = new Intent(this, PermissionRationalActivity.class);
startActivityForResult(startIntent, 0);
}
Aqui perguntamos se o reconhecimento de atividade foi aprovado. Se for e o reconhecimento de atividade já estiver ativado, vamos desativá-lo. Caso contrário, vamos ativar.
Quando a permissão não é aprovada, enviamos o usuário para a atividade na tela de apresentação, que explica por que precisamos da permissão, e permitimos que ele a ative.
Analisar o código de solicitação de permissão
No módulo base, pesquise TODO: Review solicitação de permissão para reconhecimento de atividade em PermissionRationalActivity.java. Você verá este snippet de código.
Não há ações para esta seção.
// TODO: Review permission request for activity recognition.
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
PERMISSION_REQUEST_ACTIVITY_RECOGNITION)
Essa é a parte mais importante da atividade e a parte a ser revisada. O código aciona a solicitação de permissão quando o usuário pede.
Fora isso, a classe PermissionRationalActivity.java mostra uma justificativa de por que o usuário precisa aprovar a permissão de reconhecimento de atividade (prática recomendada). O usuário pode clicar no botão Não, obrigado ou em Continuar (que aciona o código acima).
Confira o arquivo se quiser saber mais.
5. Registrar/cancelar o registro do receptor para transições de atividades
Antes de configurar o código de reconhecimento de atividades, queremos garantir que nossa atividade possa processar ações de transição geradas pelo sistema.
Criar um BroadcastReceiver para a transição
No módulo base, pesquise TODO: Create a BroadcastReceiver to listen for activity transitions em MainActivity.java. Cole o snippet abaixo.
// TODO: Create a BroadcastReceiver to listen for activity transitions.
// The receiver listens for the PendingIntent above that is triggered by the system when an
// activity transition occurs.
mTransitionsReceiver = new TransitionsReceiver();
Registrar um BroadcastReceiver para a transição
No módulo base, pesquise TODO: Register a BroadcastReceiver to listen for activity transitions em MainActivity.java. Ele está em onStart(). Cole o snippet abaixo.
// TODO: Register a BroadcastReceiver to listen for activity transitions.
registerReceiver(mTransitionsReceiver, new IntentFilter(TRANSITIONS_RECEIVER_ACTION));
Agora temos uma maneira de receber atualizações quando as transições de atividade são geradas pelo PendingIntent.
Cancelar o registro do BroadcastReceiver
No módulo base, pesquise Unregister activity transition receiver when user leaves the app em MainActivity.java. Ele está em onStop(). Cole o snippet abaixo.
// TODO: Unregister activity transition receiver when user leaves the app.
unregisterReceiver(mTransitionsReceiver);
A prática recomendada é cancelar o registro de um receptor quando o Activity está sendo desligado.
6. Configurar transições de atividade e solicitar atualizações
Para começar a receber atualizações sobre transições de atividade, implemente:
- Um objeto ActivityTransitionRequest que especifica o tipo de atividade e a transição.
- Um callback PendingIntent em que seu app recebe notificações. Para mais informações, consulte Como usar um intent pendente.
Criar uma lista de ActivityTransitions a serem seguidas
Para criar o objeto ActivityTransitionRequest, crie uma lista de objetos ActivityTransition, que representam a transição que você quer rastrear. Um objeto ActivityTransition inclui os seguintes dados:
- Um tipo de atividade, representado pela classe DetectedActivity. A API Transition é compatível com as seguintes atividades:
- Um tipo de transição, representado pela classe ActivityTransition. Os tipos de transição são:
No módulo base, pesquise TODO: Add activity transitions to track em MainActivity.java. Adicione o código abaixo após o comentário.
// TODO: Add activity transitions to track.
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
activityTransitionList.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
Esse código adiciona as transições que queremos rastrear a uma lista anteriormente vazia.
Criar uma PendingIntent
Como mencionado anteriormente, precisamos de um PendingIntent se quisermos receber alertas sobre mudanças no nosso ActivityTransitionRequest. Portanto, antes de configurar o ActivityTransitionRequest, precisamos criar um PendingIntent.
No módulo base, pesquise TODO: Initialize PendingIntent that will be triggered when a activity transition occurs em MainActivity.java. Adicione o código abaixo após o comentário.
// TODO: Initialize PendingIntent that will be triggered when a activity transition occurs.
Intent intent = new Intent(TRANSITIONS_RECEIVER_ACTION);
mActivityTransitionsPendingIntent =
PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Agora temos um PendingIntent que pode ser acionado quando uma das ActivityTransition ocorre.
Criar um ActivityTransitionRequest e solicitar atualizações
Você pode criar um objeto ActivityTransitionRequest transmitindo a lista de ActivityTransitions para a classe ActivityTransitionRequest.
No módulo base, pesquise Create request and listen for activity changes em MainActivity.java. Adicione o código abaixo após o comentário.
// TODO: Create request and listen for activity changes.
ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);
// Register for Transitions Updates.
Task<Void> task =
ActivityRecognition.getClient(this)
.requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);
task.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
activityTrackingEnabled = true;
printToScreen("Transitions Api was successfully registered.");
}
});
task.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions Api could NOT be registered: " + e);
Log.e(TAG, "Transitions Api could NOT be registered: " + e);
}
});
Vamos analisar o código. Primeiro, criamos um ActivityTransitionRequest na nossa lista de transições de atividade.
ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);
Em seguida, registramos as atualizações de transição de atividade transmitindo sua instância de ActivityTransitionRequest e o objeto PendingIntent que criamos na última etapa para o método requestActivityTransitionUpdates(). O método requestActivityTransitionUpdates() retorna um objeto Task que você pode verificar quanto a sucesso ou falha, conforme mostrado no próximo bloco de código:
// Register for Transitions Updates.
Task<Void> task =
ActivityRecognition.getClient(this)
.requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);
task.addOnSuccessListener(
new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
activityTrackingEnabled = true;
printToScreen("Transitions Api was successfully registered.");
}
});
task.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions Api could NOT be registered: " + e);
Log.e(TAG, "Transitions Api could NOT be registered: " + e);
}
});
Depois de se inscrever para receber atualizações de transição de atividades, o app recebe notificações na PendingIntent registrada. Também definimos uma variável que indica se o rastreamento de atividades está ativado para saber se é necessário desativar/ativar caso o usuário clique no botão novamente.
Remover atualizações quando o app for fechado
É importante remover as atualizações de transição quando o app está sendo fechado.
No módulo base, pesquise Stop listening for activity changes em MainActivity.java. Adicione o código abaixo após o comentário.
// TODO: Stop listening for activity changes.
ActivityRecognition.getClient(this).removeActivityTransitionUpdates(mActivityTransitionsPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
activityTrackingEnabled = false;
printToScreen("Transitions successfully unregistered.");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
printToScreen("Transitions could not be unregistered: " + e);
Log.e(TAG,"Transitions could not be unregistered: " + e);
}
});
Agora precisamos chamar o método que contém o código acima quando o app está sendo encerrado.
No módulo base, pesquise TODO: Disable activity transitions when user leaves the app em MainActivity.java em onPause(). Adicione o código abaixo após o comentário.
// TODO: Disable activity transitions when user leaves the app.
if (activityTrackingEnabled) {
disableActivityTransitions();
}
É isso para acompanhar as mudanças nas transições de atividade. Agora só precisamos processar as atualizações.
7. Como processar eventos
Quando a transição da atividade solicitada ocorre, seu app recebe um callback de Intent. Um objeto ActivityTransitionResult pode ser extraído da intent, que inclui uma lista de objetos ActivityTransitionEvent. Os eventos são organizados em ordem cronológica. Por exemplo, se um app solicita o tipo de atividade IN_VEHICLE nas transições ACTIVITY_TRANSITION_ENTER e ACTIVITY_TRANSITION_EXIT, ele recebe um objeto ActivityTransitionEvent quando o usuário começa a dirigir e outro quando ele faz a transição para qualquer outra atividade.
Vamos adicionar o código para lidar com esses eventos.
No módulo base, pesquise TODO: Extract activity transition information from listener em MainActivity.java no onReceive() do BroadcastReceiver que criamos anteriormente. Adicione o código abaixo após o comentário.
// TODO: Extract activity transition information from listener.
if (ActivityTransitionResult.hasResult(intent)) {
ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
for (ActivityTransitionEvent event : result.getTransitionEvents()) {
String info = "Transition: " + toActivityString(event.getActivityType()) +
" (" + toTransitionType(event.getTransitionType()) + ")" + " " +
new SimpleDateFormat("HH:mm:ss", Locale.US).format(new Date());
printToScreen(info);
}
}
Isso vai converter as informações em um String e imprimir na tela.
É isso. Está tudo pronto! Tente executar o app.
OBSERVAÇÃO IMPORTANTE: é difícil reproduzir mudanças de atividade no emulador. Por isso, recomendamos usar um dispositivo físico.
Você poderá monitorar as mudanças na atividade.
Para ter os melhores resultados, instale o app em um dispositivo físico e caminhe por aí. :)
8. Revisar o código
Você criou um app simples que rastreia transições de atividade e as lista na tela.
Você pode ler o código completo para revisar o que foi feito e entender melhor como ele funciona.