Cómo exponer datos para complicaciones de la cara de reloj en Wear OS

1. Cómo exponer tus datos a complicaciones

En este codelab, aprenderás a compilar una fuente de datos de complicación.

Conceptos y configuración

Al final del codelab, comprenderás cómo brindarles datos a las complicaciones de la cara de reloj en Wear OS.

Conceptos

Una complicación es una característica de una cara de reloj diferente a las horas y los minutos. Por ejemplo, la cara de reloj en la siguiente imagen contiene cuatro complicaciones.

39f4ebe8dc4800b0.png

La API de Complications está diseñada para caras de reloj y apps de fuente de datos:

  • Las fuentes de datos de complicación brindan información, p. ej., el nivel de la batería, el clima, el recuento de pasos, etc.
  • Los desarrolladores de caras de reloj pueden mostrar esos datos en una complicación en la cara de reloj.
  • El usuario selecciona las fuentes de datos que desea para sus complicaciones.

Screen Shot 2016-05-17 at 5.14.50 PM.png

En este codelab, abarcamos la creación de una fuente de datos de complicación. Si también te interesa agregar complicaciones a una cara de reloj, consulta nuestra ejemplo de caras de reloj.

Comencemos.

Clona el repositorio del proyecto inicial

A fin de ayudarte a comenzar rápidamente, preparamos un proyecto para que tú lo compiles. Contiene algunos parámetros de configuración básicos de código y de aplicaciones necesarias para el codelab.

Si tienes Git instalado, ejecuta el comando que se indica abajo. Para comprobar si Git está instalado, escribe git --version en la terminal o línea de comandos y verifica que se ejecute de manera correcta:

 git clone https://github.com/android/codelab-complications-data-source.git

Si no tienes Git, puedes descargar el proyecto como un archivo ZIP:

Importa el proyecto

Inicia Android Studio y selecciona "Open an existing Android Studio project" en la pantalla de bienvenida. Abre el directorio del proyecto y haz doble clic en el archivo build.gradle en el directorio complications-data-source.

En la esquina superior izquierda de la ventana del proyecto, si estás en la vista Android, deberías ver un conjunto de íconos de carpeta similares a los de la siguiente captura de pantalla. (Si estás en la vista Project, expande el proyecto complications-data-source para ver el conjunto de íconos de carpeta).

786caabc75caee70.png

Hay dos íconos de carpeta. Ambos representan un módulo. Ten en cuenta que Android Studio puede tardar varios segundos la primera vez que compile el proyecto en segundo plano. Durante este período, verás un ícono giratorio en la barra de estado, en la parte inferior de Android Studio:

27f04b5598a2f95e.png

Espera hasta que los procesos terminen antes de realizar cambios en el código para que Android Studio extraiga todos los componentes necesarios.

Comprende el proyecto inicial

Ya está todo listo y configurado para comenzar a exponer tus datos a complicaciones. Comenzaremos con el módulo base. Agregarás código de cada paso a base.

Puedes usar el módulo complete del codelab como punto de referencia para verificar tu trabajo (o como referencia si encuentras un problema).

Descripción general de los componentes clave para las fuentes de datos

  • ComplicationTapBroadcastReceiver: Es la clase que se usa para actualizar nuestros datos de complicación a través de un PendingIntent.
  • CustomComplicationDataSourceService: Es la clase que se usa para exponer nuestros datos a complicaciones. Este archivo se encuentra en el directorio base/java/com/example/android/wearable/complicationsdatasource En Android Studio, se encuentra en base/java/com.example.android.wearable.complicationsdatasource. Dentro de la clase, trabajaremos principalmente con cuatro métodos:
  • onComplicationActivated: Se llama cuando se activa una complicación con tus datos.
  • getPreviewData: Obtiene una vista previa de datos para una complicación que se utiliza en la IU del editor (por lo general, solo contenido estático).
  • onComplicationRequest: La mayor parte de nuestro trabajo estará en este método. Se llama a este método cada vez que una complicación activa necesita datos actualizados desde tu fuente.
  • onComplicationDeactivated: Se llama cuando se desactiva la complicación.

