Esegui comandi

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:

  1. 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).
  2. 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:

  • CarMediaService fornisce 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-common fornisce 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.

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.