Como usar a biblioteca Android for Cars App

A biblioteca Android for Cars App permite que seus apps de navegação, estacionamento e carregamento sejam usados em carros. Para isso, ela fornece um conjunto de modelos projetados para atender aos padrões de distração do motorista e cuidar de detalhes, como a variedade de fatores da tela do carro e as modalidades de entrada.

Este guia traz uma visão geral dos principais recursos e conceitos da biblioteca e oferece orientações sobre o processo de configuração de um app simples.

Antes de começar

  1. Leia as Diretrizes de design da biblioteca Android for Cars App.
  2. Revise os principais termos e conceitos listados nesta seção.
  3. Conheça melhor a IU do sistema do Android Auto.
  4. Leia as Notas da versão.
  5. Analise os Exemplos (link em inglês).
  6. [Apenas para bibliotecas de código fechado] Leia os Termos de Uso da biblioteca Android for Cars App.

Principais termos e conceitos

Estilos e modelos
A interface do usuário é representada por um gráfico de objetos de estilo que podem ser organizados de maneiras diferentes, conforme permitido pelo modelo a que pertencem. Os modelos são um subconjunto dos estilos principais que podem funcionar como uma raiz nesses gráficos. Os estilos principais incluem as informações a serem exibidas ao usuário, na forma de texto e imagens, bem como atributos para configurar aspectos da aparência visual dessas informações (por exemplo, cores de texto ou tamanhos de imagem). O host converte os estilos principais em visualizações projetadas para atender aos padrões de distração do motorista e cuida de detalhes como a variedade de fatores da tela do carro e modalidades de entrada.
Host
O host é o componente back-end que implementa a funcionalidade oferecida pelas APIs da biblioteca para que o app seja executado no carro. As responsabilidades do host variam desde descobrir o app e gerenciar o ciclo de vida dele até converter os estilos em visualizações e notificar o app sobre interações do usuário. Em dispositivos móveis, esse host é implementado pelo Android Auto.
Restrições de modelos
Diferentes modelos impõem restrições ao conteúdo dos estilos principais. Por exemplo, os modelos de lista têm limites quanto ao número de itens que podem ser apresentados ao usuário. Os modelos também têm restrições quanto à maneira como podem ser conectados para formar o fluxo de uma tarefa. Por exemplo, o aplicativo pode enviar até cinco modelos. Consulte Restrições de modelo para mais detalhes.
Screen
Uma Screen é uma classe fornecida pela biblioteca que os apps implementam para gerenciar a interface do usuário exibida. Uma Screen tem um ciclo de vida e fornece o mecanismo para que o app envie o modelo a ser exibido quando a tela estiver visível. Instâncias de Screen também podem ser enviadas e abertas na Pilha de telas e retiradas dela, o que garante que elas sigam as restrições de fluxos de modelo.
CarAppService
Uma CarAppService é uma classe abstrata Service que o app precisa implementar e exportar para ser descoberto e gerenciado pelo host. A CarAppService do app é responsável por validar que uma conexão de host pode ser confiável usando CarAppService.createHostValidator e, em seguida, fornecendo instâncias da Session para cada conexão usando CarAppService.onCreateSession.
Session

Uma Session é uma classe abstrata que seu app precisa implementar e retornar usando CarAppService.onCreateSession. Ela serve como ponto de entrada para exibir informações na tela do carro e tem um ciclo de vida que informa o estado atual do app na tela, por exemplo, quando ele está visível ou oculto.

Quando uma Session é iniciada (como quando o app é aberto pela primeira vez), o host solicita a Screen inicial a ser exibida usando o método Session.onCreateScreen.

Instalar a biblioteca

Siga a página de versões da biblioteca do Jetpack para ver instruções sobre como adicionar a biblioteca ao seu app.

Configurar os arquivos de manifesto do app

Antes de criar o app para carro, é preciso configurar os arquivos de manifesto dele.

Declarar o CarAppService

O host se conecta ao seu app usando a implementação CarAppService. Declare esse serviço no manifesto para permitir que o host descubra o app e se conecte a ele.

Também é necessário declarar a categoria do app no elemento category do filtro de intent. Veja a lista de categorias de apps compatíveis com os valores permitidos para esse elemento.

