Cómo ejecutar comandos

En esta página, se describe cómo ejecutar comandos mediante la interacción de voz.

Cómo ejecutar comandos de contenido multimedia

El comando relacionado con el contenido multimedia se puede dividir en tres grupos diferentes:

  • Fuentes multimedia externas (como Spotify instalado en AAOS)
  • Fuentes de contenido multimedia de backend (como música transmitida a través del VIA)
  • Fuentes de medios locales (como la radio del automóvil)

Cómo controlar comandos de fuentes de contenido multimedia externas

Las fuentes multimedia externas se definen como apps para Android que admiten MediaSessionCompat. y MediaBrowseCompat. en la nube (consulta Cómo crear apps multimedia para vehículos para obtener una explicación detallada sobre el uso de estas APIs).

Importante: Para que una app del Asistente se conecte al MediaBrowseService de todas las apps multimedia instaladas en de la aplicación, debe cumplir con los siguientes requisitos:

  1. Estar instaladas como una firma del sistema (consulta los lineamientos de desarrollo de apps multimedia para AAOS y el código PackageValidator de muestra).
  2. Conservar android.permission.MEDIA_CONTENT_CONTROL con privilegios del sistema permiso (consulta Otorgar permisos con privilegios del sistema).

Además de MediaBrowserCompat y MediaControllerCompat, El AAOS proporciona lo siguiente:

  • CarMediaService proporciona información centralizada sobre la fuente de contenido multimedia seleccionada actualmente. Este es también se usa para reanudar una fuente multimedia que se estaba reproduciendo después de reiniciar el vehículo
  • car-media-common proporciona métodos convenientes para generar listas, interactuar y conectarse. con apps multimedia.

A continuación, se incluyen lineamientos específicos para la implementación de interacciones por voz comunes con comandos de SQL sencillos.

Cómo obtener una lista de las fuentes de contenido multimedia instaladas

Las fuentes de contenido multimedia se pueden detectar con PackageManager, y filtrando servicios que coincidan con la MediaBrowserService.SERVICE_INTERFACE. En algunos vehículos, puede haber algunas implementaciones especiales de servicios de navegador multimedia. que deben excluirse. Aquí hay un ejemplo de esta 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;
}

Ten en cuenta que las fuentes multimedia se pueden instalar o desinstalar en cualquier momento. En Para mantener una lista precisa, se recomienda implementar un BroadcastReceiver para las acciones de intent ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REPLACED: y ACTION_PACKAGE_REMOVED.

Conectarse a la fuente multimedia en reproducción

CarMediaService proporciona métodos para obtener la fuente de contenido multimedia seleccionada y cuándo este los cambios de origen. Estos cambios podrían ocurrir porque el usuario interactuó con el directamente en la IU o debido al uso de botones de hardware en el vehículo. Por otro lado, La biblioteca auto-media-common ofrece formas prácticas de conectarse a un contenido multimedia determinado. fuente. Este es un fragmento simplificado sobre cómo conectarse al entorno seleccionado app multimedia:

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 la reproducción de la fuente del contenido multimedia que se está reproduciendo

Con un MediaBrowserCompat conectado es fácil enviar transporte Comandos de control a la app de destino. Este es un ejemplo simplificado ejemplo:

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;
    }

    …
}

Cómo controlar los comandos de la fuente de contenido multimedia local (radio, reproductor de CD, Bluetooth, USB)

Las fuentes de medios locales exponen su funcionalidad al sistema con la misma Las APIs de MediaSession y MediaBrowse que se describieron más arriba Para adaptarse a las particularidades de cada tipo de hardware, estos servicios MediaBrowse utilizan convenciones específicas para organizar su información y sus comandos multimedia.

Controlar la radio

Se puede identificar Radio MediaBrowseService con ACTION_PLAY_BROADCASTRADIO. filtro de intents. Se espera que sigan los controles de reproducción y la exploración de contenido multimedia. descrita en Cómo implementar radio. AAOS ofrece la car-broadcastradio-support biblioteca que contiene constantes y métodos para ayudar a los OEM a crear MediaBrowseService para sus propios servicios de radio que siguen el protocolo definido y brinda asistencia para las apps que consumen su árbol de navegación (por ejemplo, VIA).

Cómo controlar entradas auxiliares, audio de CD y medios USB

No hay una implementación predeterminada de estas fuentes multimedia como parte del AOSP. El enfoque sugerido es el siguiente:

Cómo controlar Bluetooth

El contenido multimedia de Bluetooth se expone a través del perfil de Bluetooth AVRCP. En para facilitar el acceso a esta funcionalidad, AAOS incluye un una implementación de MediaBrowserService y MediaSession que abstrae los detalles de comunicación (consulta paquetes/apps/Bluetooth)

