Esta seção detalha os diferentes recursos da biblioteca que você pode usar para implementar a funcionalidade do seu app de navegação passo a passo.
Declarar compatibilidade com navegação no manifesto
Seu app de navegação precisa declarar a categoria do app para carros
androidx.car.app.category.NAVIGATION
no filtro de intent de
CarAppService
:
<application>
...
<service
...
android:name=".MyNavigationCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION"/>
</intent-filter>
</service>
...
<application>
Compatibilidade com intents de navegação
Para ter suporte a intents de navegação no seu app, incluindo aquelas provenientes
do Google Assistente usando uma consulta por voz, o app precisa processar a
intent CarContext.ACTION_NAVIGATE
nos métodos Session.onCreateScreen
e
Session.onNewIntent
.
Consulte a documentação de CarContext.startCarApp
para ver detalhes sobre o formato da intent.
Acessar os modelos de navegação
Os apps de navegação podem acessar os seguintes modelos projetados especificamente para apps de navegação. Todos estes modelos exibem uma superfície em segundo plano que o app pode acessar para desenhar o mapa, junto com outras informações fornecidas pelo app que variam de acordo com o modelo.
NavigationTemplate
: exibe o mapa com uma mensagem informativa opcional ou rotas e estimativas de viagem durante a navegação ativa.PlaceListNavigationTemplate
: exibe uma lista de lugares que podem ter marcadores correspondentes desenhados no mapa.RoutePreviewNavigationTemplate
: exibe uma lista de rotas, em que uma pode ser selecionada e destacada no mapa.
Para ver mais detalhes sobre como projetar a interface do usuário do seu app de navegação usando esses modelos, consulte as Diretrizes de design da biblioteca Android for Cars App.
Para ter acesso aos modelos de navegação, seu app precisa declarar
a permissão androidx.car.app.NAVIGATION_TEMPLATES
no
AndroidManifest.xml
:
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
Desenhar o mapa
Os aplicativos de navegação podem acessar uma Surface
para desenhar o mapa nos modelos relevantes.
Um objeto SurfaceContainer
pode
ser acessado ao definir uma instância de SurfaceCallback
para o serviço de carro
AppManager
:
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
O SurfaceCallback
fornece um
callback quando o SurfaceContainer
está disponível com outros callbacks quando as propriedades da Surface
mudam.
Para ter acesso à superfície, seu app precisa declarar a
permissão androidx.car.app.ACCESS_SURFACE
no AndroidManifest.xml
:
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE"/>
Área visível do mapa
O host pode desenhar elementos da interface do usuário para diferentes modelos na parte
superior do mapa. O host comunicará a área que certamente não estará fechada
e que ficará totalmente visível para o usuário chamando
SurfaceCallback.onVisibleAreaChanged
.
Além disso, para minimizar o número de mudanças, o host também chamará o
método SurfaceCallback.onStableAreaChanged
com o maior retângulo que será visível com base no modelo
atual.
Por exemplo, quando um app de navegação está usando o NavigationTemplate
com uma faixa de ação na parte superior, essa faixa pode ficar oculta quando o usuário não
está interagindo com a tela há algum tempo, para criar mais espaço para o mapa. Nesse
caso, haverá um callback para onStableAreaChanged
e
onVisibleAreaChanged
com o mesmo retângulo. Quando a faixa de ação estiver oculta,
somente onVisibleAreaChanged
será chamado com a área maior. Se o usuário
interagir com a tela, novamente apenas onVisibleAreaChanged
será chamado com
o primeiro retângulo.
Modo escuro
Os apps de navegação precisam redesenhar o mapa na instância de Surface
com as
cores escuras adequadas quando o host determina que as condições as justificam, conforme
descrito nas Diretrizes de qualidade de apps do Android Auto.
Para decidir se você precisa desenhar um mapa escuro, use o
método
CarContext.isDarkMode
. Você vai receber uma chamada para
Session.onCarConfigurationChanged
sempre que o status do modo escuro for alterado.
Metadados de navegação
Os aplicativos de navegação precisam comunicar outros metadados de navegação ao host. O host usa as informações para fornecer dados à unidade principal do veículo e para impedir que aplicativos de navegação entrem em conflito com os recursos compartilhados.
Os metadados de navegação são fornecidos pelo serviço de carro NavigationManager
,
acessível no CarContext
:
Kotlin
val navigationManager = carContext.getCarService(NavigationManager::class.java)
Java
NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);
Iniciar, encerrar e interromper a navegação
Para que o host gerencie vários apps de navegação, notificações de roteamento
e dados de cluster do veículo, ele precisa estar ciente do estado atual da
navegação. Quando um usuário inicia a navegação, o app precisa chamar
NavigationManager.navigationStarted
.
Da mesma forma, quando a navegação termina, por exemplo, quando o usuário chega ao
destino ou quando ele cancela a navegação, o app precisa chamar
NavigationManager.navigationEnded
.
Chame NavigationManager.navigationEnded
apenas quando o usuário terminar a navegação. Por exemplo, se você precisar recalcular
a rota no meio de uma viagem, use
Trip.Builder.setLoading(true)
.
Ocasionalmente, o host precisará de um app para interromper a navegação e chamar
stopNavigation
em um objeto NavigationManagerListener
fornecido pelo seu aplicativo pelo
NavigationManager.setListener
. O app precisa parar de emitir
informações da próxima curva na exibição do cluster, nas notificações de navegação e na orientação por voz.
Informações da viagem
Durante a navegação ativa, o app precisa chamar NavigationManager.updateTrip
.
As informações fornecidas nessa chamada serão usadas no cluster do veículo e
nos avisos na tela. Nem todas as informações podem ser mostradas para o usuário, dependendo do
veículo em questão. Por exemplo, a Desktop Head Unit mostra
a Step
adicionada à
Trip
, mas não mostra
a informação do
Destination
.
Para testar se as informações estão chegando ao cluster, a ferramenta Desktop Head
Unit (DHU) pode ser configurada para mostrar uma exibição de cluster simples. Crie um
arquivo cluster.ini
com o seguinte conteúdo:
[general]
instrumentcluster = true
É possível invocar a DHU com um parâmetro de linha de comando adicional:
dhu -c cluster.ini
Notificações passo a passo
As instruções de navegação passo a passo (TBT, sigla em inglês) podem ser fornecidas com uma notificação de navegação atualizada com frequência. Para ser tratada como uma notificação de navegação na tela do carro, o builder da notificação precisa fazer o seguinte:
- Marcar a notificação como em andamento com o
método
NotificationCompat.Builder.setOngoing
- Definir a categoria da notificação como
Notification.CATEGORY_NAVIGATION
- Estender a notificação com um
CarAppExtender
Uma notificação de navegação será exibida no widget de coluna na parte inferior da
tela do carro. Se o nível de importância da notificação estiver definido como
IMPORTANCE_HIGH
, ele também será exibido como uma notificação de alerta (HUN, sigla em inglês).
Se a importância não estiver definida com o método CarAppExtender.Builder.setImportance
,
a importância do canal de notificação
será usada.
O app pode definir uma PendingIntent
no
CarAppExtender
que
será enviada ao app quando o usuário tocar na HUN ou no widget de coluna.
Se NotificationCompat.Builder.setOnlyAlertOnce
for chamado com o valor true
, uma notificação de alta importância será emitida apenas
uma vez na HUN.
O snippet a seguir mostra como criar uma notificação de navegação:
Kotlin
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) ... .setOnlyAlertOnce(true) .setOngoing(true) .setCategory(NotificationCompat.CATEGORY_NAVIGATION) .extend( CarAppExtender.Builder() .setContentTitle(carScreenTitle) ... .setContentIntent( PendingIntent.getBroadcast( context, ACTION_OPEN_APP.hashCode(), Intent(ACTION_OPEN_APP).setComponent( ComponentName(context, MyNotificationReceiver::class.java)), 0)) .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH) .build()) .build()
Java
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) ... .setOnlyAlertOnce(true) .setOngoing(true) .setCategory(NotificationCompat.CATEGORY_NAVIGATION) .extend( new CarAppExtender.Builder() .setContentTitle(carScreenTitle) ... .setContentIntent( PendingIntent.getBroadcast( context, ACTION_OPEN_APP.hashCode(), new Intent(ACTION_OPEN_APP).setComponent( new ComponentName(context, MyNotificationReceiver.class)), 0)) .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH) .build()) .build();
Diretrizes para notificações passo a passo
Os apps de navegação precisam atualizar a notificação TBT regularmente com mudanças
de distância, o que atualiza o widget de coluna e mostra a notificação apenas como HUN.
Os apps podem controlar o comportamento da HUN definindo a importância da notificação com
o método
CarAppExtender.Builder.setImportance
. Definir a importância como IMPORTANCE_HIGH
vai mostrar uma HUN, enquanto a definição
com qualquer outro valor vai atualizar apenas o widget de coluna.
Orientação por voz
Para reproduzir a orientação de navegação nos alto-falantes do carro, seu app precisa solicitar
seleção de áudio. Como parte da
AudioFocusRequest
, você precisa definir
o uso como AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
. Defina também
o ganho de seleção como AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
.
Simular a navegação
Para verificar a funcionalidade de navegação do seu app ao enviá-lo à
Google Play Store, o app precisa implementar o
callback
NavigationManagerCallback.onAutoDriveEnabled
. Quando esse callback é chamado, o app precisa simular o trajeto até o
destino escolhido quando o usuário inicia a navegação. O app pode sair desse
modo sempre que o ciclo de vida da Session
atual atingir o estado
Lifecycle.Event.ON_DESTROY
.
Teste se a implementação de onAutoDriveEnabled
é chamada
executando o seguinte em uma linha de comando:
adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE
Exemplo:
adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE
App padrão de navegação para carro
No Android Auto, o app padrão de navegação para carro corresponde ao último app de navegação que o usuário iniciou. Esse é o app que, por exemplo, recebe as intents de navegação quando o usuário invoca comandos de navegação pelo assistente ou quando outro app envia uma intent para iniciar a navegação.
Permitir que os usuários interajam com seu mapa
A partir do nível 2 da API Car App, você pode aplicar zoom ao seu mapa ou movimentá-lo no
NavigationTemplate
para permitir que os usuários vejam diferentes partes do mapa.
Métodos de SurfaceCallback
O SurfaceCallback
tem três métodos de callback que permitem adicionar interatividade de mapas ao
NavigationTemplate
: onScale
,
onScroll
e
onFling
.
Consulte a tabela abaixo para saber como esses callbacks estão relacionados às interações do usuário.
Interação | Método SurfaceCallback |
---|---|
Fazer gesto de pinça (zoom) | onScale |
Arrastar com um único toque | onScroll |
Deslizar rapidamente com um único toque | onFling |
Tocar duas vezes | onScale (com um fator de escalonamento determinado pelo host do modelo) |
Alerta giratório no modo Movimentar | onScroll (com um fator de distância determinado pelo host do modelo) |
Faixa de ações no mapa
O NavigationTemplate
pode ter uma faixa de ações no mapa para ações relacionadas
ao mapa, por exemplo, aumentar e diminuir o zoom, recentralizar, exibir uma bússola ou qualquer outra ação que é
possível exibir no app. A faixa de ações no mapa pode ter até quatro botões somente de
ícones que podem ser atualizados sem afetar a profundidade da tarefa. Assim como a
faixa de ações, a faixa de ações no mapa fica oculta no estado inativo e reaparece no
estado ativo.
Para receber callbacks de interatividade no mapa, adicione um
botão Action.PAN
à faixa de ações no mapa. Se o app omitir o botão Action.PAN
na faixa de ações, você não receberá entradas dos usuários dos métodos
SurfaceCallback
, e o host fechará qualquer modo de movimentação
ativado anteriormente. Quando o usuário pressiona o botão de movimentação, o host entra
no modo de movimentação. Em uma tela touchscreen, o botão de movimentação não será exibido.
Modo de movimentação
No modo de movimentação, o host do modelo converte a entrada do usuário de
dispositivos de entrada sem toque, como controladores giratórios e touchpads, em métodos
SurfaceCallback
adequados. Responda à ação do usuário para entrar ou sair do modo de movimentação
com o
método setPanModeListener
no NavigationTemplate
Builder
. O host pode ocultar outros componentes
de IU no modelo enquanto o usuário está no modo de movimentação.
Área estável
A área estável é atualizada entre os estados ativo e inativo. Seu app precisa desenhar informações relacionadas à condução, como velocidade, limite de velocidade ou avisos de rua, dependendo do tamanho da área estável, para que informações importantes no mapa não sejam escondidas pela faixa de ações no mapa.