O snippet de código a seguir mostra como declarar um serviço de app para carros em um app de estacionamento no seu manifesto:

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService"/>
        <category android:name="androidx.car.app.category.PARKING"/>
      </intent-filter>
    </service>

    ...
<application>

Categorias de apps compatíveis

Para ser listado na Play Store para Android Auto, o app precisa pertencer a uma das categorias de apps para carro compatíveis. Para declarar a categoria do seu app, adicione um ou mais dos seguintes valores de categorias compatíveis ao filtro de intent ao declarar o serviço do app para carro:

  • androidx.car.app.category.NAVIGATION: um app que fornece rotas de navegação passo a passo.
  • androidx.car.app.category.PARKING: um app que oferece uma funcionalidade relevante para encontrar vagas de estacionamento.
  • androidx.car.app.category.CHARGING: um app que oferece uma funcionalidade relevante para encontrar estações de recarga de veículos elétricos.

Consulte Qualidade de apps Android para carros e veja a descrição e os critérios detalhados de apps que pertencem a cada categoria.

Especificar o nome e o ícone do aplicativo

Especifique o nome e o ícone do app que o host pode usar para representar seu app na IU do sistema.

É possível especificar o nome e o ícone do app usados para representar seu app com os elementos label e icon de CarAppService:

...
<service
   android:name=".MyCarAppService"
   android:exported="true"
   android:label="@string/my_app_name"
   android:icon="@drawable/my_app_icon">
   ...
</service>
...

Se o rótulo ou o ícone não forem declarados no elemento service, o host usará os valores especificados para o aplicativo.

Nível da API Car App

A biblioteca Car App define os próprios níveis de API para que você saiba quais recursos da biblioteca são compatíveis com o host do modelo em determinado veículo. Para recuperar o nível mais alto da API Car App compatível com um host, use o método getCarAppApiLevel().

É necessário declarar no arquivo AndroidManifest.xml o nível mínimo da API Car App compatível com o app:

<manifest ...>
    <application ...>
        <meta-data
            android:name="androidx.car.app.minCarApiLevel"
            android:value="1"/>
    </application>
</manifest>

Consulte a documentação da anotação RequiresCarApi para ver mais detalhes sobre como manter a compatibilidade com versões anteriores e declarar o nível mínimo da API necessário para usar um recurso. Para ver uma definição de qual nível da API é necessário para usar determinado recurso da biblioteca Car App, consulte a documentação de referência de CarAppApiLevels.

Criar CarAppService e Session

Seu app precisa ampliar a classe CarAppService e implementar o método CarAppService.onCreateSession, que retorna uma Session correspondente à conexão atual com o host:

Kotlin

class HelloWorldService : CarAppService() {
    ...
    override fun onCreateSession(): Session {
        return HelloWorldSession()
    }
    ...
}

Java

public final class HelloWorldService extends CarAppService {
    ...
    @Override
    @NonNull
    public Session onCreateSession() {
        return new HelloWorldSession();
    }
    ...
}

A instância de Session é responsável por retornar a instância de Screen a ser usada na primeira vez em que o aplicativo for iniciado:

Kotlin

class HelloWorldSession : Session() {
    ...
    override fun onCreateScreen(intent: Intent): Screen {
        return HelloWorldScreen()
    }
    ...
}

Java

public final class HelloWorldSession extends Session {
    ...
    @Override
    @NonNull
    public Screen onCreateScreen(@NonNull Intent intent) {
        return new HelloWorldScreen();
    }
    ...
}

Para gerenciar situações em que seu app para carro precise ser iniciado em uma tela que não seja a inicial ou de destino do app (como no processamento de links diretos), é possível pré-buscar uma pilha de retorno de telas usando ScreenManager.push. antes de retornar de onCreateScreen. A pré-busca permite que os usuários naveguem de volta para as telas anteriores pela primeira tela que seu app está exibindo.

Criar a tela inicial

Para criar as telas exibidas pelo app, defina classes que ampliem a classe Screen e implemente o método Screen.onGetTemplate, que retorna a instância de Template que representa o estado da IU a ser exibida na tela do carro.

O snippet a seguir mostra como declarar uma Screen que usa um modelo PaneTemplate para exibir um simples "Hello world!":

