Android Automotive considera la voz como un componente crucial
las interacciones seguras para conducir y una de las formas más seguras para que los usuarios
interactuar con el SO Android Automotive mientras conduces Como resultado, ampliamos la
APIs del asistente de voz de Android (incluidas VoiceInteractionSession
)
Para permitir que los asistentes de voz realicen tareas para los usuarios
que pueden ser difíciles de lograr mientras se conduce.
La función Tocar para leer permite que los asistentes de voz lean y respondan los mensajes de texto en
en nombre del usuario, cuando este interactúa con las notificaciones de mensajes. Para proporcionar
esta funcionalidad, puedes integrar un asistente de voz con
CarVoiceInteractionSession
En Automotive, las notificaciones publicadas en el Centro de notificaciones identificaron
como INBOX
o INBOX_IN_GROUP
(por ejemplo, mensajes SMS) incluye un
Botón Reproducir. El usuario puede hacer clic en Reproducir para seleccionar
el asistente de voz lee la notificación en voz alta y, de manera opcional, responde con la voz.
Figura 1: Notificación de Presionar para leer con el botón Reproducir.
Cómo realizar la integración con CarVoiceInteractionSession
En las siguientes secciones, se describe cómo integrar un asistente de voz con
CarVoiceInteractionSession
Cómo admitir interacciones de voz
Las apps que proporcionan servicios de interacción por voz en el vehículo deben
integrarse con las interacciones de voz existentes de Android. Para obtener más información, consulta Asistente de Google para Android.
(con la excepción de VoiceInteractionSession
). Si bien toda la API de interacción de voz
siguen siendo los mismos que se implementaron en los dispositivos móviles, CarVoiceInteractionSession
(descrito en Cómo implementar CarVoiceInteractionSession), reemplaza
VoiceInteractionSession
Para obtener más información, consulta las siguientes páginas:
Cómo implementar CarVoiceInteractionSession
CarVoiceInteractionSession
expone las APIs que puedes usar para permitir que los asistentes de voz lean mensajes de texto en voz alta y, luego,
responder los mensajes en nombre del usuario.
La diferencia clave entre CarVoiceInteractionSession
y
VoiceInteractionSession
clase es que
CarVoiceInteractionSession
pase en la acción en onShow
para que el asistente de voz pueda detectar el contexto de la solicitud del usuario tan pronto como
CarVoiceInteractionSession
inicia una sesión. Los parámetros de onShow
para cada clase se enumeran en la siguiente tabla:
CarVoiceInteractionSession | VoiceInteractionSession |
---|---|
onShow toma estos tres parámetros:
|
onShow toma estos dos parámetros:
|
Cambios en Android 10
A partir de Android 10, la plataforma llama a VoiceInteractionService.onGetSupportedVoiceActions
para detectar qué acciones se admiten. El asistente de voz anula y
implementa VoiceInteractionService.onGetSupportedVoiceActions
,
como se muestra en el siguiente ejemplo:
public class MyInteractionService extends VoiceInteractionService { private static final ListSUPPORTED_VOICE_ACTIONS = Arrays.asList( CarVoiceInteractionSession.VOICE_ACTION_READ_NOTIFICATION); @Override public Set onGetSupportedVoiceActions(@NonNull Set voiceActions) { Set result = new HashSet<>(voiceActions); result.retainAll(SUPPORTED_VOICE_ACTIONS); return result; } }
Las acciones válidas se describen en la siguiente tabla. Para obtener detalles sobre cada acción, consulta Diagramas de secuencias.
Acción | Carga útil esperada | Acción esperada de interacción de voz |
---|---|---|
VOICE_ACTION_READ_NOTIFICATION |
Leer los mensajes en voz alta para el usuario y, luego, activar la opción Marcar como leído pendiente cuando los mensajes se leen correctamente. De forma opcional, solicita usuario para que te brinde una respuesta. | |
VOICE_ACTION_REPLY_NOTIFICATION |
Parcelable con key.KEY_NOTIFICATION
que se asigna a StatusBarNotification .Requiere android.permission.BIND_NOTIFICATION_LISTENER_SERVICE . |
Solicita al usuario que indique el mensaje de respuesta, escribe el mensaje de respuesta en
el RemoteInputReply del intent pendiente y, luego, activa el
intent pendiente. |
VOICE_ACTION_HANDLE_EXCEPTION |
String con clave.KEY_EXCEPTION
que se asigna a ExceptionValue
(descritos en Valores de excepciones).KEY_FALLBACK_ASSISTANT_ENABLED que se asigna a un valor booleano. Si el valor
es true , el asistente de resguardo
que puede controlar la solicitud del usuario
inhabilitado. |
La acción esperada que se debe tomar para la excepción se define en el documentación de la excepción. |
Valores de excepción
EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING
le indica al asistente de voz que falta el permiso Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE
y que debe obtenerlo del usuario.
Solicita permiso de objeto de escucha de notificaciones
Si el asistente de voz predeterminado no tiene el objeto de escucha de notificaciones
permiso, el objeto FallbackAssistant
de la plataforma
(si el fabricante del vehículo lo habilita), es posible que lea el mensaje en voz alta antes de que se active
a quien se le notificó para solicitar el permiso. Para determinar si FallbackAssistant
está habilitado
leyó el mensaje, el asistente de voz debería revisar
Valor booleano KEY_FALLBACK_ASSISTANT_ENABLED
en la carga útil.
La plataforma recomienda que el asistente de voz agregue lógica de límite de frecuencia para
la cantidad de veces que se solicita este permiso. Al hacerlo, se respeta al usuario que no
deseas conceder al asistente de voz este permiso y prefiere la
FallbackAssistant
para leer mensajes de texto en voz alta. Hacer una solicitud
al usuario para obtener permiso cada vez que presiona Reproducir en una notificación de mensaje
puede generar una experiencia del usuario negativa. La plataforma no impone límites de frecuencia.
en nombre del asistente de voz.
Al solicitar el permiso de objeto de escucha de notificaciones, el asistente de voz debe
usa CarUxRestrictionsManager
para determinar si un usuario está estacionado o conduciendo. Si el usuario está conduciendo, el asistente de voz
muestra una notificación con instrucciones para otorgar el permiso. Hacerlo
ayuda (y le recuerda) al usuario a otorgar el permiso cuando sea más seguro.
Cómo trabajar con StatusBarNotification
StatusBarNotification
pasó con la función de lectura y respuesta
las acciones de voz siempre están en una notificación de mensajería compatible con vehículos, como se describe
en Notificar
usuarios de mensajes. Si bien es posible que algunas notificaciones no tengan la respuesta pendiente
todos tienen intents pendientes Marcar como leído.
Para optimizar las interacciones con las notificaciones, usa NotificationPayloadHandler
,
que proporciona métodos para extraer mensajes de la notificación y escribir el
responder mensajes al intent pendiente adecuado de la notificación. Después del
Asistente de voz lee el mensaje y debe activar la marca.
como intent de lectura.
Cumplimiento de las condiciones previas de Tocar para leer
Solo el VoiceInteractionSession
de la voz predeterminada
el asistente recibe una notificación cuando un usuario activa la acción de voz para leer y
responder mensajes. Como se mencionó anteriormente, este asistente de voz predeterminado también debe
tener el permiso de objeto de escucha de notificaciones.
Diagramas de secuencias
Estas figuras muestran los flujos lógicos de CarVoiceInteractionSession actions
:
Figura 2: Diagrama de secuencias de VOICE_ACTION_READ_NOTIFICATION.
En el caso de la Figura 3, se recomienda usar la app de límites de frecuencia para las solicitudes de permisos:
Figura 3: Diagrama de secuencias de VOICE_ACTION_REPLY_NOTIFICATION.
Figura 4: Diagrama de secuencias de VOICE_ACTION_HANDLE_EXCEPTION.
Leer el nombre de la app
Si deseas que el asistente de voz lea el nombre de la aplicación de mensajería en voz alta durante la (por ejemplo, "Sam de Hangouts dijo...") crea una función como la que se muestra en el siguiente ejemplo de código para asegurarte de que el asistente lea el nombre correcto:
@Nullable String getMessageApplicationName(Context context, StatusBarNotification statusBarNotification) { ApplicationInfo info = getApplicationInfo(context, statusBarNotification.getPackageName()); if (info == null) return null; Notification notification = statusBarNotification.getNotification(); // Sometimes system packages will post on behalf of other apps, so check this // field for a system app notification. if (isSystemApp(info) && notification.extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) { return notification.extras.getString(Notification.EXTRA_SUBSTITUTE_APP_NAME); } else { PackageManager pm = context.getPackageManager(); return String.valueOf(pm.getApplicationLabel(info)); } } @Nullable ApplicationInfo getApplicationInfo(Context context, String packageName) { final PackageManager pm = context.getPackageManager(); ApplicationInfo info; try { info = pm.getApplicationInfo(packageName, 0); } catch (PackageManager.NameNotFoundException e) { return null; } return info; } boolean isSystemApp(ApplicationInfo info) { return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; }