Dentro de la lista de novedades que nos ha dejado la Google I/O de este año y que se celebró hace unos días, en Quelinka Tech vamos a realizar una serie de artículos donde repasaremos algunas de las novedades provistas por Google y, en este artículo, veremos cómo trabajaremos con las Android Slices. Una novedad que traerá Android P y que nos permitirá mejorar la interacción de nuestras aplicaciones con los usuarios.
Primero de todo, ¿qué son las Android Slices?
Esta nueva funcionalidad dentro de nuestro sistema operativo móvil y compatible desde Android 4.4, serán plantillas de interfaz de usuario provistas por nuestro aplicativo que mostrarán contenido enriquecido, dinámico e interactivo, que después podrá aparecer dentro de otros aplicativos, como el asistente de búsqueda de Google. Estos slices permitirán a los usuarios realizar acciones rápidas sobre nuestra aplicación desde otras aplicaciones.
Nosotros, como desarrolladores, podremos personalizar la apariencia y el funcionamiento de nuestras Slices a través de la utilización de las plantillas provistas en el sistema. Para esta primera toma de contacto, realizaremos un ejemplo sencillo, que contendrá una cabecera, una etiqueta y una acción, que podrá ser un botón o un control de tipo Toogle.
Integrando Android Slices en nuestros aplicativos.
Para crear nuestra primera Slice, deberemos de agregar un proveedor a través del menú New > Other > Slice Provider dentro de nuestro proyecto. Este asistente creará una clase dentro de nuestro proyecto, e introducirá en nuestro AndroidManifest.xml una entrada para definir nuestro proveedor:
<provider android:name=".MyFirstSliceProvider" android:authorities="com.tech.slicesapp" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.app.slice.category.SLICE" /> </intent-filter> </provider>
Nota: El asistente que acabamos de invocar, dentro de la versión Android 3.2.0 Canary Update 14, asignó mal los paquetes androidx.slice* dentro del fichero build.gradle de la aplicación, y tuve que apuntar correctamente estos paquetes a los siguientes:
dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0-alpha1' //Solo si vamos a usar librerías de compatibilidad
implementation 'androidx.slice:slice-core:1.0.0-alpha1'
implementation 'androidx.slice:slice-builders:1.0.0-alpha1'
}
Además, tuve que ajustar la versión de compilación para que fuese compatible con Android P, tal y como se muestra a continuación:
compileSdkVersion 'android-P' defaultConfig { applicationId "com.tech.slicessample" minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }
Cada Slice que definamos tendrá establecida una URI que, cuando otro aplicativo quiera mostrarla dentro de un control de tipo SliceViewer, enviará una petición a nuestra aplicación, que deberá de manejar esta entrada y construir de manera dinámica nuestra Slice a través del método onBindSlice de nuestro proveedor:
override fun onBindSlice(sliceUri: Uri): Slice? { return if (sliceUri.path == "/") { ListBuilder(context, sliceUri, ListBuilder.INFINITY) .addRow { it.setTitle("Mi primera slice") } .build() } else null }
Como vemos, estas Slices estarán construidas a partir de un ListBuilder, que nos permitirá agregar diferentes tipos de filas que se mostrarán dentro de un listado. La apariencia de nuestra slice cuando sea invocada por otro aplicativo ahora mismo será la siguiente:
Personalización de Slices.
Como hemos visto, las Slices las podremos construir a través de la utilización de un ListBuilder, con el que podremos personalizar la apariencia y el funcionamiento a través de las siguientes opciones.
SliceAction
Este será el elemento más básico que podremos adjuntar a una Slice, y que contendrá una etiqueta, junto con un objeto de tipo PendingIntent, que podrá ser; un botón en forma de icono o un control de tipo toggle. Para la definición de una SliceAction haremos uso de uno de los constructores de filas que veremos a continuación. Estas slices podrán tener además, una imagen con un tamaño personalizable, y que podrá ser ICON_IMAGE, SMALL_IMAGE o LARGE_IMAGE.
Ejemplo de creación de una acción:
val noteAction = SliceAction(takeNoteIntent, IconCompat.createWithResource(context, R.drawable.ic_pencil), ICON_IMAGE, "Take note")
HeaderBuilder
La clase HeaderBuilder nos permitirá definir una cabecera para nuestras Slices. En la mayoría de casos estableceremos una cabecera en nuestras Slices, pero no es obligatorio. Nuestras cabeceras podrán contener un título, un subtítulo, un subtítulo de tipo resumen, y una acción principal.
fun createSliceWithHeader(sliceUri: Uri) = ListBuilder(context, sliceUri, ListBuilder.INFINITY) .setAccentColor(0xff0F9D) // Specify color for tinting icons .setHeader { it.apply { setTitle("Get a ride") setSubtitle("Ride in 4 min") setSummary("Work in 1 hour 45 min | Home in 12 min") } }
RowBuilder
RowBuilder nos permitirá definir filas dentro de un ListBuilder. Tendremos que tener en cuenta que nuestros ListBuilder nos permitirán definir tantas filas como necesitemos, y que las filas aparecerán en el orden establecido dentro de nuestro código asociado. Una fila soportará cualquiera de los siguientes elementos; un título, un subtítulo, uno o varios elementos de inicio (que podrán ser una acción, un icono o un timestamp), uno o varios elementos al final de la fila, y una acción primaria.
Podremos combinar el contenido de nuestras filas como queramos, pero siempre siguiendo estas dos reglas:
- Los elementos al final de la fila no podrán ser una mezcla de iconos y SliceActions.
- Una fila solo deberá de contener un timestamp.
Os mostramos el ejemplo de la documentación oficial a continuación que definirá una fila de activación / desactivación de wifi donde, al pulsarla, nos llevará a la configuración Wifi de nuestro dispositivo:
fun createActionWithActionInRow(sliceUri: Uri): Slice { // Primary action - open wifi settings. val primaryAction = SliceAction(wifiSettingsPendingIntent, IconCompat.createWithResource(context, R.drawable.ic_wifi), "Wi-Fi Settings") // Toggle action - toggle wifi. val toggleAction = SliceAction(wifiTogglePendingIntent, "Toggle Wi-Fi", isConnected /* isChecked */) // Create the parent builder. return ListBuilder(context, wifiUri, ListBuilder.INFINITY) .setAccentColor(0xff4285) // Specify color for tinting icons / controls. .addRow { it.apply { setTitle("Wi-Fi") setPrimaryAction(primaryAction) addEndItem(toggleAction) } } .build() }
GridBuilder
GridBuilder será un constructor similar a RowBuilder, en que con los dos conseguiremos la adición de una fila, pero en el caso de GridBuilder podremos agregar tantos elementos como queramos, y estos aparecerán representados en una tabla:
Cada celda de nuestra tabla la podremos configurar a través de la adición de las llamadas a CellBuilder, que nos permitirá agregar dos líneas de texto (una principal y otra secundaria), y una imagen, que podremos mostrarla en tres tamaños diferentes; ICON_IMAGE, SMALL_IMAGE y LARGE_IMAGE.
fun createSliceWithGridRow(sliceUri: Uri): Slice { // Create the parent builder. return ListBuilder(context, sliceUri, ListBuilder.INFINITY) .setHeader { it.apply { setTitle("Famous restaurants") setPrimaryAction(SliceAction(pendingIntent, icon, "Famous restaurants")) } } .addGridRow { it.apply { addCell { it.apply { addImage(image1, LARGE_IMAGE) addTitleText("Top Restaurant") addText("0.3 mil") setContentIntent(intent1) } } addCell { it.apply { addImage(image2, LARGE_IMAGE) addTitleText("Fast and Casual") addText("0.5 mil") setContentIntent(intent2) } } addCell { it.apply { addImage(image3, LARGE_IMAGE) addTitleText("Casual Diner") addText("0.9 mi") setContentIntent(intent3) } } addCell { it.apply { addImage(image4, LARGE_IMAGE) addTitleText("Ramen Spot") addText("1.2 mi") setContentIntent(intent4) } } } } .build() }
Previsualización de nuestras slices
En la página de documentación de desarrolladores de Android han dejado disponible una aplicación, llamada SliceViewer, y que podremos descargar desde aquí con la que podremos testear nuestras aplicaciones y el funcionamiento de nuestras Slices.
Para su instalación, simplemente deberemos de ejecutar el siguiente comando dentro de una terminal de comandos, donde tengamos disponible nuestro ejecutable de adb:
adb install -r -t slice-viewer.apk
Una vez que hayamos ejecutado este comando, la aplicación descargada aparecerá sobre el dispositivo que tuviésemos conectado y funcionando en ese momento sobre nuestro equipo y, con la que podremos invocar, a través de las urls definidas en nuestro aplicativo los Slices programados.
La URL de acceso a nuestro aplicativo será:
content://identificador-app/ruta-slice
Por ejemplo:
content://com.tech.slicessample/helloworld
En el siguiente artículo pondremos en práctica lo visto aquí, junto con otras técnicas de obtención de información, para hacer un widget del tiempo climático por ciudad.
Fuentes del artículo:
Android Slices: https://developer.android.com/guide/slices/
CodeLab I/O 2018 Android Slices: https://codelabs.developers.google.com/codelabs/android-slices-basic/index.html
Deja un comentario