Kotlin

class HelloWorldScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val row = Row.Builder().setTitle("Hello world!").build()
        val pane = Pane.Builder().addRow(row).build()
        return PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build()
    }
}

Java

public class HelloWorldScreen extends Screen {
    @NonNull
    @Override
    public Template onGetTemplate() {
        Row row = new Row.Builder().setTitle("Hello world!").build();
        Pane pane = new Pane.Builder().addRow(row).build();
        return new PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build();
    }
}

Classe CarContext

A classe CarContext é uma subclasse de ContextWrapper acessível às suas instâncias de Session e Screen. Ela dá acesso a serviços para carros como o ScreenManager para gerenciar a pilha de tela, o AppManager para funcionalidades gerais relacionadas a apps, como acessar o objeto Surface para desenhar o mapa do app de navegação, e o NavigationManager, usado por aplicativos de navegação passo a passo para comunicar ao host metadados de navegação e outros eventos relacionados à navegação. Consulte Acessar os modelos de navegação para ver uma lista completa das funcionalidades da biblioteca disponíveis para apps de navegação.

A CarContext também oferece outras funcionalidades, como permitir o carregamento de recursos drawable usando a configuração da tela do carro, iniciar um app no carro usando intents e sinalizar se o app de navegação precisa exibir o mapa no modo escuro.

Implementar a navegação na tela

Os apps costumam apresentar uma série de telas diferentes, cada uma possivelmente usando modelos diferentes, em que o usuário pode navegar enquanto interage com a interface exibida na tela.

A classe ScreenManager fornece uma pilha de tela a ser usada para enviar telas que podem ser abertas automaticamente quando o usuário seleciona um botão "Voltar" na tela do carro ou usa o botão de retorno do hardware disponível em alguns carros.

O snippet a seguir mostra como adicionar uma ação de retorno ao modelo de mensagem, bem como uma ação que abre uma nova tela quando selecionada pelo usuário:

Kotlin

val template = MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener { screenManager.push(NextScreen(carContext)) }
            .build())
    .build()

Java

MessageTemplate template = new MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        new Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener(
                () -> getScreenManager().push(new NextScreen(getCarContext())))
            .build())
    .build();

O objeto Action.BACK é uma Action padrão que invoca automaticamente ScreenManager.pop. Esse comportamento pode ser modificado usando a instância OnBackPressedDispatcher disponível em CarContext.

Para garantir que o app seja seguro ao dirigir, a pilha de tela pode ter uma profundidade máxima de cinco telas. Consulte Restrições de modelo para mais detalhes.

Atualizar o conteúdo de um modelo

Seu app pode solicitar que o conteúdo de uma Screen seja invalidado chamando o método Screen.invalidate. Em seguida, o host chamará o método Screen.onGetTemplate do app para recuperar o modelo com o novo conteúdo.

Ao atualizar uma Screen, é importante entender o conteúdo específico do modelo que pode ser atualizado, para que o host não contabilize o novo modelo na cota. Consulte Restrições de modelo para mais detalhes.

É recomendável estruturar as telas para que haja um mapeamento de um para um entre uma Screen e o tipo de modelo que ela retorna pela implementação de Screen.onGetTemplate.

Interagir com o usuário

Seu app pode interagir com o usuário usando padrões semelhantes ao app para dispositivos móveis.

Processar entrada do usuário

Seu app pode responder à entrada do usuário transmitindo os listeners adequados aos estilos compatíveis. O snippet a seguir mostra como criar um estilo de Action que define um OnClickListener que chama um método definido pelo código do aplicativo:

Kotlin

val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()

Java

Action action = new Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(this::onClickNavigate)
    .build();

O método onClickNavigate pode iniciar o app padrão de navegação para carro usando o método CarContext.startCarApp:

Kotlin

private fun onClickNavigate() {
    val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address))
    carContext.startCarApp(intent)
}

Java

private void onClickNavigate() {
    Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address));
    getCarContext().startCarApp(intent);
}

Para ver mais detalhes sobre como iniciar apps, incluindo o formato da intent ACTION_NAVIGATE, consulte Iniciar um app para carro com uma intent.