Configuración del emulador

Si necesitas ayuda para configurar un emulador de Wear OS, consulta la sección "Cómo iniciar el emulador y ejecutar tu app para Wear" en la página "Cómo crear y ejecutar una app para wearables".

Ejecuta el proyecto inicial

Ejecutemos la app en un reloj.

  • Conecta tu dispositivo Wear OS o inicia un emulador.
  • En la barra de herramientas, selecciona la configuración "base" en el selector desplegable y haz clic en el botón triangular verde (Run) que está a un lado:

a04699aa4cf2ca12.png

  • Si aparece un error como el que se muestra a continuación (Error Launching activity), cambia Activity de lanzamiento predeterminado (sigue las instrucciones que se indican a continuación). 6ea74bcba8278349.png

Por el contrario, si se te solicita que se use Activity para iniciar la app, elige "Do not launch Activity".

  • Para cambiar el Activity de lanzamiento predeterminado (si es necesario, del paso anterior), haz clic en el selector desplegable a la izquierda de la flecha verde y haz clic en "Edit configurations".

1e3e1dc73655ccd8.png

Selecciona "base" y verás una ventana similar a la que se muestra más abajo. Selecciona "Nothing" en la sección Launch Options y haz clic en Run. Más adelante, si deseas intentar iniciar el otro módulo, también deberás hacerlo.

5e98572969d8228.png

  • Selecciona tu dispositivo o emulador de Android y haz clic en OK. De esta manera, se instalará el servicio en el dispositivo o emulador de Wear OS.
  • Después de unos segundos, se compila el servicio y está listo para implementarse. Verás un ícono giratorio en la barra de estado, en la parte inferior de Android Studio.
  • Si aún no está en la pestaña "Build", en la parte inferior izquierda de Android Studio, selecciona esa pestaña y podrás ver el progreso de la instalación. Al final del proceso de instalación, deberías ver el mensaje "Build: completed successfully".

5ea92276833c0446.png

  • Selecciona una cara de reloj que te permita seleccionar una complicación. En nuestro caso, elegimos Elements Digital, pero es probable que no esté disponible en tu reloj.

a5cf2c605206efe2.png

Ten en cuenta que, debido a que es la primera vez que ejecutas esta cara de reloj, deberás seleccionarla en "Agregar más caras de reloj". Después de que se seleccione una vez, aparecerá como una de las opciones junto a esta.

  • Ahora, debes centrarte en la cara de reloj elegida en el menú Favoritos (consulta la siguiente imagen). Haz clic en el ícono de ajustes en la parte inferior.

f17fb6b4cfe06182.png

  • Para esta cara de reloj, debes seleccionar Datos. Es posible que la IU sea diferente para la cara de reloj personalizada que usas.

aef4fca32751a15a.png

  • Selecciona cualquier posición, es decir, cualquier "+" (complicación).

461f8a704fbc6496.png

  • Por último, desplázate hacia abajo y selecciona el servicio Codelab de fuente de datos de complicación. (Después de seleccionarlo, es posible que debas deslizar el dedo varias veces hacia la izquierda o presionar el dispositivo para salir).

b4d0d14140ce0120.png

  • En el resultado, deberías ver los mensajes de registro "onComplicationActivated()" y "onComplicationRequest ()" (aunque no se mostrará nada en la ubicación de la complicación).
  • Si no ves los mensajes del registro, vuelve a intentar implementar la cara de reloj presionando el botón triangular verde en la barra de herramientas.
  • Si no sabes cómo ver los datos de Log, haz clic en la pestaña etiquetada como "6: Logcat" en la parte inferior de Android Studio. Establece los menús desplegables en tu dispositivo o emulador y el nombre del paquete, com.example.android.wearable.complicationsdatasource (a continuación, se incluye una captura de pantalla).

af9cf164f9c598fc.png

"¡Pero espera! No se muestra nada en el espacio de datos que seleccioné". No te preocupes, aún no brindamos datos. Agregaremos esto en el paso siguiente.

