Esta página descreve como executar comandos com interação por voz.
Executar comandos de mídia
O comando relacionado à mídia pode ser dividido em três grupos diferentes:
- Fontes de mídia externas (como Spotify instalado no AAOS)
- Fontes de mídia de back-end (como músicas transmitidas por VIA)
- Fontes de mídia locais (como rádio do carro).
Processar comandos de fonte de mídia externa
Fontes de mídia externas são definidas como apps Android com suporte a MediaSessionCompat
e MediaBrowseCompat
APIs (consulte Criar apps de mídia para
carros para uma explicação detalhada sobre o uso dessas APIs).
Importante: para que um app assistente se conecte ao
MediaBrowseService
de todos os apps de mídia instalados neste
ele precisa:
- Ser instalado como assinado pelo sistema (consulte Diretrizes de desenvolvimento de aplicativos de mídia para
AAOS e o exemplo de código
PackageValidator
). - Manter
android.permission.MEDIA_CONTENT_CONTROL
com privilégios de sistema (consulte Conceder permissões com privilégios de sistema).
Além de MediaBrowserCompat
e MediaControllerCompat
,
O AAOS oferece o seguinte:
CarMediaService
fornece informações centralizadas sobre a fonte de mídia selecionada no momento. Isso é também é usado para retomar uma fonte de mídia que estava em reprodução após o desligamento e a reinicialização do carro.- O
car-media-common
oferece métodos convenientes para listar, conectar e interagir. com apps de música.
Abaixo estão as diretrizes específicas para a implementação de interações por voz comuns comandos
Conferir uma lista das fontes de mídia instaladas
As fontes de mídia podem ser detectadas usando PackageManager
,
e filtre por serviços que correspondem a MediaBrowserService.SERVICE_INTERFACE
.
Em alguns carros, pode haver algumas implementações especiais de serviço de navegador de mídia,
que deve ser excluído. Aqui está um exemplo dessa lógica:
private Map<String, MediaSource> getAvailableMediaSources() { List<String> customMediaServices = Arrays.asList(mContext.getResources() .getStringArray(R.array.custom_media_packages)); List<ResolveInfo> mediaServices = mPackageManager.queryIntentServices( new Intent(MediaBrowserService.SERVICE_INTERFACE), PackageManager.GET_RESOLVED_FILTER); Map<String, MediaSource> result = new HashMap<>(); for (ResolveInfo info : mediaServices) { String packageName = info.serviceInfo.packageName; if (customMediaServices.contains(packageName)) { // Custom media sources should be ignored, as they might have a // specialized handling (e.g., radio). continue; } String className = info.serviceInfo.name; ComponentName componentName = new ComponentName(packageName, className); MediaSource source = MediaSource.create(mContext, componentName); result.put(source.getDisplayName().toString().toLowerCase(), source); } return result; }
As fontes de mídia podem ser instaladas ou desinstaladas a qualquer momento. Em
Para manter uma lista precisa, é recomendável implementar um BroadcastReceiver
para as ações de intent ACTION_PACKAGE_ADDED
,
ACTION_PACKAGE_CHANGED
,
ACTION_PACKAGE_REPLACED
,
e ACTION_PACKAGE_REMOVED
.
Conectar à fonte de mídia em reprodução
CarMediaService
fornece métodos para obter a fonte de mídia selecionada no momento e quando essa mídia
mudanças na fonte. Essas mudanças podem acontecer porque o usuário interagiu com o
na interface do usuário ou devido ao uso de botões físicos no carro. Por outro lado,
a biblioteca car-media-common oferece maneiras convenientes de se conectar a uma determinada mídia
fonte. Veja um snippet simplificado sobre como se conectar ao
app de música:
public class MediaActuator implements MediaBrowserConnector.onConnectedBrowserChanged { private final Car mCar; private CarMediaManager mCarMediaManager; private MediaBrowserConnector mBrowserConnector; … public void initialize(Context context) { mCar = Car.createCar(context); mBrowserConnector = new MediaBrowserConnector(context, this); mCarMediaManager = (CarMediaManager) mCar.getCarManager(Car.CAR_MEDIA_SERVICE); mBrowserConnector.connectTo(mCarMediaManager.getMediaSource()); … } @Override public void onConnectedBrowserChanged( @Nullable MediaBrowserCompat browser) { // TODO: Handle connected/disconnected browser } … }
Controlar a reprodução da fonte de mídia em reprodução
Com um MediaBrowserCompat
conectado
é fácil enviar informações de transporte
controlar comandos ao app de destino. Este é um exemplo
exemplo:
public class MediaActuator … { … private MediaControllerCompat mMediaController; @Override public void onConnectedBrowserChanged( @Nullable MediaBrowserCompat browser) { if (browser != null && browser.isConnected()) { mMediaController = new MediaControllerCompat(mContext, browser.getSessionToken()); } else { mMediaController = null; } } private boolean playSongOnCurrentSource(String song) { if (mMediaController == null) { // No source selected. return false; } MediaControllerCompat.TransportControls controls = mMediaController.getTransportControls(); PlaybackStateCompat state = controller.getPlaybackState(); if (state == null || ((state.getActions() & PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH) == 0)) { // Source can't play from search return false; } controls.playFromSearch(query, null); return true; } … }
Gerenciar comandos de fontes de mídia local (rádio, CD player, Bluetooth, USB)
As fontes de mídia locais expõem suas funcionalidades ao sistema usando a mesma APIs MediaSession e MediaBrowse detalhadas acima. Para acomodar as particularidades para cada tipo de hardware, esses serviços MediaBrowse usam convenções específicas para organizar informações e comandos de mídia.
Gerenciar rádio
O Radio MediaBrowseService pode ser identificado pelo objeto ACTION_PLAY_BROADCASTRADIO
filtro de intent. O usuário deve seguir os controles de mídia e a navegação de mídia
descrita em Implementar rádio. O AAOS oferece
car-broadcastradio-support
biblioteca contendo constantes e métodos para ajudar os OEMs a criar MediaBrowseService
implementações para seus próprios serviços de rádio que seguem o protocolo definido,
e oferece suporte para apps que consomem sua árvore de navegação (por exemplo, VIAs).
Gerenciar a entrada auxiliar, o áudio CD e a mídia USB
Não há implementação padrão dessas fontes de mídia como parte do AOSP. A abordagem sugerida é:
- Os OEMs precisam implementar serviços de mídia para cada um deles. Para saber mais, consulte Criar apps de música para carros.
- Essas implementações do MediaBrowseService seriam identificadas e respondidas na intent ações definidas em Intents gerais de reprodução.
- Esses serviços exporiam uma árvore de navegação seguindo as diretrizes descritas em Outros tipos de origem.
Gerenciar o Bluetooth
O conteúdo de mídia Bluetooth é exposto por meio do perfil Bluetooth do AVRCP. Em para facilitar o acesso a essa funcionalidade, o AAOS inclui um implementação MediaBrowserService e MediaSession que abstrai o detalhes de comunicação (consulte packages/apps/Bluetooth).
A respectiva estrutura de árvore de navegador de mídia é definida em BrowseTree. . Os comandos de controle de reprodução podem ser entregues de forma semelhante a qualquer outro aplicativo, usando a implementação MediaSession.
Processar comandos de streaming de mídia
Para implementar o streaming de mídia do lado do servidor, o VIA precisa se tornar ele mesmo uma fonte de mídia, implementando MediaBrowse e API MediaSession. Consulte Criar apps de mídia para carros. Com a implementação dessas APIs, um app de controle de voz poderia (entre outras coisas):
- Participe da seleção da fonte de mídia sem problemas
- Ser retomado automaticamente após a reinicialização do carro
- Fornecer controle de reprodução e navegação usando a interface do Media Center
- Receber eventos de botão de mídia de hardware padrão
Atender aos comandos de navegação
Não há uma maneira padronizada de interagir com todos os aplicativos de navegação. Para integrações com o Google Maps, consulte Google Mapas para intents do Android Automotive. Para integrações com outros apps, entre em contato diretamente com os desenvolvedores. Antes do lançamento uma intent a qualquer aplicativo (incluindo o Google Maps), verifique se ela pode ser resolvido (consulte Intent solicitações). Isso cria a oportunidade de informar o usuário caso o app de destino não está disponível.
Atender aos comandos do veículo
O acesso às propriedades do veículo para leitura e gravação é fornecido pelo
CarPropertyManager (em inglês).
Explicação sobre os tipos de propriedades do veículo, a implementação delas e outros detalhes
em Propriedade
personalizadas. Para uma descrição precisa das propriedades compatíveis
Android, é melhor consultar diretamente hardware/interfaces/automotive/vehicle/2.0/types.hal
.
O objeto VehicleProperty
um tipo enumerado definido nele contém propriedades padrão e específicas do fornecedor, dados
tipos, modo de alteração, unidades e definição de acesso de leitura/gravação.
Para acessar essas mesmas constantes a partir de Java, você pode usar VehiclePropertyIds e suas classes complementares. Propriedades diferentes têm permissões do Android distintas controlando as próprias acesso. Essas permissões são declaradas no bloco CarService manifesto do app, e o mapeamento entre as propriedades e as permissões descritas em VehiclePropertyIds Javadoc e aplicado em PropertyHalServiceIds.
Ler uma propriedade de um veículo
Confira abaixo um exemplo que mostra como ler a velocidade do veículo:
public class CarActuator ... { private final Car mCar; private final CarPropertyManager mCarPropertyManager; private final TextToSpeech mTTS; /** Global VHAL area id */ public static final int GLOBAL_AREA_ID = 0; public CarActuator(Context context, TextToSpeech tts) { mCar = Car.createCar(context); mCarPropertyManager = (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE); mTTS = tts; ... } @Nullable private void getSpeedInMetersPerSecond() { if (!mCarPropertyManager.isPropertyAvailable(VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID)) { mTTS.speak("I'm sorry, but I can't read the speed of this vehicle"); return; } // Data type and unit can be found in // automotive/vehicle/2.0/types.hal float speedInMps = mCarPropertyManager.getFloatProperty( VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID); int speedInMph = (int)(speedInMetersPerSecond * 2.23694f); mTTS.speak(String.format("Sure. Your current speed is %d miles " + "per hour", speedInUserUnit); } ... }
Definir uma propriedade do veículo
Confira abaixo um exemplo que mostra como ligar e desligar o ar-condicionado frontal.
public class CarActuator … { … private void changeFrontAC(boolean turnOn) { List<CarPropertyConfig> configs = mCarPropertyManager .getPropertyList(new ArraySet<>(Arrays.asList( VehiclePropertyIds.HVAC_AC_ON))); if (configs == null || configs.size() != 1) { mTTS.speak("I'm sorry, but I can't control the AC of your vehicle"); return; } // Find the front area Ids for the AC property. int[] areaIds = configs.get(0).getAreaIds(); List<Integer> areasToChange = new ArrayList<>(); for (int areaId : areaIds) { if ((areaId & (VehicleAreaSeat.SEAT_ROW_1_CENTER | VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_1_RIGHT)) == 0) { continue; } boolean isACInAreaAlreadyOn = mCarPropertyManager .getBooleanProperty(VehiclePropertyIds.HVAC_AC_ON, areaId); if ((!isACInAreaAlreadyOn && turnOn) || (isACInAreaAlreadyOn && !turnOn)) { areasToChange.add(areaId); } } if (areasToChange.isEmpty()) { mTTS.speak(String.format("The AC is already %s", turnOn ? "on" : "off")); return; } for (int areaId : areasToChange) { mCarPropertyManager.setBooleanProperty( VehiclePropertyIds.HVAC_AC_ON, areaId, turnOn); } mTTS.speak(String.format("Okay, I'm turning your front AC %s", turnOn ? "on" : "off")); } … }
Atender aos comandos de comunicação
Gerenciar comandos de mensagens
Os VIAs precisam gerenciar as mensagens recebidas após o "toque para ler" fluxo descrito
no Assistente de voz
Toque para ler, que pode gerenciar o envio de respostas de volta ao remetente da mensagem recebida.
Além disso, os VIAs podem usar SmsManager
.
(parte do android.telephony
para escrever e enviar mensagens SMS diretamente do carro ou por Bluetooth.
Processar comandos de chamada
Os VIAs também podem usar TelephonyManager
.
para fazer chamadas telefônicas e ligar para o número do correio de voz do usuário. Nesses casos,
Os VIAs vão interagir com a pilha de telefonia diretamente ou com o Telefone do Carro
app. De qualquer forma, o app Telefone do carro deve ser o que mostra
interface relacionada a chamadas de voz para o usuário.
Executar outros comandos
Para obter uma lista de outros possíveis pontos de integração entre o VIA e o sistema, verifique a lista de intents do Android conhecidas. Muitas os comandos de usuário podem ser resolvidos no lado do servidor (por exemplo, ler e-mails de usuários e eventos da agenda) e não exigem nenhuma interação com o sistema além da interação por voz.
Ações imersivas (exibir conteúdo visual)
Quando melhora as ações ou o entendimento do usuário, um VIA pode oferecer conteúdo visual complementar na tela do carro. Para minimizar a distração do motorista, mantenha esse conteúdo simples, breve e acionável. Para detalhes sobre as diretrizes de interface/UX sobre ações imersivas, consulte Assistentes pré-carregados: orientações sobre a UX.
Para permitir a personalização e a consistência com o restante do design da unidade principal (HU), os VIAs devem usar Carro Componentes da biblioteca de interface para a maioria dos elementos da interface. Para mais detalhes, consulte Personalização.