Algumas ações, como as que exigem direcionar o usuário para continuar a interação nos dispositivos móveis, são permitidas apenas quando o carro está parado. Você pode usar o ParkedOnlyOnClickListener para implementar essas ações. Se o carro não estiver parado, o host exibirá uma indicação ao usuário de que a ação não é permitida nesse caso. Com o carro estacionado, o código será executado normalmente. O snippet a seguir mostra como usar ParkedOnlyOnClickListener para abrir uma tela de configurações no dispositivo móvel:

Kotlin

val row = Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone))
    .build()

Java

Row row = new Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone))
    .build();

Mostrar notificações

As notificações enviadas ao dispositivo móvel só aparecerão na tela do carro se forem estendidas com um CarAppExtender. Alguns atributos de notificação, como título, texto, ícone e ações do conteúdo, podem ser definidos no CarAppExtender, substituindo os atributos da notificação quando forem exibidos na tela do carro.

O snippet a seguir mostra como enviar uma notificação para a tela do carro com um título diferente daquele exibido no dispositivo móvel:

Kotlin

val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build()

Java

Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build();

As notificações podem afetar as seguintes partes da interface do usuário:

  • Uma notificação de alerta (HUN, sigla em inglês) poderá ser exibida para o usuário.
  • É possível adicionar uma entrada à central de notificações, com a opção de um ícone visível na coluna.
  • Em apps de navegação, a notificação pode ser exibida no widget de coluna, conforme descrito em Notificações passo a passo.

Os aplicativos podem escolher como configurar as notificações para afetar cada um desses elementos da interface do usuário usando a prioridade da notificação, conforme descrito na documentação do CarAppExtender.

Se NotificationCompat.Builder.setOnlyAlertOnce for chamado com o valor true, uma notificação de alta prioridade será exibida como HUN apenas uma vez.

Para saber mais sobre como projetar as notificações do seu app para carros, consulte Notificações.

Mostrar avisos

Seu app pode exibir um aviso usando CarToast, conforme mostrado neste snippet:

Kotlin

CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()

Java

CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();

Solicitar permissões

Se o app precisar de acesso a dados ou ações restritos (por exemplo, acesso a localização), as regras padrão de permissões do Android também se aplicarão a ele. Para solicitar uma permissão, use o método CarContext.requestPermissions(). No Android Auto, a caixa de diálogo de permissões do usuário será exibida no smartphone.

A vantagem de usar CarContext.requestPermissions() em vez de APIs padrão do Android é que você não precisa iniciar sua Activity exclusivamente para criar a caixa de diálogo de permissões. Quando a compatibilidade com o Android Automotive SO estiver disponível no final do ano, você também poderá usar o mesmo código no Android Auto e no Android Automotive SO, em vez de precisar criar fluxos dependentes da plataforma.

Iniciar um app para carro com uma intent

É possível chamar o método CarContext.startCarApp para executar uma das seguintes ações:

  • Abrir o discador para fazer uma chamada telefônica
  • Iniciar a navegação passo a passo em um local com o app de navegação padrão
  • Iniciar seu app com uma intent

O exemplo a seguir mostra como criar uma notificação com uma ação que abre seu app com uma tela que mostra os detalhes de uma reserva de estacionamento. Amplie a instância de notificação com uma intent de conteúdo que tenha uma PendingIntent envolvendo uma intent explícita para a ação do seu app:

Kotlin

val notification = notificationBuilder
    ...
    .extend(
        CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(ComponentName(context, MyNotificationReceiver::class.java)),
                    0))
            .build())

Java

Notification notification = notificationBuilder
    ...
    .extend(
        new CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    new Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(new ComponentName(context, MyNotificationReceiver.class)),
                    0))
            .build());

Seu aplicativo também precisa declarar um BroadcastReceiver, que é invocado para processar a intent quando o usuário seleciona a ação na interface de notificação e invoca CarContext.startCarApp com uma intent que inclui o URI de dados:

Kotlin

class MyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val intentAction = intent.action
        if (ACTION_VIEW_PARKING_RESERVATION == intentAction) {
            CarContext.startCarApp(
                intent,
                Intent(Intent.ACTION_VIEW)
                    .setComponent(ComponentName(context, MyCarAppService::class.java))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)))
        }
    }
}