En algunos relojes, la cara de reloj de Elements tiene complicaciones habilitadas, por lo que es probable que veas una complicación propagada en tu reloj. Tampoco te preocupes si el emulador tiene una nube tachada en lugar del ícono de avión. Para este codelab, no necesitaremos una conexión a un teléfono ni a Internet.

52da39817e329e7a.png

Resumen

En este paso, aprendiste lo siguiente:

  • Wear OS y los conceptos detrás de la exposición de datos a complicaciones
  • Conceptos básicos de nuestro punto de partida (módulo base)
  • Cómo implementar y ejecutar una cara de reloj

Cuál es el próximo paso

Comencemos a exponer algunos datos.

2. Cómo exponer datos de textos cortos

Paso 2 del código

En este paso, comenzaremos a exponer los datos. Las complicaciones aceptan varios tipos de datos. En este paso, mostraremos el tipo de datos de textos cortos.

Si, en algún momento, te confunden los conceptos que se analizan en este codelab, consulta el módulo complete y aprende a implementar estos pasos.

Cómo especificar los tipos de datos que admite tu fuente de datos

Abre el archivo AndroidManifest.xml y observa el servicio CustomComplicationDataSourceService. Observa el filtro de intents:

<action android:name=
    "android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>

De esta manera, se indica al sistema que tu servicio extiende ComplicationDataSourceService o SuspendingComplicationDataSourceService (variación que admite corrutinas de Kotlin) y puede enviar datos para complicaciones.

A continuación, se muestra el elemento meta-data que especifica los tipos de datos que admitimos. En este caso, se admite SMALL_IMAGE, pero, en este paso, cambia eso a SHORT_TEXT. Cambia tu primer elemento meta-data por lo siguiente:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="SHORT_TEXT"/>

Cómo exponer tus datos

Como se indicó anteriormente, se llama a onComplicationActivated() cuando se activa la fuente de datos. Este es un buen momento o lugar para realizar cualquier configuración básica que se debe establecer una vez por activación. No lo haremos en este codelab, ya que nuestro ejemplo es relativamente simple.

La llamada a onComplicationRequest() es donde la complicación activa solicita datos actualizados.

El método onComplicationRequest() se activa por varios motivos:

  • Se modificó una complicación de cara de reloj activa para usar esta fuente.
  • Se activa una complicación que usa esta fuente.
  • Activaste una actualización de tu propia clase mediante ComplicationDataSourceUpdateRequester.requestUpdate() o ComplicationDataSourceUpdateRequester.requestUpdateAll().
  • Transcurrió el tiempo que especificaste en el manifiesto

Abre CustomComplicationDataSourceService .kt y mueve el cursor hacia abajo hasta el método onComplicationRequest(). Borra la línea "return null" y, luego, copia y pega el siguiente código en la llamada Log.d() inicial:

// Retrieves your data, in this case, we grab an incrementing number from Datastore.
val number: Int = applicationContext.dataStore.data
    .map { preferences ->
        preferences[TAP_COUNTER_PREF_KEY] ?: 0
    }
    .first()

val numberText = String.format(Locale.getDefault(), "%d!", number)

En este caso, recuperaremos un elemento int almacenado del DataStore que representa nuestros datos. Fácilmente podría ser una llamada a tu base de datos.

Interactuar con un DataStore requiere una corrutina para controlar la recopilación de Flow que produce. Es probable que notes que onComplicationRequest() es una función suspend, por lo que podemos recopilar nuestros datos a través de Flow sin iniciar específicamente una corrutina.

Después de recuperar el valor entero, lo convertimos en una string simple a fin de que se prepare para convertirla en un objeto ComplicationData, es decir, un tipo de datos que la complicación comprenda.

Luego, copia y pega el código debajo del código que acabas de agregar.

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

En este código, se muestra un objeto ComplicationData según el tipo de complicación, es decir, se mostrará un ShortTextComplicationData (una subclase de ComplicationData) para el tipo de datos SHORT_TEXT.

Es posible que un tipo de datos determinado incluya campos diferentes. Por ejemplo, es posible que SHORT_TEXT sea solo texto, un título y texto o una imagen y texto monocromáticos (que deben incluir una descripción del contenido para ofrecer accesibilidad).

