Use a API Instrument Cluster (uma API do Android) para mostrar apps de navegação,
incluindo o Google Maps, em uma tela secundária de um carro, como atrás do
no painel de instrumentos. Nesta página, descrevemos como criar um
para controlar essa tela secundária e integrar o serviço com
CarService
para que os apps de navegação possam mostrar uma
de uma ferramenta de visualização.
Terminologia
Os termos a seguir são usados nesta página.
CarManager
que permite que apps externos iniciem uma atividade em
o cluster de instrumentos e receba callbacks quando ele estiver pronto para ser exibido
atividades.android:singleUser
. Em
no máximo uma instância do serviço é executada no sistema Android a qualquer momento.Pré-requisitos
Antes de continuar, confira se você tem estes elementos:
- Ambiente de desenvolvimento do Android. Para configurar o Android ambiente de desenvolvimento, consulte Requisitos de build.
- Faça o download do código-fonte do Android. Obtenha a versão mais recente do o código-fonte do Android da ramificação pi-car-release (ou posterior), em https://android.googlesource.com
- Unidade principal (HU). Um dispositivo Android capaz de executar Android 9 (ou versão mais recente). Este dispositivo deve ter sua própria tela e ser capaz de atualizar a tela com novos builds do Android.
- O cluster de instrumentos é um dos seguintes:
- Tela secundária física anexada à HU. Se o o hardware e o kernel do dispositivo oferecem suporte ao gerenciamento de várias telas.
- Unidade independente. Qualquer unidade computacional conectada ao HU por meio de uma conexão de rede, capaz de receber e exibir um stream de vídeo na própria tela.
- Tela emulada. Durante o desenvolvimento, você pode usar uma
desses ambientes emulados:
- Telas secundárias simuladas. Para ativar um modelo tela secundária em qualquer distribuição AOSP Android, acesse as Opções do desenvolvedor configurações no app Configurações do sistema e depois selecione Simular secundário exibições. Essa configuração é equivalente a anexar uma instância com a limitação de que essa tela é sobreposta sobre a exibição.
- Cluster de instrumentos emulado. O Android Emulator incluído com o AAOS, é possível mostrar um cluster de instrumentos ClusterRenderingService (link em inglês).
Arquitetura de integração
Componentes de integração
Qualquer integração da API Instrument Cluster consiste nestes três componentes:
CarService
- Apps de navegação
- Serviço de cluster de instrumentos OEM
CarService
O CarService
faz a mediação entre os apps de navegação e o carro, garantindo que apenas
um aplicativo de navegação fica ativo a qualquer momento e somente aplicativos com a
android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
permissão pode enviar dados
para o carro.
O CarService
inicializa todos os serviços específicos do carro e fornece acesso a
esses serviços por meio de uma série de gerentes. Para interagir com os serviços,
e os apps em execução no carro podem acessar esses gerenciadores.
Para a implementação de clusters de instrumentos, os OEMs automotivos precisam criar um implementação de InstrumentClusterRendererService e atualizar o ClusterRenderingService (link em inglês).
Ao renderizar um cluster de instrumentos, durante o processo de inicialização, o
CarService
lê a chave InstrumentClusterRendererService
do
ClusterRenderingService (link em inglês)
para localizar uma implementação de InstrumentClusterService
. No AOSP, essa entrada
aponta para o serviço de renderização de implementação de cluster de exemplo da API Navigation State:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
O serviço mencionado nesta entrada é inicializado e vinculado
CarService
: Quando apps de navegação, como o Google Maps, solicitam uma
CarInstrumentClusterManager
, CarService
fornece um administrador que
atualiza o estado do cluster de instrumentos do InstrumentClusterRenderingService
vinculado.
Nesse caso, vinculado refere-se a
No Android
Serviços.
Serviço de cluster de instrumentos
Os OEMs precisam criar um pacote Android (APK) que contém uma subclasse de ClusterRenderingService (link em inglês).
Essa classe serve a dois propósitos:
- Fornece uma interface do Android e o dispositivo de renderização do cluster de instrumentos (o objetivo desta página).
- Recebe e renderiza atualizações de estado de navegação, como a navegação guiada orientações de navegação.
Para o primeiro propósito, as implementações de OEM de InstrumentClusterRendererService
.
precisa inicializar a tela secundária usada para renderizar informações nas telas da cabine do carro e
comunicam essas informações para CarService
chamando o
InstrumentClusterRendererService.setClusterActivityOptions()
e
InstrumentClusterRendererService.setClusterActivityState()
.
Para a segunda função, o serviço "Cluster de instrumentos" precisa fornecer um
implementação do
ClusterRenderingService (link em inglês)
que recebe eventos de atualização do status da 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:
Nessa ilustração, as cores indicam o seguinte:
- Amarelo.
CarService
eCarNavigationStatusManager
fornecidos pela plataforma Android. Para saber mais, consulte Car e CAR_NAVIGATION_SERVICE, - Ciano.
InstrumentClusterRendererService
implementado pelo OEM. - Roxo. O app de navegação implementado pelo Google e por terceiros desenvolvedores de aplicativos.
- Verde.
CarAppFocusManager
. Para saber mais, consulte Como usar 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
é atualizadoCarService
por:- Propriedades de exibição do cluster de instrumentos, como limites não obscuros (veja mais detalhes sobre limites não obscuros posteriormente).
- Opções de atividade necessárias para iniciar atividades na tela do cluster de instrumentos. Para saber mais, consulte ActivityOptions.
- Um app de navegação (como o Google Maps para Android Automotive ou qualquer app de mapas)
com as permissões necessárias):
- Recebe um
CarAppFocusManager
usando a classe Car de car-lib. - Antes do início das rotas de navegação guiada, as chamadas para
CarAppFocusManager.requestFocus()
para passarCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
comoappType
. .
- Recebe um
CarAppFocusManager
comunica essa solicitação aCarService
. Se concedido,CarService
inspeciona o pacote do app de navegação e localiza um atividade marcada com a categoriaandroid.car.cluster.NAVIGATION
.- Se encontrado, o app de navegação usa o
ActivityOptions
informado peloInstrumentClusterRenderingService
para iniciar a atividade e inclui o Propriedades de exibição do cluster de instrumentos como extras na intent.
Integrar a API
A implementação de InstrumentClusterRenderingService
precisa:
- Defina o serviço como um serviço Singleton adicionando o seguinte valor ao
o arquivo AndroidManifest.xml. Isso é necessário para garantir que uma única cópia do arquivo
O serviço do cluster de instrumentos é executado, mesmo durante a inicialização e a troca de usuários:
android:singleUser="true"
- Mantenha a permissão do sistema
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Isso garante que apenas o serviço de renderização do cluster de instrumentos da imagem do sistema Android sempre é vinculada peloCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementar o InstrumentClusterRenderingService
Para criar o serviço:
- Escreva uma classe que se estenda da
ClusterRenderingService (link em inglês)
e, em seguida, adicione uma entrada correspondente ao arquivo
AndroidManifest.xml
. Esta turma Controla a tela do cluster de instrumentos e pode, opcionalmente, renderizar o estado de navegação. dados da API. - Durante o
onCreate()
, use esse serviço para inicializar a comunicação com o o hardware de renderização. As opções incluem:- Determine a tela secundária a ser usada para o cluster de instrumentos.
- Crie uma tela virtual para que o app do cluster de instrumentos renderize e transmita o imagem renderizada para uma unidade externa (usando um formato de streaming de vídeo, como H.264).
- Quando a exibição indicada acima estiver pronta, este serviço deverá chamar
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
para definir oActivityOptions
exato que deve ser usado para exibir uma atividade no Cluster de instrumentos. Use estes parâmetros:category.
ClusterRenderingService (em inglês).ActivityOptions.
Uma instância deActivityOptions
que pode ser usada para iniciar uma atividade no cluster de instrumentos. Por exemplo, na amostra Implementação do cluster de instrumentos no AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Quando o cluster de instrumentos estiver pronto para mostrar atividades, este serviço precisará invocar
InstrumentClusterRenderingService#setClusterActivityState()
: Use estas parâmetros:category
ClusterRenderingService (em inglês).state
pacote gerado com ClusterRenderingService (em inglês). Lembre-se de fornecer estes dados:visible
: especifica o cluster de instrumentos como visível e pronto para exibir conteúdo.unobscuredBounds
Um retângulo que define a área dentro de Tela do cluster de instrumentos em que é seguro mostrar conteúdo. Por exemplo, áreas coberta por mostradores e medidores.
- Substitua o método
Service#dump()
e informe as informações de status úteis para: depuração (consulte dumpsys) para mais informações).
Exemplo de implementação de InstrumentClusterRenderingService
O exemplo abaixo descreve um InstrumentClusterRenderingService
implementação, que cria um VirtualDisplay
para apresentar o objeto Instrument
Conteúdo do cluster em uma tela física remota.
Como alternativa, esse código pode transmitir o displayId
de uma instância física secundária
tela conectada à HU, caso haja uma 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 to 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); } }
Usar a API CarAppFocusManager
A API CarAppFocusManager fornece um método chamado getAppTypeOwner()
, que permite
o serviço de cluster criado por OEMs para saber qual app tem o foco de navegação em qualquer dado
tempo de resposta. Os OEMs podem usar o método CarAppFocusManager#addFocusListener()
atual.
use getAppTypeOwner()
para saber qual app está em foco. Com essas informações,
Os OEMs podem:
- Alterne a atividade mostrada no cluster para a atividade do cluster fornecida pelo app de navegação segurando o foco.
- Pode detectar se o app de navegação em foco tem uma atividade de cluster ou não. Se o foco app de navegação não tiver uma atividade de cluster (ou, se essa atividade estiver desativada), os OEMs poderão envie esse sinal para o DIM do carro para que o atributo de navegação do cluster seja ignorado.
Use CarAppFocusManager
para definir e detectar o foco atual do app, como:
navegação ativa ou um comando de voz. Normalmente, apenas uma instância desse app
em execução (ou em foco) no sistema.
Usar o método CarAppFocusManager#addFocusListener(..)
para detectar o foco do app
muda:
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 o pacote
nomes do proprietário atual de um determinado tipo de aplicativo em foco. Esse 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 app 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: usar o app de exemplo
O AOSP oferece um app de exemplo que implementa a API Navigation State.
Para executar este app de exemplo:
- Crie e atualize o Android Auto em uma HU compatível. Use o Instruções de criação e atualização de build do Android específicas para seu dispositivo. Para instruções, consulte Uso de placas de referência.
- Conecte uma tela secundária física à HU (se compatível) ou ative a
HU secundária:
- Selecione Modo de desenvolvedor no app Configurações.
- Acesse Configurações > Sistema > Avançado > Opções do desenvolvedor > Simular telas secundárias.
- Reinicializar a HU
- Para iniciar o app KitchenSink:
- Abra a gaveta.
- Acesse Inst. cluster.
- Clique em INICIAR METADADOS.
O KitchenSink solicita o foco de NAVIGATION, que instrui o DirectRenderingCluster
para exibir uma simulação de interface do usuário no cluster de instrumentos.