Java

public class MyNotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) {
            CarContext.startCarApp(
                intent,
                new Intent(Intent.ACTION_VIEW)
                    .setComponent(new ComponentName(context, MyCarAppService.class))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)));
        }
    }
}

Por fim, o método Session.onNewIntent no seu app processa essa intent enviando a tela de reserva de estacionamento à pilha, caso ainda não esteja na parte superior:

Kotlin

override fun onNewIntent(intent: Intent) {
    val screenManager = carContext.getCarService(ScreenManager::class.java)
    val uri = intent.data
    if (uri != null
        && MY_URI_SCHEME == uri.scheme
        && MY_URI_HOST == uri.schemeSpecificPart
        && ACTION_VIEW_PARKING_RESERVATION == uri.fragment
    ) {
        val top = screenManager.top
        if (top !is ParkingReservationScreen) {
            screenManager.push(ParkingReservationScreen(carContext))
        }
    }
}

Java

@Override
public void onNewIntent(@NonNull Intent intent) {
    ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
    Uri uri = intent.getData();
    if (uri != null
        && MY_URI_SCHEME.equals(uri.getScheme())
        && MY_URI_HOST.equals(uri.getSchemeSpecificPart())
        && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment())
    ) {
        Screen top = screenManager.getTop();
        if (!(top instanceof ParkingReservationScreen)) {
            screenManager.push(new ParkingReservationScreen(getCarContext()));
        }
    }
}

Consulte Mostrar notificações para mais informações sobre como lidar com notificações do app para carro.

Restrições de modelos

O host limita o número de modelos a serem exibidos para determinada tarefa até o máximo de cinco. Nesse caso, o último dos modelos precisa ser um dos tipos a seguir:

  1. NavigationTemplate
  2. PaneTemplate
  3. MessageTemplate

Observe que esse limite se aplica ao número de modelos, e não ao número de instâncias de Screen na pilha. Por exemplo, se um app enviar dois modelos enquanto estiver na tela A, ao abrir a tela B, ele poderá enviar mais três modelos. Como alternativa, se cada tela for estruturada para enviar um único modelo, o app poderá enviar cinco instâncias de tela para a pilha ScreenManager.

Há casos especiais para essas restrições: atualizações de modelos e operações de retorno e redefinição.

Atualizações de modelos

Algumas atualizações de conteúdo não são contabilizadas no limite de modelos. Em geral, contanto que um app envie um novo modelo que seja do mesmo tipo e tenha o mesmo conteúdo principal do anterior, o novo modelo não será contabilizado na cota. Por exemplo, a atualização do estado de alternância de uma linha em um ListTemplate não é considerada na cota. Consulte a documentação de modelos individuais para saber mais sobre quais tipos de atualizações de conteúdo podem ser considerados uma atualização.

Operações de retorno

Para ativar subfluxos em uma tarefa, o host detecta quando um app está abrindo uma Screen da pilha ScreenManager e atualiza a cota restante com base no número de modelos que o app está retornando.

Por exemplo, se enquanto estiver na tela A o app enviar dois modelos, depois abrir a tela B e enviar mais dois, o app terá uma cota restante. Se o aplicativo voltar à tela A, o host redefinirá a cota para três, porque o app voltou dois modelos.

Ao retornar a uma tela, um aplicativo precisa enviar um modelo do mesmo tipo que o último enviado por essa tela. O envio de qualquer outro tipo de modelo causaria um erro. Porém, contanto que o tipo permaneça o mesmo durante uma operação de retorno, um aplicativo poderá modificar livremente o conteúdo do modelo sem afetar a cota.

Redefinir operações

Alguns modelos têm uma semântica especial que representa o final de uma tarefa. Por exemplo, o NavigationTemplate é uma visualização que permanecerá na tela e será atualizada com novas instruções passo a passo para o consumo do usuário. Ao chegar a um desses modelos, o host redefinirá a cota e tratará o modelo como se fosse a primeira etapa de uma nova tarefa, permitindo que o app a inicie. Consulte a documentação de modelos individuais para ver quais deles acionam uma redefinição no host.