Para nuestro caso, solo configuramos el campo obligatorio, pero ningún campo opcional. Para obtener más información sobre estos tipos y campos, consulta nuestra documentación.

Puedes preguntar por qué usamos una sentencia when para crear los datos. Más adelante, admitiremos diversas formas de datos en función del tipo que solicite el sistema. Si usas una sentencia when ahora, más adelante, podemos agregar con facilidad nuevos tipos de datos (LONG_TEXT, RANGED_VALUE, etc.).

Por último, se muestra un valor nulo si no se admite el tipo de datos.

El método final debería verse de la siguiente manera:

override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
    Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")

    // Retrieves your data, in this case, we grab an incrementing number from Datastore.
    val number: Int = applicationContext.dataStore.data
        .map { preferences ->
            preferences[TAP_COUNTER_PREF_KEY] ?: 0
        }
        .first()

    val numberText = String.format(Locale.getDefault(), "%d!", number)

    return when (request.complicationType) {

        ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text = numberText).build(),
            contentDescription = PlainComplicationText
                .Builder(text = "Short Text version of Number.").build()
        )
            .build()

        else -> {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unexpected complication type ${request.complicationType}")
            }
            null
        }
    }
}

Vuelve a ejecutar la app

En el primer paso, aprendiste a instalar el servicio de datos de complicación en tu dispositivo o emulador. Ahora, es momento de volverlo a hacer. Instala tu app y vuelve a seleccionar la complicación, es decir, desliza la cara de reloj, selecciona el ícono de ajustes, dirígete a la misma complicación y selecciona el codelab de fuente de datos de complicación. Debería ver algo como esto:

caae484f1f2508fd.png

Resumen

En este paso, aprendiste lo siguiente:

  • Cómo especificar los tipos de datos que puede admitir la fuente
  • Con qué frecuencia se deben solicitar tus datos cuando los usa una complicación activa
  • Dónde exponer tus datos a Wear OS

Cuál es el próximo paso

Intentemos admitir un tipo de datos diferente.

3. Cómo activar actualizaciones de datos de complicación

Paso 3 del código

En este paso, activaremos actualizaciones en los datos cuando el usuario presione nuestra complicación.

Si, en algún momento, te confunden los conceptos que se analizan en este codelab, consulta el módulo complete y aprende a implementar estos pasos.

Cómo especificar la frecuencia con la que la complicación debería actualizar tus datos

Abre el archivo AndroidManifest.xml y vuelve a observar el servicio CustomComplicationDataSourceService.

Observa un campo UPDATE_PERIOD_SECONDS en el elemento meta-data. Especifica la frecuencia con la que quieres que el sistema busque actualizaciones de los datos cuando está activa tu fuente de datos.

En este momento, está configurada en 600 segundos (10 minutos). Como deseamos actualizar nuestra complicación en respuesta a una acción del usuario, queremos actualizar con mayor frecuencia. Si bien podríamos disminuir este período, es posible que el sistema no active actualizaciones para períodos inferiores a un par de minutos.

Un mejor enfoque es un "estilo push" en el que le decimos al sistema que se actualice con precisión cuando se hayan modificado los datos.

Cambia la frecuencia de actualización de 600 a 0, lo cual indica que haremos ping directamente al sistema cuando los datos cambien, en lugar de depender de actualizaciones periódicas. Ten en cuenta que los metadatos son un requisito.

<meta-data
    android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
    android:value="0"/>

Cómo informar al sistema que hay nuevos datos de complicación disponibles

Abre ComplicationTapBroadcastReceiver.kt. Esta clase BroadcastReceiver actualizará nuestros datos de complicación cuando se active. (Recuerda que estamos guardando los datos en un DataStore).

Esta clase también ofrece un método de ayuda que construye un PendingIntent (lo activa como BroadcastReceiver).

Por el momento, el método onReceive() extrae del intent el ID de la fuente de datos y de la complicación y actualiza el número entero en DataStore. Debemos indicarle a nuestra complicación que se actualizaron los datos.