La estructura de árbol del navegador multimedia correspondiente se define en BrowseTree. . Los comandos de control de reproducción se pueden entregar de manera similar a cualquier otra app. con su implementación de MediaSession.

Cómo controlar los comandos de transmisión de contenido multimedia

Para implementar la transmisión de contenido multimedia del servidor, el VIA debe convertirse una fuente de medios que implementa la API de MediaBrowse y MediaSession. Consulta Cómo compilar apps multimedia para automóviles. Con la implementación de estas APIs, una app de control por voz podría (entre otras cosas):

  • Participa sin problemas en la selección de fuentes de contenido multimedia
  • Se reanudará automáticamente después de reiniciar el vehículo.
  • Proporciona controles de reproducción y navegación con la IU de Media Center
  • Cómo recibir eventos de botones multimedia de hardware estándar

No hay una forma estandarizada de interactuar con todas las apps de navegación. Para obtener información sobre integraciones con Google Maps, consulta Google Maps Maps para intents de Android Automotive Para integraciones con otras de Google, comunícate directamente con sus desarrolladores. Antes del lanzamiento una intención a cualquier aplicación (incluido Google Maps), verifiquen que la intención resuelto (consulta Intent solicitudes). Así, tendrás la oportunidad de informar al usuario en caso la app de destino no está disponible.

Cómo entregar comandos del vehículo

El acceso a las propiedades del vehículo para lectura y escritura se proporciona a través de CarPropertyManager. Explicación de los tipos de propiedades de los vehículos, su implementación y otros detalles en Propiedad parámetros de configuración. Para obtener una descripción precisa de las propiedades admitidas según Android, te recomendamos que te refieras directamente a hardware/interfaces/automotive/vehicle/2.0/types.hal. La propiedad VehicleProperty “enum definido” contiene propiedades estándar y específicas del proveedor, los tipos de datos, el modo de cambio, las unidades y la definición de acceso de lectura/escritura.

Para acceder a estas mismas constantes desde Java, puedes usar VehiclePropertyIds y sus clases complementarias. Las diferentes propiedades tienen distintos permisos de Android para controlar su el acceso a los datos. Esos permisos se declaran en el campo CarService de Terraform y la asignación entre propiedades y permisos que se describen en VehiclePropertyIds Javadoc y se aplica en PropertyHalServiceIds.

Lee la propiedad de un vehículo

A continuación, se incluye un ejemplo que muestra cómo leer la velocidad del vehí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);
    }

    ...
}

Cómo configurar la propiedad de un vehículo

A continuación, se incluye un ejemplo en el que se muestra cómo encender y apagar el aire acondicionado 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"));
    }

    …
}

Cómo ejecutar comandos de comunicación

Administra los comandos de mensajería

Las VIA deben manejar los mensajes entrantes después de la acción de "presionar para leer" flujo descrito en Asistente de voz Presionar para leer, que opcionalmente puede controlar el envío de respuestas al remitente del mensaje entrante. Además, las VIA pueden usar SmsManager (parte de android.telephony ) para redactar y enviar mensajes SMS directamente desde el automóvil o por Bluetooth.

Cómo controlar comandos de llamadas

De manera similar, los VIA pueden usar TelephonyManager. para realizar llamadas telefónicas y llamar al número del buzón de voz del usuario. En estos casos, Las VIA interactuarán con la pila de telefonía directamente o con Car Dialer. . En cualquier caso, la app de Car Dialer debería ser la que se muestre IU relacionada con llamadas de voz para el usuario.

Cómo ejecutar otros comandos

Para obtener una lista de otros posibles puntos de integración entre el VIA y el consulta la lista de intents de Android conocidos. Muchos los comandos de usuario se pueden resolver del servidor (por ejemplo, leer correos electrónicos y eventos de calendario de los usuarios) y no requieren ninguna interacción con el sistema además de la interacción de voz en sí.

Acciones envolventes (contenido visual de la pantalla)

Cuando mejora las acciones o la comprensión del usuario, un VIA puede proporcionar contenido visual complementario en la pantalla del vehículo. Para minimizar la distracción del conductor, que este contenido sea simple, breve y práctico. Para obtener detalles sobre los lineamientos de IU y UX sobre las acciones envolventes, consulta Asistentes precargados: Guía de UX.

Para habilitar la personalización y la coherencia del resto de la consola central (HU), los VIA deben usar Automóvil de la IU de Cloud para la mayoría de los elementos de la IU. Para obtener más información, consulta Personalización.