¿No crees que muchas aplicaciones móviles serían mucho más convenientes si tuvieran control por voz? Y no me refiero a chatear con un bot bancario. En la mayoría de los casos, la navegación por voz o el llenado de un formulario conversacional es suficiente.
Mediante el uso del ejemplo de Habitica (una aplicación de seguimiento de hábitos de código abierto basada en Kotlin), Vit Gorbachyov, arquitecto de soluciones Just AI, te mostrará cómo agregar una interfaz de voz en cualquier aplicación de forma rápida y sin problemas.
Tabla de contenidos
¿Cuán conveniente es?
Comencemos con lo obvio:
- Es muy frecuente que necesitemos usar la aplicación cuando tenemos las manos ocupadas, cuando cocinamos, conducimos, llevamos una maleta, etc.
- La voz es un instrumento importante para las personas con discapacidad visual.
Es realmente obvio, pero la mayoría de las veces la voz es más rápida. Considera esto, pedir un vuelo que diga “Consígame un avión a Londres para mañana para dos personas” en lugar de llenar un formulario por mucho tiempo. Con una opción de preguntas aclaratorias, ¿debería ser por la mañana o por la noche? ¿Habrá equipaje o no?
La voz es muy útil en un escenario lleno de formularios y se adapta perfectamente a casi cualquier formulario largo, lo que requiere mucha información del usuario. Y estos son tipos de formularios que tiene casi cualquier aplicación móvil.
La mayoría de las empresas siguen intentando incluir todas las funciones que se les ocurren en un chat porque, por lo general, los asistentes de voz están integrados en el soporte por chat. Ya sabes, para recargar el saldo, obtener el artículo o la información del servicio, etc. No siempre es conveniente, a veces incluso es contraproducente porque el reconocimiento de voz aún no es perfecto.
El enfoque correcto aquí es integrar un asistente en la funcionalidad de la aplicación ya existente. Así que tomamos Habitica como ejemplo: es perfecto para una adición de asistente de voz porque para crear una nueva tarea debes completar el formulario largo. Intentemos cambiar este aburrido proceso a una frase con algunas preguntas de orientación.
Que necesitamos para empezar
SDK. Usamos Aimybox para crear interfaces de diálogo. Es un SDK de asistente de voz de código abierto con una interfaz de usuario personalizable lista para usar. Puede usar componentes integrados de voz a texto y texto a voz e implementaciones de NLU o puede crear su propia suite.
Aimybox implementa la arquitectura del asistente, estandariza interfaces y organiza el apoyo mutuo. Por lo tanto, realmente puede reducir el tiempo que lleva desarrollar una interfaz de voz.
Herramientas para crear un escenario. Utilizaremos el marco de desarrollo de asistente de voz y chatbot basado en Kotlin de código abierto JAICF (Just AI Conversational Framework), que es totalmente gratuito. Caila (un servicio de NLU) dentro de JAICP (Just AI Conversational Platform) nos ayudaría con el reconocimiento de intenciones.
Cubriré estas herramientas en la siguiente parte de este tutorial. Allí muestro cómo administrar una aplicación solo con voz, invocando ciertas pantallas, implementando consultas complejas dentro de la aplicación y cambiando hábitos.
- Smartphone. Necesitaremos un teléfono Android para probar la solución Habitica.
Plan de acción
Comenzamos con una bifurcación de proyecto: tomamos la rama de desarrollo de versiones y buscamos los archivos más esenciales. Usé el IDE Android Studio:
- MainActivity.kt: ahí es donde construimos la lógica.
- HabiticaBaseApplication.kt: ahí es donde iniciaremos Aimybox.
- Activity_main.xml: ahí es donde estará el elemento de la interfaz.
- AndroidManifest.xml: ahí es donde se almacenan la estructura de la aplicación y sus permisos.
De acuerdo con las instrucciones del repositorio de Habitica, cambiamos el nombre de habitica.properties.example y habitica.resources.example sacando el ejemplo. Luego comenzamos un nuevo proyecto de base de fuego y copiamos el archivo google-services.json al nodo raíz.
Ahora iniciamos la aplicación para ver si funciona. ¡Ta-dah!
Para empezar, agregamos las dependencias de Aimybox.
- implementación “com.justai.aimybox: core: 0.11.0”
- implementación («com.justai.aimybox: components: 0.1.8»)
a las dependencias:
- maven {url ‘https://dl.bintray.com/aimybox/aimybox-android-sdk/’}
- maven {url «https://dl.bintray.com/aimybox/aimybox-android-assistant/»}
y repositorios.
Y justo después de compilé Options agregamos el siguiente lone para que todo funcione correctamente.
kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString () }
Ahora los permisos.
Quitamos las “flags”en RECORD_AUDIO y MODIFY_AUDIO_SETTINGS en AndroidManifest.xml, para que las opciones se vean así:
<uses-permission android:name=»android.permission.READ_PHONE_STATE» /> <uses-permission android:name=»android.permission.ACCESS_NETWORK_STATE» /> <uses-permission android:name=»android.permission.INTERNET» /> <uses-permission android:name=»android.permission.WRITE_EXTERNAL_STORAGE» /> <uses-permission android:name=»android.permission.READ_EXTERNAL_STORAGE» /> <uses-permission android:name=»com.android.vending.BILLING» /> <uses-permission android:name=»android.permission.RECEIVE_BOOT_COMPLETED»/> <uses-permission android:name=»android.permission.RECORD_AUDIO»/> <uses-permission android:name=»android.permission.MODIFY_AUDIO_SETTINGS»/>
Ahora iniciamos Aimybox en una BaseApplication. Agregar AimyboxProvider en la inicialización del componente
E inicializando:
private fun createAimybox (context: Context): Aimybox { val unitId = UUID.randomUUID().toString() val textToSpeech = GooglePlatformTextToSpeech(context, Locale(«Ru»)) val speechToText = GooglePlatformSpeechToText(context, Locale(«Ru»)) val dialogApi = AimyboxDialogApi( «YOUR KEY», unitId) return Aimybox(Config.create(speechToText, textToSpeech, dialogApi)) }
Luego, en lugar de YOUR_KEY, verás el código de su consola Aimybox.
Ahora construimos un fragmento en mainActivity.kt. Incrustamos FrameLayout en activity_main.xml tentativamente, justo debajo de FrameLayout con id bottom_navigation
<FrameLayout android:id=»@+id/assistant_container» android:layout_width=»match_parent» android:layout_height=»match_parent»/>
En MainActivity agregamos permisos de solicitud explícitos OnCreate
ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.RECORD_AUDIO), 1)
Y cuando lo obtengamos, agregamos el fragmento en el marco mencionado anteriormente.
@SuppressLint(«MissingPermission») override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() fragmentTransaction.add(R.id.assistant_container, AimyboxAssistantFragment()) fragmentTransaction.commit()}
No olvides agregar una opción para cerrar la sesión del asistente después de haber iniciado sesión en OnBackPressed.
val assistantFragment = (supportFragmentManager.findFragmentById(R.id.assistant_container) as? AimyboxAssistantFragment) if (assistantFragment?.onBackPressed() != true) { return }
Además, agregamos estilos a styles.xml en AppTheme
<item name=»aimybox_assistantButtonTheme»>@style/CustomAssistantButtonTheme</item> <item name=»aimybox_recognitionTheme»>@style/CustomRecognitionWidgetTheme</item> <item name=»aimybox_responseTheme»>@style/CustomResponseWidgetTheme</item> <item name=»aimybox_imageReplyTheme»>@style/CustomImageReplyWidgetTheme</item> <item name=»aimybox_buttonReplyTheme»>@style/CustomButtonReplyWidgetTheme</item> Y algunos estilos personalizados un poco más abajo: <style name=»CustomAssistantButtonTheme» parent=»DefaultAssistantTheme.AssistantButton»></style> <style name=»CustomRecognitionWidgetTheme» parent=»DefaultAssistantTheme.Widget.Recognition»></style> <style name=»CustomResponseWidgetTheme» parent=»DefaultAssistantTheme.Widget.Response»></style> <style name=»CustomButtonReplyWidgetTheme» parent=»DefaultAssistantTheme.Widget.ButtonReply»></style> <style name=»CustomImageReplyWidgetTheme» parent=»DefaultAssistantTheme.Widget.ImageReply»> </style>
Ahora veamos si tras esta interacción ha aparecido el micrófono. Lanzamiento de una aplicación. De acuerdo, tenemos muchos errores sintácticos. Corregimos todo como dice IDE.
¡Aaaa y funciona!
Pero el micrófono bajó la navegación. Vamos a darle un impulso. Agreguemos esto a los estilos en CustomAssistantButtonTheme:
<item name=»aimybox_buttonMarginBottom»>72dp</item>
¡Así mejor!
Ahora cambiamos el asistente para ver si responde bien. Necesitaremos la consola Aimybox para eso.
Vamos a app.aimybox.com usando Github acc, creamos un nuevo proyecto, agregamos un par de habilidades (agregué DateTime para fines de prueba) e intentamos hacer preguntas. Usando la configuración en la esquina superior derecha, tomamos apiKey y la agregamos a createAimybox en lugar de YOUR KEY.
private fun createAimybox (context: Context): Aimybox { val unitId = UUID.randomUUID().toString() val textToSpeech = GooglePlatformTextToSpeech(context) val speechToText = GooglePlatformSpeechToText(context)val dialogApi = AimyboxDialogApi( “YOUR KEY”, unitId) return Aimybox(Config.create(speechToText, textToSpeech, dialogApi)) }
¡Funciona!
Aquí puedes encontrar el enlace al repositorio.