Desplázate hasta el final del método onReceive(). Arriba del bloque final, deberías ver el comentario "Request an update for the…" Copia y pega el código que está debajo de ese comentario.

// Request an update for the complication that has just been tapped, that is,
// the system call onComplicationUpdate on the specified complication data
// source.
val complicationDataSourceUpdateRequester =
    ComplicationDataSourceUpdateRequester.create(
        context = context,
        complicationDataSourceComponent = dataSource
    )
complicationDataSourceUpdateRequester.requestUpdate(complicationId)

De esta manera, se le indica a Wear OS que se actualizaron los datos de nuestra complicación. Necesitamos tres datos para que funcione:

  • context: Context está disponible como un argumento para este método: onReceive().
  • complicationDataSourceComponent: El DataSource de tu complicación se pasa como un Extra de PendingIntent que activa este BroadcastReceiver.
  • complicationId: Es el número entero único asignado por una cara de reloj para la ubicación de la complicación. El int se pasa como un Extra del PendingIntent que activa este BroadcastReceiver.

Ya terminamos con este paso, y tu método final debería verse de la siguiente manera:

override fun onReceive(context: Context, intent: Intent) {

    // Retrieve complication values from Intent's extras.
    val extras = intent.extras ?: return
    val dataSource = extras.getParcelable<ComponentName>(EXTRA_DATA_SOURCE_COMPONENT) ?: return
    val complicationId = extras.getInt(EXTRA_COMPLICATION_ID)

    // Required when using async code in onReceive().
    val result = goAsync()

    // Launches coroutine to update the DataStore counter value.
    scope.launch {
        try {
            context.dataStore.edit { preferences ->
                val currentValue = preferences[TAP_COUNTER_PREF_KEY] ?: 0

                // Update data for complication.
                val newValue = (currentValue + 1) % MAX_NUMBER

                preferences[TAP_COUNTER_PREF_KEY] = newValue
            }

            // Request an update for the complication that has just been tapped, that is,
            // the system call onComplicationUpdate on the specified complication data
            // source.
            val complicationDataSourceUpdateRequester =
                ComplicationDataSourceUpdateRequester.create(
                    context = context,
                    complicationDataSourceComponent = dataSource
                )
            complicationDataSourceUpdateRequester.requestUpdate(complicationId)
        } finally {
            // Always call finish, even if cancelled
            result.finish()
        }
    }
}

Cómo agregar una acción de presión a nuestra complicación

Nuestro BroadcastReceiver no solo actualiza los datos, sino que también le informa al sistema que hay datos nuevos disponibles (consulta el paso anterior). Debemos agregar una acción de presión a nuestra complicación para activar el BroadcastReceiver.

Abre CustomComplicationDataSourceService.kt y desplázate hacia abajo hasta el método onComplicationRequest().

Debajo de la primera sentencia Log.d() y arriba de donde se recupera el valor entero de DataStore, copia y pega el siguiente código:

// Create Tap Action so that the user can trigger an update by tapping the complication.
val thisDataSource = ComponentName(this, javaClass)
// We pass the complication id, so we can only update the specific complication tapped.
val complicationPendingIntent =
    ComplicationTapBroadcastReceiver.getToggleIntent(
        this,
        thisDataSource,
        request.complicationInstanceId
    )

Recuerda que en el paso anterior necesitábamos estos datos para que funcione nuestro BroadcastReceiver (el ID de la fuente de datos y de la complicación). En este paso, pasamos ambos datos como adicionales con PendingIntent.

Luego, debemos asignar el PendingIntent al evento de presión para nuestra complicación.

Busca la sentencia when para ST y agrega esta línea sobre la llamada .build().

    .setTapAction(complicationPendingIntent)

Ahora, el bloque de código debería verse de la siguiente manera.

ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
    text = PlainComplicationText.Builder(text = numberText).build(),
    contentDescription = PlainComplicationText
        .Builder(text = "Short Text version of Number.").build()
)
    .setTapAction(complicationPendingIntent)
    .build()

