Adapte aplicativos Android existentes de vídeo, jogos e navegadores web para serem executados como aplicativos estacionados no Android Auto e no Android Automotive OS. Siga estas etapas para atender às diretrizes de qualidade de aplicativos para carros na distribuição pelo Google Play.
Pré-requisitos
- Comece com um aplicativo Android adaptativo existente em uma das categorias de aplicativos estacionados compatíveis: aplicativos de streaming de vídeo, jogos ou navegadores web.
Glossário
- Aplicativos estacionados (Parked apps): Aplicativos estacionados são executados no Android Auto e no Android Automotive OS apenas enquanto o veículo está estacionado. As três categorias de estacionados são vídeo, jogos e navegadores; outras categorias não podem ser publicadas como aplicativos estacionados.
- Android Auto: O Android Auto é um sistema de projeção alimentado pelo telefone. Os aplicativos são executados no telefone do usuário e projetados no display do carro por meio de uma conexão com ou sem fio. O Android Auto é uma plataforma separada do Android Automotive OS.
- Android Automotive OS: O Android Automotive OS, ou AAOS, é uma variante do Android que é executada diretamente no veículo. O Android Automotive OS é uma plataforma separada do Android Auto.
- Categoria de Vídeo: Aplicativos de vídeo exibem vídeos em streaming enquanto estacionados. Geralmente disponível no Android Automotive OS; não compatível com Android Auto.
- Categoria de Jogos: Aplicativos de jogos fornecem gameplay enquanto estacionados. Geralmente disponível no Android Automotive OS e Android Auto.
- Categoria de Navegadores: Navegadores web permitem que os usuários naveguem na web enquanto estacionados. Disponível em beta no Android Automotive OS; não compatível com Android Auto.
- Categoria de Mídia: Não é uma categoria estacionada. Aplicativos de mídia reproduzem conteúdo de áudio (música, rádio, audiolivros, excluindo vídeo) enquanto dirige ou está estacionado.
- Plataforma Android para Carros: Android para Carros é um termo abrangente que consiste em Android Auto e Android Automotive OS.
- Categorias Geralmente Disponíveis: Permitidas nos canais de teste interno, teste fechado, teste aberto e produção do Google Play para uma plataforma compatível.
- Categorias Beta: Permitidas nos canais de teste interno ou fechado; canais de teste aberto e produção exigem aceitação em um programa de acesso antecipado.
- Áudio durante a direção: Um recurso beta no Android Automotive OS que permite que aplicativos de vídeo reproduzam áudio enquanto o veículo está em movimento.
- Diretrizes de qualidade de aplicativos para carros: Ao auditar um aplicativo de acordo com os critérios Tier 3 (Pronto para carro), Tier 2 (Otimizado para carro) ou Tier 1 (Diferenciado para carro), DEVE verificar as diretrizes de qualidade de aplicativos para carros.
- Modo de compatibilidade do Android Automotive OS: O modo de compatibilidade (
android.software.car.display_compatibility) é um recurso de sistema em veículos selecionados que fornece um affordance de retorno do sistema, renderização de área segura, dimensionamento de densidade e bloqueio opaco durante a condução (movendo atividades para o estado Stopped). O modo de compatibilidade é relevante apenas para aplicativos que suportam Android Automotive OS; não é relevante para aplicativos que suportam apenas Android Auto.
Exploração do código-fonte
Pesquise no código-fonte por arquivos AndroidManifest.xml (ou crie Assets/Plugins/Android/AndroidManifest.xml em projetos Unity), res/xml/automotive_app_desc.xml, build.gradle, build.gradle.kts, ou gradle/libs.versions.toml. Localize players de vídeo existentes, classes MediaSession, chamadas requestedOrientation e manipuladores WindowInsets. A menos que instruído de outra forma pelo usuário, peça permissão antes de adicionar dependências.
Etapa 1: Configurar o manifesto do aplicativo
Declare a categoria do aplicativo, plataformas alvo, requisitos de recursos de hardware e configuração de atividade no AndroidManifest.xml.
1.1: Identificar a categoria do aplicativo
- Aplicativos de Vídeo: Aplicativos de vídeo DEVEM definir
android:appCategory="video"em<application>e NÃO DEVEM incluirapp/src/main/res/xml/automotive_app_desc.xmlcomuses name="video". - Jogos: Jogos DEVEM definir
android:appCategory="game"em<application>. Declareandroid.hardware.gamepadcomandroid:required="false"se a entrada do controle for suportada pelo aplicativo. - Navegadores: Navegadores DEVEM incluir
<category android:name="android.intent.category.APP_BROWSER"/>noMAIN<intent-filter>de uma<activity>exportada (android:exported="true").
1.2: Identificar plataformas alvo e recursos de hardware
- Android Auto: Aplicativos direcionados ao Android Auto (Android 15+) DEVEM adicionar
<category android:name="android.intent.category.CAR_LAUNCHER"/>a um<intent-filter>no arquivoAndroidManifest.xml. Adicione-o aoMAIN<intent-filter>a menos que o usuário especifique um filtro de intenção diferente. NUNCA adicione esta categoria se o aplicativo for direcionado exclusivamente ao Android Automotive OS. - Android Automotive OS: Aplicativos direcionados ao Android Automotive OS DEVEM declarar
<uses-feature android:name="android.hardware.type.automotive" android:required="false"/>("false"para canais móveis ou de múltiplos formatos;"true"apenas se o aplicativo for publicado no canal dedicado do Automotive OS) no arquivoAndroidManifest.xml. NUNCA adicione esta tag de recurso se o aplicativo for direcionado exclusivamente ao Android Auto. - Recursos de hardware não obrigatórios (
DO-1): Para satisfazer os requisitos de recursos do Google Play eDO-1, declare recursos não suportados (android.hardware.wifi,android.hardware.screen.portrait,android.hardware.screen.landscape,android.hardware.camera) comandroid:required="false", e removaandroid:required="true"em recursos ausentes em carros. - Continuidade de exibição (
LS-C1): Configureandroid:configChangesparascreenSize,smallestScreenSize,orientation,screenLayoutedensityem<activity>para que mover para ou de uma tela distante não recrie a atividade ou cause instabilidade na reprodução. - Modo de compatibilidade e distração: Declarar o modo de compatibilidade é opcional e relevante apenas para aplicativos que suportam Android Automotive OS. NUNCA adicione modo de compatibilidade para aplicativos que suportam apenas Android Auto. Adicionar
android.hardware.type.automotivedesabilita o modo de compatibilidade, a menos que<meta-data android:name="android.software.car.display_compatibility" android:value="true"/>seja adicionado a<application>. Quando um aplicativo declaraandroid.software.car.display_compatibilitynoAndroidManifest.xml, o aplicativo DEVE verificarPackageManager.hasSystemFeature("android.software.car.display_compatibility")em tempo de execução e ocultar affordances duplicados de retorno ou fechar no aplicativo quando retornartrue. Aplicativos estacionados NÃO DEVEM incluir<meta-data android:name="distractionOptimized" android:value="true"/>em qualquer<activity>(DD-2,DD-3).
Etapa 2: Fornecer suporte de navegação de retorno e orientação
2.1: Adicionar affordances de retorno e fechar no aplicativo
Os veículos com Android Automotive OS não são obrigados a ter um botão de retorno de hardware ou software ou navegação por gestos (AN-1). Forneça controles explícitos de retorno e fechar na interface do usuário em cada tela que não seja raiz, incluindo telas de detalhes e players em tela cheia:
- Se
AndroidManifest.xmlnão declararandroid.software.car.display_compatibility: Exiba controles explícitos de retorno e fechar no aplicativo incondicionalmente. - Se
AndroidManifest.xmldeclararandroid.software.car.display_compatibilitycomandroid:value="true": Mostre controles de retorno e fechar no aplicativo apenas quandoPackageManager.hasSystemFeature("android.software.car.display_compatibility")retornarfalse.
2.2: Proteger solicitações de orientação em tempo de execução
Os displays dos veículos têm orientações fixas. Solicitar paisagem em um display de carro fixo em retrato causa letterboxing ou loops de oscilação (DO-1). Remova atributos de manifesto android:screenOrientation codificados e verifique PackageManager.FEATURE_SCREEN_LANDSCAPE e PackageManager.FEATURE_SCREEN_PORTRAIT antes de definir requestedOrientation.
Etapa 3: Adaptar-se às barras do sistema e recortes de exibição irregulares
3.1: Rastrear insets de barras de sistema controláveis
No Android Automotive OS, as montadoras têm permissão para travar as barras do sistema visíveis para que os controles de clima e veículo permaneçam acessíveis (AR-1). Rastreie insets controláveis com OnControllableInsetsChangedListener, oculte apenas barras controláveis e aplique windowInsetsPadding para insets não controláveis statusBars, navigationBars e displayCutout.
3.2: Renderizar com segurança em recortes de exibição irregulares
Para atender ao critério Tier 1 AR-2 em displays de carro curvos ou não retangulares, NUNCA use LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT (0) ou LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES (1). Configure LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS (3) ou LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER (2) usando o qualificador de recurso car em res/values-car-v30/integers.xml:
<integer name="windowLayoutInDisplayCutoutMode">3</integer>
Proteja a interface do usuário interativa, barras de aplicativos e listas roláveis com WindowInsets.safeDrawing.
Etapa 4: Atender aos requisitos de distração do motorista e reprodução de mídia
4.1: Pausar a reprodução em transições de ciclo de vida e bloquear o reinício durante a condução
Quando um veículo começa a se mover, o sistema operacional cobre as atividades estacionadas com uma sobreposição de bloqueio e aciona onPause (e onStop em veículos com modo de compatibilidade). Para satisfazer DD-2, DD-3 e MC-1:
- Pause a reprodução em
ON_PAUSEouON_STOPusandoLifecycleEventEffectdeandroidx.lifecycle:lifecycle-runtime-compose. - Exponha um
MediaSession(androidx.media3:media3-session) com comandos de reprodução, pausa ou parada e metadados de item (MC-1), e o libere emonCleared. - Adicione
useLibrary("android.car")embuild.gradle.kts, envolvaExoPlayeremForwardingSimpleBasePlayer, escuteCarUxRestrictionsManager, pause a reprodução quandoisRequiresDistractionOptimizationse tornartrue, e removaCOMMAND_PLAY_PAUSEemgetStatepara que os controles externos doMediaSessionnão possam retomar a reprodução durante a condução:
@UnstableApi
class CarAwarePlayer(context: Context) :
ForwardingSimpleBasePlayer(ExoPlayer.Builder(context).build()) {
private var shouldPreventPlay = false
private var pausedByUxRestrictions = false
private lateinit var carUxRestrictionsManager: CarUxRestrictionsManager
init {
if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
val car = Car.createCar(context)
carUxRestrictionsManager =
car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
shouldPreventPlay =
carUxRestrictionsManager.currentCarUxRestrictions.isRequiresDistractionOptimization
invalidateState()
carUxRestrictionsManager.registerListener { restrictions: CarUxRestrictions ->
shouldPreventPlay = restrictions.isRequiresDistractionOptimization
if (!shouldPreventPlay && pausedByUxRestrictions) {
handleSetPlayWhenReady(true)
invalidateState()
} else if (shouldPreventPlay && isPlaying) {
pausedByUxRestrictions = true
handleSetPlayWhenReady(false)
invalidateState()
}
}
}
}
override fun getState(): State {
val state = super.getState()
return state.buildUpon()
.setAvailableCommands(
state.availableCommands.buildUpon()
.removeIf(COMMAND_PLAY_PAUSE, shouldPreventPlay)
.build()
)
.build()
}
override fun handleRelease(): ListenableFuture<*> {
if (::carUxRestrictionsManager.isInitialized) {
carUxRestrictionsManager.unregisterListener()
}
return super.handleRelease()
}
}
4.2: Suportar áudio em segundo plano durante a direção (recurso beta opcional)
Como este é um recurso beta opcional, NUNCA implemente este recurso a menos que o usuário o solicite. Para implementar o recurso:
- Declare
<uses-feature android:name="com.android.car.background_audio_while_driving" android:required="false" />noAndroidManifest.xml, junto com as permissõesFOREGROUND_SERVICEeFOREGROUND_SERVICE_MEDIA_PLAYBACK. - Verifique o suporte do veículo em tempo de execução com
CarFeatures.isFeatureEnabled(context, CarFeatures.FEATURE_BACKGROUND_AUDIO_WHILE_DRIVING)deandroidx.car.app:app. DefinashouldPreventPlayapenas quando!isBackgroundAudioWhileDrivingSupported && restrictions.isRequiresDistractionOptimization. - Hospede o
MediaSessione o player dentro de umMediaSessionServiceexportado comandroid:foregroundServiceType="mediaPlayback", e conecte-se da interface do usuário usandoMediaController.BuilderebuildAsync.
Etapa 5: Proteger dados sensíveis em aplicativos de navegador
Como os veículos são dispositivos compartilhados, os navegadores DEVEM bloquear o acesso a senhas salvas e métodos de pagamento, a menos que estejam protegidos por um bloqueio de perfil (SD-1). Antes de sincronizar senhas ou dados de pagamento com o veículo, os navegadores DEVEM solicitar que o usuário se autentique e exibir um aviso na tela do carro informando que seus dados serão sincronizados com o carro (SD-2).
Verifique se um PIN, padrão ou senha foi definido usando KeyguardManager, abra Settings.ACTION_SECURITY_SETTINGS se não estiver definido e autentique com BiometricPrompt usando apenas BiometricManager.Authenticators.DEVICE_CREDENTIAL (os veículos não possuem hardware biométrico):
val keyguardManager = context.getSystemService<KeyguardManager>()
val isDeviceSecure = keyguardManager?.isDeviceSecure == true
lateinit var biometricPrompt: BiometricPrompt
if (!isDeviceSecure) {
context.startActivity(
Intent(Settings.ACTION_SECURITY_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
} else {
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(context.getString(R.string.auth_title))
.setSubtitle(context.getString(R.string.sync_data_to_car_notice))
.setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.build()
biometricPrompt.authenticate(promptInfo)
}
Etapa 6: Verificar a implementação
Compile o aplicativo usando ./gradlew assembleDebug. Encontre e corrija quaisquer erros de compilação.