Questa pagina descrive come eseguire i comandi con l'interazione vocale.
Eseguire i comandi multimediali
I comandi relativi ai contenuti multimediali possono essere suddivisi in tre gruppi diversi:
- Origini multimediali esterne (ad es. Spotify installato in AAOS).
- Origini multimediali di backend (ad es. musica riprodotta in streaming tramite VIA).
- Origini multimediali locali (ad es. autoradio).
Gestire i comandi delle origini multimediali esterne
Le origini multimediali esterne sono definite come app Android che supportano le API MediaSessionCompat
e MediaBrowseCompat (per una spiegazione dettagliata sull'utilizzo di queste API, consulta Creare app multimediali per
le auto).
Importante:affinché un'app assistente possa connettersi a MediaBrowseService di tutte le app multimediali installate nel sistema, deve:
- Essere installata come app firmata dal sistema (vedi le linee guida per lo sviluppo di app multimediali per AAOS e il codice di esempio
PackageValidator). - Avere l'autorizzazione con privilegi di sistema
android.permission.MEDIA_CONTENT_CONTROL(vedi Concedere autorizzazioni con privilegi di sistema).
Oltre a MediaBrowserCompat
e MediaControllerCompat,
AAOS fornisce quanto segue:
CarMediaServicefornisce informazioni centralizzate sull'origine multimediale attualmente selezionata. Viene utilizzato anche per riprendere un'origine multimediale riprodotta in precedenza dopo lo spegnimento e il riavvio dell'auto.car-media-commonfornisce metodi pratici per elencare, connettere e interagire con le app multimediali.
Di seguito sono riportate le linee guida specifiche per l'implementazione dei comandi di interazione vocale comuni.
Visualizzare un elenco delle origini multimediali installate
Le origini multimediali possono essere rilevate utilizzando PackageManager,
e filtrando i servizi che corrispondono a MediaBrowserService.SERVICE_INTERFACE.
In alcune auto potrebbero essere presenti implementazioni speciali del servizio di navigazione multimediale, che devono essere escluse. Ecco un esempio di questa logica:
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; }
Tieni presente che le origini multimediali potrebbero essere installate o disinstallate in qualsiasi momento. Per
mantenere un elenco accurato, ti consigliamo di implementare un'BroadcastReceiver
istanza per le azioni di intent ACTION_PACKAGE_ADDED,
ACTION_PACKAGE_CHANGED,
ACTION_PACKAGE_REPLACED,
e ACTION_PACKAGE_REMOVED.
Connettersi all'origine multimediale attualmente in riproduzione
CarMediaService
fornisce metodi per ottenere l'origine multimediale attualmente selezionata e quando questa origine multimediale cambia. Queste modifiche potrebbero verificarsi perché l'utente ha interagito direttamente con l'UI o a causa dell'utilizzo dei pulsanti hardware dell'auto. D'altra parte, la libreria car-media-common offre modi pratici per connettersi a una determinata origine multimediale. Ecco un snippet semplificato su come connettersi all'app multimediale attualmente selezionata:
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 } … }
Controllare la riproduzione dell'origine multimediale attualmente in riproduzione
Con un MediaBrowserCompat
`MediaBrowserCompat` connesso, è facile inviare comandi di controllo del trasporto all'app di destinazione. Ecco un esempio semplificato:
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; } … }
Gestire i comandi delle origini multimediali locali (radio, lettore CD, Bluetooth, USB)
Le origini multimediali locali espongono le loro funzionalità al sistema utilizzando le stesse API MediaSession e MediaBrowse descritte sopra. Per adattarsi alle particolarità di ogni tipo di hardware, questi servizi MediaBrowse utilizzano convenzioni specifiche per organizzare le informazioni e i comandi multimediali.
Gestire la radio
Il servizio MediaBrowse della radio può essere identificato dal ACTION_PLAY_BROADCASTRADIO
filtro per intent. È previsto che seguano i controlli di riproduzione e la struttura di navigazione multimediale
descritti in Implementare la radio. AAOS offers the
car-broadcastradio-support
libreria contenente costanti e metodi per aiutare gli OEM a creare implementazioni di MediaBrowseService
per i propri servizi radio che seguono il protocollo definito,
e fornisce supporto per le app che utilizzano la struttura di navigazione (ad esempio, VIA).
Gestire l'input ausiliario, l'audio CD e i contenuti multimediali USB
Non esiste un'implementazione predefinita di queste origini multimediali come parte di AOSP. L'approccio suggerito è:
- Chiedere agli OEM di implementare i servizi multimediali per ciascuna di queste origini. Per maggiori dettagli, vedi Creare app multimediali per le auto.
- Queste implementazioni di MediaBrowseService verrebbero identificate e a cui verrebbe risposto nelle azioni di intent definite in Intent di riproduzione generali.
- Questi servizi esporrebbero una struttura di navigazione seguendo le linee guida descritte in Altri tipi di origine.
Gestire il Bluetooth
I contenuti multimediali Bluetooth vengono esposti tramite il profilo AVRCP Bluetooth. Per facilitare l'accesso a questa funzionalità, AAOS include un'implementazione di MediaBrowserService e MediaSession che astrae i dettagli di comunicazione (vedi packages/apps/Bluetooth).
La rispettiva struttura ad albero del browser multimediale è definita nella classe BrowseTree. I comandi di controllo della riproduzione possono essere forniti in modo simile a qualsiasi altra app, utilizzando la sua implementazione di MediaSession.
Gestire i comandi multimediali di streaming
Per implementare lo streaming multimediale lato server, VIA deve diventare un'origine multimediale, implementando le API MediaBrowse e MediaSession. Consulta Creare app multimediali per le auto. Implementando queste API, un'app di controllo vocale potrebbe (tra le altre cose):
- Partecipare senza problemi alla selezione dell'origine multimediale.
- Riprendere automaticamente la riproduzione dopo il riavvio dell'auto.
- Fornire il controllo della riproduzione e della navigazione utilizzando l'UI del Centro multimediale.
- Ricevere eventi standard dei pulsanti multimediali hardware.
Eseguire i comandi di navigazione
Non esiste un modo standardizzato per interagire con tutte le app di navigazione. Per le integrazioni con Google Maps, vedi Google Maps per Android Automotive Intents. Per le integrazioni con altre app, contatta direttamente gli sviluppatori delle app. Prima di avviare un intent per qualsiasi app (inclusa Google Maps), verifica che l'intent possa essere risolto (vedi Intent di Google Maps). In questo modo, puoi informare l'utente nel caso in cui l'app di destinazione non sia disponibile.
Eseguire i comandi del veicolo
L'accesso alle proprietà del veicolo sia per la lettura sia per la scrittura viene fornito tramite
CarPropertyManager.
I tipi di proprietà del veicolo, la relativa implementazione e altri dettagli sono spiegati
in Configurazioni delle proprietà. Per una descrizione accurata delle proprietà supportate
da Android, è consigliabile fare riferimento direttamente a hardware/interfaces/automotive/vehicle/2.0/types.hal.
L'enumerazione VehicleProperty
definita contiene proprietà standard e specifiche del fornitore, tipi di
dati, modalità di modifica, unità e definizione dell'accesso in lettura/scrittura.
Per accedere a queste stesse costanti da Java, puoi utilizzare VehiclePropertyIds e le relative classi complementari. Proprietà diverse hanno autorizzazioni Android diverse che controllano il loro accesso. Queste autorizzazioni sono dichiarate nel manifest di CarService e il mapping tra proprietà e autorizzazioni è descritto nel Javadoc di VehiclePropertyIds e applicato in PropertyHalServiceIds.
Leggere una proprietà del veicolo
Di seguito è riportato un esempio che mostra come leggere la velocità del veicolo:
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); } ... }
Impostare una proprietà del veicolo
Di seguito è riportato un esempio che mostra come attivare e disattivare l'aria condizionata anteriore.
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"));
}
…
}Eseguire i comandi di comunicazione
Gestire i comandi di messaggistica
Le VIA devono gestire i messaggi in arrivo seguendo il flusso "Tocca per leggere" descritto
in Assistente vocale
Tocca per leggere, che può gestire facoltativamente l'invio di risposte al mittente del messaggio in arrivo.
Inoltre, le VIA possono utilizzare SmsManager
(parte del android.telephony
pacchetto) per comporre e inviare messaggi SMS direttamente dall'auto o tramite Bluetooth.
Gestire i comandi di chiamata
Allo stesso modo, le VIA possono utilizzare TelephonyManager
per effettuare chiamate telefoniche e chiamare il numero della segreteria telefonica dell'utente. In questi casi, le VIA interagiranno direttamente con lo stack di telefonia o con l'app Telefono dell'auto. In ogni caso, l'app Telefono dell'auto deve essere quella che mostra all'utente l'UI relativa alle chiamate vocali.
Eseguire altri comandi
Per un elenco di altri possibili punti di integrazione tra VIA e il sistema, consulta l'elenco degli intent Android noti. Molti comandi utente possono essere risolti lato server (ad esempio, leggere le email e gli eventi di calendario degli utenti) e non richiedono interazioni con il sistema diverse dall'interazione vocale stessa.
Azioni immersive (mostrare contenuti visivi)
Quando migliora le azioni o la comprensione dell'utente, una VIA può fornire contenuti visivi supplementari sullo schermo dell'auto. Per ridurre al minimo la distrazione del conducente, mantieni questi contenuti semplici, brevi e utilizzabili. Per maggiori dettagli sulle linee guida UI/UX relative alle azioni immersive, vedi Assistenti precaricati: linee guida UX.
Per consentire la personalizzazione e la coerenza con il resto del design dell'unità principale, le VIA devono utilizzare i componenti della libreria UI per auto per la maggior parte degli elementi dell'UI. Per maggiori dettagli, vedi Personalizzazione.