Solo se agrega una línea, el método .setTapAction() que asigna nuestro nuevo PendingIntent a la acción de presión para la complicación.

Ya terminamos con este paso. El método final debería verse de la siguiente manera:

override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
    Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")

    // Create Tap Action so that the user can trigger an update by tapping the complication.
    val thisDataSource = ComponentName(this, javaClass)
    // We pass the complication id, so we can only update the specific complication tapped.
    val complicationPendingIntent =
        ComplicationTapBroadcastReceiver.getToggleIntent(
            this,
            thisDataSource,
            request.complicationInstanceId
        )

    // Retrieves your data, in this case, we grab an incrementing number from Datastore.
    val number: Int = applicationContext.dataStore.data
        .map { preferences ->
            preferences[TAP_COUNTER_PREF_KEY] ?: 0
        }
        .first()

    val numberText = String.format(Locale.getDefault(), "%d!", number)

    return when (request.complicationType) {

        ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text = numberText).build(),
            contentDescription = PlainComplicationText
                .Builder(text = "Short Text version of Number.").build()
        )
            .setTapAction(complicationPendingIntent)
            .build()

        else -> {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unexpected complication type ${request.complicationType}")
            }
            null
        }
    }
}

Vuelve a ejecutar la app

Instala tu app y vuelve a seleccionar la complicación, es decir, desliza la cara de reloj, selecciona el ícono de ajustes, dirígete a la misma complicación y selecciona la fuente del codelab de fuente de datos de complicación. Deberías ver lo mismo que antes. Sin embargo, ahora puedes presionar la complicación, y se actualizarán los datos.

a9d767e37161e609.png

Resumen

En este paso, aprendiste lo siguiente:

  • Cómo informarle al sistema que se actualizaron los datos de tu complicación
  • Cómo vincular un PendingIntent a una acción de presión en tu complicación

Cuál es el próximo paso

Intentemos admitir un tipo de datos diferente.

4. Cómo exponer datos de textos largos

Paso 4 del código

A medida que exponemos nuestros datos a las complicaciones, puede ser buena idea admitir más tipos de datos y verificar cómo se ven en las complicaciones.

Cómo especificar otro tipo de datos compatible

Vuelve a abrir el archivo AndroidManifest.xml y observa la declaración del servicio CustomComplicationDataSourceService.

Cambia SUPPORTED_TYPES del elemento meta-data de SHORT_TEXT a LONG_TEXT. El cambio debería verse de la siguiente manera:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="LONG_TEXT"/>

Cómo agregar compatibilidad con LONG TEXT

Abre CustomComplicationDataSourceService.kt, desplázate hacia abajo a la sentencia when en el método onComplicationRequest() y agrega el siguiente código debajo del final del caso TYPE_SHORT_TEXT y arriba del caso predeterminado.

ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
    text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
    contentDescription = PlainComplicationText
        .Builder(text = "Long Text version of Number.").build()
)
    .setTapAction(complicationPendingIntent)
    .build()

La sentencia when debería verse de la siguiente manera:

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Long Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

Quizá notaste que simplemente estamos modificando y volviendo a empaquetar los mismos datos en un nuevo formato. Observemos cómo se ve.

Cómo verificar tu progreso y depurar

Instala tu servicio, pero esta vez elige la complicación del espacio inferior antes de elegir la fuente del servicio de complicación:

518b646d3c3f3305.png

Deberías ver algo como la siguiente imagen. Ten en cuenta que cada complicación se almacena en una clave diferente, por lo que es posible que veas valores diferentes si estableciste la complicación en varias ubicaciones:

17ec0506f1412676.png

Resumen

En este paso, aprendiste lo siguiente:

  • Cómo cambiar y admitir diferentes tipos de datos de complicación

Cuál es el próximo paso

Queremos admitir otro tipo de datos antes de aplicar todos estos conocimientos en conjunto.

5. Cómo exponer datos de textos con rango

Paso 5 del código

Si bien exponemos nuestros datos a complicaciones, continuamos explorando cómo admitir más tipos de datos.

Cómo especificar otro tipo de datos compatible

