Use a API do Instrument Cluster (uma API do Android) para exibir aplicativos de navegação, incluindo o Google Maps, em uma exibição secundária em um carro, como atrás do volante no painel de instrumentos. Esta página descreve como criar um serviço para controlar essa exibição secundária e, em seguida, integrar o serviço ao
para que os aplicativos de navegação possam exibir uma interface do usuário.CarService
Terminologia
Os seguintes termos são usados nesta página:
Prazo | Descrição |
---|---|
CarInstrumentClusterManager | Um CarManager que permite que aplicativos externos iniciem uma atividade no Instrument Cluster e recebam retornos de chamada quando o Instrument Cluster estiver pronto para exibir atividades. |
Car Manager | Classe base de todos os gerenciadores usados por aplicativos externos para interagir com serviços específicos de carros implementados por CarService . |
CarService | Serviço da plataforma Android que fornece comunicação entre aplicativos externos (incluindo Google Maps) e recursos específicos do carro, como acesso ao Instrument Cluster. |
Destino | O destino final para o qual o veículo irá navegar. |
ETA | Hora prevista de chegada ao destino. |
Unidade principal (HU) | Unidade computacional primária embutida em um carro. A HU executa todo o código Android e está conectada ao display central do carro. |
Conjunto de Instrumentos | Display secundário localizado atrás do volante e entre os instrumentos do carro. Pode ser uma unidade computacional independente conectada à HU através da rede interna do carro (barramento CAN) ou um display secundário conectado à HU. |
InstrumentClusterRenderingService | Classe base para o serviço usado para fazer a interface com o display do Instrument Cluster. Os OEMs devem fornecer uma extensão dessa classe que interaja com o hardware específico do OEM. |
App KitchenSink | Aplicativo de teste incluído no Android Automotive. |
Rota | Um caminho específico ao longo do qual um veículo navega para chegar a um destino. |
serviço singleton | Um serviço Android com o atributo android:singleUser . A qualquer momento, no máximo uma instância do serviço é executada no sistema Android. |
Pré-requisitos
Para desenvolver a integração, certifique-se de ter estes elementos:
- Ambiente de desenvolvimento Android. Para configurar o ambiente de desenvolvimento do Android, consulte Requisitos de compilação .
- Baixe o código-fonte do Android. Obtenha a versão mais recente do código-fonte do Android na ramificação pi-car-release (ou posterior) em https://android.googlesource.com .
- Unidade Principal (HU). Um dispositivo Android capaz de executar o Android 9 (ou posterior). Este dispositivo deve ter seu próprio display e ser capaz de piscar o display com novas compilações do Android.
- O conjunto de instrumentos é um dos seguintes:
- Visor secundário físico conectado à HU. Se o hardware e o kernel do dispositivo suportarem o gerenciamento de vários monitores.
- Unidade independente. Qualquer unidade computacional conectada à HU por meio de uma conexão de rede, capaz de receber e exibir um fluxo de vídeo em seu próprio monitor.
- Exibição emulada. Durante o desenvolvimento, você pode usar um destes ambientes emulados:
- Displays secundários simulados. Para habilitar uma exibição secundária simulada em qualquer distribuição Android AOSP, vá para as configurações de Opções do desenvolvedor no aplicativo do sistema Configurações e selecione Simular exibições secundárias. Essa configuração é equivalente a anexar um monitor secundário físico, com a limitação de que esse monitor é sobreposto ao monitor principal.
- Painel de instrumentos emulado. O emulador do Android incluído no Android Automotive fornece uma opção para exibir um painel de instrumentos com o serviço ClusterRenderingService conectado ao monitor secundário. emulador _qemu-pipes . O serviço ClusterRenderingService está conectado ao monitor secundário.
implementação de conjunto de instrumentos de referência para se conectar a este monitor externo emulado.
Arquitetura de integração
Componentes de integração
Qualquer integração da API do Instrument Cluster consiste nestes três componentes:
-
CarService
- Aplicativos de navegação
- Serviço de cluster de instrumentos OEM
Serviço automotivo
CarService
faz a mediação entre os aplicativos de navegação e o carro, garantindo que apenas um aplicativo de navegação esteja ativo a qualquer momento e apenas os aplicativos com a permissão android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
possam enviar dados para o carro.
CarService
inicializa todos os serviços específicos do carro e fornece acesso a esses serviços por meio de uma série de gerenciadores. Para interagir com os serviços, os aplicativos rodando no carro podem acessar esses gerenciadores.
Para a implementação do cluster de instrumentos, os OEMs automotivos devem criar uma implementação personalizada de InstrumentClusterRendererService e atualizar se o serviço ClusterRenderingService está conectado ao monitor secundário.
Ao renderizar um Instrument Cluster, durante o processo de inicialização, o CarService
lê a chave InstrumentClusterRendererService
do serviço ClusterRenderingService conectado ao monitor secundário. para localizar uma implementação de InstrumentClusterService
. No AOSP, esta entrada aponta para o serviço de renderização de implementação de cluster de amostra da API de estado de navegação:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
O serviço referido nesta entrada é inicializado e vinculado a CarService
. Quando aplicativos de navegação, como o Google Maps, solicitam um CarInstrumentClusterManager
, CarService
fornece um gerenciador que atualiza o estado do Instrument Cluster a partir do InstrumentClusterRenderingService
vinculado. (Neste caso, vinculado refere-se a Android Services .)
Serviço de Cluster de Instrumentos
Os OEMs devem criar um Android Package (APK) que contenha uma subclasse do serviço ClusterRenderingService conectado ao monitor secundário. O serviço ClusterRenderingService está conectado ao monitor secundário. para uma amostra.
Esta classe serve a dois propósitos:
- Fornece uma interface Android e o dispositivo de renderização Instrument Cluster (o objetivo desta página).
- Recebe e processa atualizações de estado de navegação, como orientação de navegação passo a passo.
Para a primeira finalidade, as implementações OEM de InstrumentClusterRendererService
devem inicializar a exibição secundária usada para renderizar informações nas telas na cabine do carro e comunicar essas informações ao CarService
chamando os métodos InstrumentClusterRendererService.setClusterActivityOptions()
e InstrumentClusterRendererService.setClusterActivityState()
.
Para a segunda função, o serviço Instrument Cluster deve fornecer uma implementação do serviço ClusterRenderingService conectado ao monitor secundário. interface que recebe eventos de atualização de status de navegação, que são codificados como um eventType
e dados de eventos codificados em um pacote.
sequência de integração
O diagrama a seguir ilustra a implementação de um estado de navegação que renderiza atualizações:
Nesta ilustração, as cores denotam o seguinte:
- Amarelo.
CarService
eCarNavigationStatusManager
fornecidos pela plataforma Android. Para saber mais, consulte Carro e CAR_NAVIGATION_SERVICE . - Ciano.
InstrumentClusterRendererService
implementado pelo OEM. - Roxo. O aplicativo de navegação implementado pelo Google e por desenvolvedores terceirizados.
- Verde.
CarAppFocusManager
. Para saber mais, consulte Usando a API CarAppFocusManager abaixo e CarAppFocusManager .
O fluxo de informações do Estado de Navegação segue esta sequência:
-
CarService
inicializa oInstrumentClusterRenderingService
. - Durante a inicialização, o
InstrumentClusterRenderingService
atualizaCarService
com:- Propriedades de exibição do agrupamento de instrumentos, como limites não obscuros (consulte mais detalhes sobre limites não obscuros posteriormente).
- Opções de atividade necessárias para iniciar atividades dentro da tela do Instrument Cluster (veja mais detalhes em ActivityOptions .
- Um aplicativo de navegação (como o Google Maps para Android Automotive ou qualquer aplicativo de mapas com as permissões necessárias):
- Obtém um
CarAppFocusManager
usando a classe Car de car-lib. - Antes do início das rotas passo a passo, chame
CarAppFocusManager.requestFocus()
para passarCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
como o parâmetroappType
.
- Obtém um
-
CarAppFocusManager
comunica essa solicitação aoCarService
. Se concedido,CarService
inspeciona o pacote do aplicativo de navegação e localiza uma atividade marcada com a categoriaandroid.car.cluster.NAVIGATION
. - Se encontrado, o aplicativo de navegação usa as
ActivityOptions
relatadas peloInstrumentClusterRenderingService
para iniciar a atividade e inclui as propriedades de exibição do Instrument Cluster como extras na intenção.
Integrando a API
A implementação InstrumentClusterRenderingService
deve:
- Seja designado como um serviço singleton adicionando o seguinte valor ao AndroidManifest.xml. Isso é necessário para garantir que uma única cópia do serviço Instrument Cluster seja executada, mesmo durante a inicialização e troca de usuário:
android:singleUser="true"
- Tenha a permissão do sistema
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Isso garante que apenas o serviço de renderização do Instrument Cluster incluído como parte da imagem do sistema Android seja vinculado aoCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementando InstrumentClusterRenderingService
Para construir o serviço:
- Escreva uma classe que se estende do serviço ClusterRenderingService conectada à exibição secundária. e adicione uma entrada correspondente ao seu arquivo
- Durante
onCreate()
, use este serviço para inicializar a comunicação com o hardware de renderização. As opções incluem:- Determine a exibição secundária a ser usada para o Instrument Cluster.
- Crie um display virtual para que o aplicativo Instrument Cluster renderize e transmita a imagem renderizada para uma unidade externa (usando um formato de streaming de vídeo, como H.264).
- Quando o display indicado acima estiver pronto, este serviço deve chamar
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
para definir asActivityOptions
exatas que devem ser usadas para exibir uma Activity no Instrument Cluster. Use estes parâmetros:- categoria. O serviço ClusterRenderingService está conectado ao monitor secundário.
-
ActivityOptions.
Uma instânciaActivityOptions
que pode ser usada para iniciar uma Activity no Instrument Cluster. Por exemplo, da amostra de implementação do Instrument Cluster no AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Quando o Instrument Cluster estiver pronto para exibir atividades, esse serviço deverá invocar
InstrumentClusterRenderingService#setClusterActivityState()
. Use estes parâmetros:- O serviço ClusterRenderingService
category
está conectado ao monitor secundário. - O pacote
state
gerado com o serviço ClusterRenderingService está conectado ao monitor secundário. Certifique-se de fornecer os seguintes dados: -
visible
Especifica o Instrument Cluster como visível e pronto para exibir o conteúdo. -
unobscuredBounds
Um retângulo que define a área dentro da exibição do Instrument Cluster na qual é seguro exibir o conteúdo. Por exemplo, áreas cobertas por mostradores e medidores.
- O serviço ClusterRenderingService
- Substitua o método
Service#dump()
e relate informações de status úteis para depuração (consulte dumpsys para obter mais informações).
AndroidManifest.xml
. Essa classe controla a exibição do Cluster de instrumentos e pode ( opcionalmente ) renderizar dados da API do estado de navegação.Exemplo de implementação de InstrumentClusterRenderingService
O exemplo a seguir descreve uma implementação de InstrumentClusterRenderingService
, que cria um VirtualDisplay
para apresentar o conteúdo do Instrument Cluster em uma exibição física remota.
Alternativamente, este código pode passar o displayId
de um display secundário físico conectado à HU, se houver algum disponível.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display that will be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
Usando a API CarAppFocusManager
A API CarAppFocusManager fornece um método chamado getAppTypeOwner()
, que permite que o serviço de cluster escrito por OEMs saiba qual aplicativo de navegação tem o foco de navegação a qualquer momento. Os OEMs podem usar o método CarAppFocusManager#addFocusListener()
existente e, em seguida, usar getAppTypeOwner()
para saber qual aplicativo tem o foco. Com essas informações, os OEMs podem:
- Alterne a atividade mostrada no cluster para a atividade de cluster fornecida pelo aplicativo de navegação que mantém o foco.
- Pode detectar se o aplicativo de navegação focado tem uma atividade de cluster ou não. Se o aplicativo de navegação focado não tiver uma atividade de cluster (ou se tal atividade estiver desativada), os OEMs podem enviar esse sinal para o carro DIM para que a faceta de navegação do cluster seja totalmente ignorada.
Use CarAppFocusManager
para definir e ouvir o foco do aplicativo atual, como navegação ativa ou um comando de voz. Normalmente, apenas uma instância desse aplicativo está sendo executada ativamente (ou focada) no sistema.
Use o método CarAppFocusManager#addFocusListener(..)
para ouvir as alterações de foco do aplicativo:
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
Use o método CarAppFocusManager#getAppTypeOwner(..)
para recuperar os nomes de pacote do proprietário atual de um determinado tipo de aplicativo que está em foco. Este método pode retornar mais de um nome de pacote se o proprietário atual usar o recurso android:sharedUserId
.
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation application has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
Apêndice: Usando o aplicativo de amostra
O AOSP fornece um aplicativo de amostra que implementa a API de estado de navegação.
Para executar este aplicativo de exemplo:
- Crie e atualize o Android Auto em uma HU compatível. Use as instruções de construção e flash do Android específicas para o seu dispositivo. Para obter instruções, consulte Usando placas de referência .
- Conecte um monitor secundário físico à HU (se compatível) ou ligue a HU secundária virtual:
- Selecione Modo de desenvolvedor no aplicativo Configurações.
- Vá para Configurações > Sistema > Avançado > Opções do desenvolvedor > Simular exibições secundárias .
- Reinicie a HU. O serviço ClusterRenderingService está conectado ao monitor secundário.
- Para iniciar o aplicativo KitchenSink:
- Abra a gaveta.
- Ir para Inst. Cluster .
- Clique em INICIAR METADADOS .
KitchenSink solicita o foco NAVIGATION, que instrui o serviço DirectRenderingCluster
a exibir uma interface de usuário simulada no Instrument Cluster.