Se o host receber uma intent para iniciar o app por uma ação de notificação ou pela tela de início, a cota também será redefinida. Esse mecanismo permite que um app inicie um novo fluxo de tarefas pelas notificações e é válido até mesmo quando um app já está vinculado e em primeiro plano.

Consulte Exibir notificações para mais detalhes sobre como exibir as notificações do seu app na tela do carro e Iniciar um app para carro com uma intent para ver como iniciar o app por uma ação de notificação.

Adicionar um fluxo de login

Caso seu app ofereça uma experiência de login para os usuários, você pode usar modelos como o SignInTemplate e o LongMessageTemplate com a API Car App nível 2 e mais recentes para processar o login no seu app na unidade principal do carro.

Para criar um SignInTemplate, você precisa definir um SignInMethod. Atualmente, a biblioteca Car App é compatível com três métodos de login:

Por exemplo, para implementar um modelo que colete a senha do usuário, comece criando um InputCallback para processar e validar a entrada do usuário:

Kotlin

val callback = object : InputCallback {
    override fun onInputSubmitted(text: String) {
        // You will receive this callback when the user presses enter on the keyboard.
    }

    override fun onInputTextChanged(text: String) {
        // You will receive this callback as the user is typing. The update frequency is determined by the host.
    }
}

Java

InputCallback callback = new InputCallback() {
    @Override
    public void onInputSubmitted(@NonNull String text) {
        // You will receive this callback when the user presses enter on the keyboard.
    }

    @Override
    public void onInputTextChanged(@NonNull String text) {
        // You will receive this callback as the user is typing. The update frequency is determined by the host.
    }
};

É necessário um InputCallback para o InputSignInMethod Builder.

Kotlin

val passwordInput = InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build()

Java

InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build();

Por fim, use o novo InputSignInMethod para criar um SignInTemplate.

Kotlin

SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build()

Java

new SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build();

Adicionar variantes de string de texto

Tamanhos de tela de carro diferentes podem mostrar quantidades distintas de texto. Com a API Car App nível 2 e mais recentes, é possível especificar múltiplas variantes de uma string de texto para se adequar melhor à tela. Para ver onde as variantes de texto são aceitas, procure modelos e componentes que usem um CarText.

Você pode adicionar variantes de string de texto a um CarText com o método CarText.Builder.addVariant():

Kotlin

val itemTitle = CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build()

Java

CarText itemTitle = new CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build();

Você pode usar esse CarText, por exemplo, como o texto principal de um GridItem.

Kotlin

GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()

Java

new GridItem.Builder()
    .addTitle(itemTitle)
    ...
    build();

Adicione as strings em ordem de mais para a menos preferida. Por exemplo, da mais longa para a mais curta. O host escolherá a string de comprimento adequado, dependendo da quantidade de espaço disponível na tela do carro.

Ciclos de vida de CarAppService, Session e Screen

As classes Session e Screen implementam a interface LifecycleOwner. Conforme o usuário interage com o app, os callbacks de ciclo de vida dos objetos Session e Screen são invocados, conforme descrito nos diagramas a seguir:

Os ciclos de vida de CarAppService e Session

Figura 1. O ciclo de vida da Session.

Para ver todos os detalhes, consulte a documentação do método Session.getLifecycle.

O ciclo de vida de Screen

Figura 2. O ciclo de vida da Screen.

Para ver todos os detalhes, consulte a documentação de Screen.getLifecycle.

Biblioteca de testes

A Biblioteca de testes do Android para carros oferece classes auxiliares que podem ser usadas para validar o comportamento dos seus apps em um ambiente de teste. Por exemplo, o SessionController permite que você simule uma conexão com o host e verifique se a Screen e o Template corretos são criados e retornados.

Consulte os exemplos de uso (link em inglês).

Informar um problema na biblioteca Android for Cars App

Se você encontrar um problema com a biblioteca, informe-o usando o Google Issue Tracker. Preencha todas as informações solicitadas no modelo de problema.

Criar novo problema

Antes de registrar um novo problema, verifique se ele está listado nas notas da versão da biblioteca ou relatado na lista de problemas. Inscreva-se e vote nos problemas clicando na estrela de um deles no Issue Tracker. Para saber mais, consulte Inscrever-se em um problema.