Vuelve a abrir el archivo AndroidManifest.xml y observa el servicio CustomComplicationDataSourceService.

Cambia el elemento meta-data SUPPORTED_TYPES a RANGED_VALUE. El cambio debería verse de la siguiente manera:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="RANGED_VALUE"/>

Cómo agregar compatibilidad con RANGED VALUES

Los rangos con valores no solo pueden mostrar texto, sino también una imagen que revela qué tan lejos se encuentra tu valor entre el mínimo y el máximo. Este tipo de complicaciones es útil para mostrar cuánta batería queda en el dispositivo o cuántos pasos quedan para cumplir el objetivo.

1fe1943a5ad29076.png

Abre CustomComplicationDataSourceService .kt, mueve el cursor hacia la sentencia when en el método onComplicationRequest() y agrega este código en el caso TYPE_LONG_TEXT y arriba del caso predeterminado:

ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
    value = number.toFloat(),
    min = 0f,
    max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
    contentDescription = PlainComplicationText
        .Builder(text = "Ranged Value version of Number.").build()
)
    .setText(PlainComplicationText.Builder(text = numberText).build())
    .setTapAction(complicationPendingIntent)
    .build()

La sentencia when debería verse de la siguiente manera:

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Long Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
        value = number.toFloat(),
        min = 0f,
        max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
        contentDescription = PlainComplicationText
            .Builder(text = "Ranged Value version of Number.").build()
    )
        .setText(PlainComplicationText.Builder(text = numberText).build())
        .setTapAction(complicationPendingIntent)
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

Nuevamente, estamos modificando y volviendo a reempaquetar los mismos datos en un formato nuevo. Observemos cómo se ve.

Cómo verificar tu progreso y depurar

Instala tu servicio y elige otra ubicación.

461f8a704fbc6496.png

Ahora, debería verse de la siguiente manera:

ffa6ea8f2ed3eb2a.png

Puedes ver un círculo radial alrededor del número que destaca el equivalente de 3/20.

Resumen

En este paso, aprendiste lo siguiente:

  • Cómo cambiar y admitir diferentes tipos de datos de complicación

Cuál es el próximo paso

Para finalizar el codelab, habilitamos todas las variaciones de tipos de datos.

6. Cómo exponer los tres tipos de datos

Paso 6 del código

Ahora, nuestra fuente de datos de complicación admite tres variaciones de nuestros datos (RANGED_VALUE, SHORT_TEXT y LONG_TEXT).

En este último paso, le informaremos al sistema que admitimos las tres variaciones.

Cómo especificar varios tipos de datos compatibles

Vuelve a abrir el archivo AndroidManifest.xml y observa el servicio CustomComplicationDataSourceService.

Cambia SUPPORTED_TYPES del elemento meta-data por RANGED_VALUE,SHORT_TEXT,LONG_TEXT. El cambio debería verse de la siguiente manera:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT"/>

Cómo verificar tu progreso

Instala tu servicio.

b3a7c0c8063c2f60.png

En este caso, la cara de reloj prefiere el tipo de datos con rango en lugar de los tipos de texto corto y largo, pero si la complicación solo admite el tipo de texto corto, los datos continuarán apareciendo porque la cara de reloj admite los tres. Ten en cuenta que la misma cara de reloj especifica los tipos de datos que admite una complicación y el orden de preferencia de esos tipos.

Resumen

En este paso, aprendiste lo siguiente:

  • Cómo brindar compatibilidad con varios tipos de datos de complicación

7. ¡Listo! ¿Qué sigue?

Hay muchos más tipos de datos que puedes admitir en las complicaciones (lo que incluye imágenes pequeñas, imágenes grandes e íconos). Intenta implementar algunos de esos tipos por tu cuenta para extender este codelab.

Si deseas obtener más información sobre el desarrollo de complicaciones para caras de reloj y sobre cómo crear fuentes de datos de complicación, consulta Complicaciones de caras de reloj

Para obtener más información para desarrollar caras de reloj para Wear OS, visita https://developer.android.com/training/wearables/watch-faces/index.html