Cómo agregar complicaciones a una cara de reloj

Una complicación de una cara de reloj muestra información de un proveedor de datos. Con la API de Complications, las caras de reloj pueden seleccionar los proveedores de datos que desean utilizar para obtener datos subyacentes. Esto permite que las caras de reloj muestren información independientemente de la hora del día, sin necesidad de utilizar código para obtener los datos.

La API de Complications también permite a los usuarios seleccionar los proveedores de datos que prefieran. Además, Wear OS by Google proporciona una interfaz de usuario para la selección de fuentes de datos.

Complicaciones

Para agregar complicaciones a una cara de reloj, haz lo siguiente:

Configura proveedores predeterminados para caras de reloj

Las caras de reloj pueden especificar proveedores predeterminados que se usan hasta que un usuario selecciona un proveedor. Establece los proveedores predeterminados usando el método setDefaultComplicationProvider() en WatchFaceService.Engine. Se puede llamar a este método en cualquier momento, pero no realizará ninguna acción si el usuario ya seleccionó un proveedor para la complicación en cuestión.

Para la mayoría de los proveedores, se debe otorgar el permiso RECEIVE_COMPLICATION_DATA a una cara de reloj antes de transferir datos. No obstante, se considera que algunos proveedores de sistemas son seguros, ya que solo proporcionan información que la cara de reloj pudo obtener por sí misma. Los proveedores seguros no requieren que la cara de reloj tenga el permiso para datos que se enviarán (consulta Proveedores de sistemas). Es preferible usar estos proveedores como valores predeterminados, ya que pueden proporcionar datos de inmediato.

Como alternativa, si se asocia una cara de reloj con un proveedor específico y esta desea usarlo como predeterminado, puede solicitar que el proveedor la indique como una cara de reloj segura.

Proveedores de sistemas

El sistema incluye proveedores que se pueden usar como predeterminados. El método setDefaultSystemComplicationProvider() de la clase WatchFaceService.Engine establece un proveedor de sistema predeterminado para una complicación. Este método toma un ID (como un valor entero) que representa a un proveedor de sistemas. Los ID disponibles se detallan en la clase SystemProviders.

La siguiente tabla contiene información detallada sobre algunos de los proveedores de sistemas admitidos:

Nombre del método en la clase SystemProviders Seguridad Puede ser el predeterminado Notas
dateProvider() Es el proveedor de fecha del sistema estándar. Al presionar, se abre la app estándar de Agenda.
currentTimeProvider() Es el proveedor estándar de "hora y fecha" del sistema. No hay acción de toque.
batteryProvider() Es el proveedor de batería estándar del sistema. No hay acción de toque.
stepCountProvider() Muestra el total diario de pasos, tal como lo informa readDailyTotal.
unreadCountProvider() Muestra la cantidad de notificaciones no leídas en el flujo.
worldClockProvider() La selección predeterminada será Londres o Nueva York. Se puede presionar para cambiar la zona horaria.
appsProvider() Primero mostrará un ícono de "apps", que se puede presionar para seleccionar una app.
nextEventProvider() No Sí (pero no es un proveedor seguro) Es el proveedor de "próximo evento" estándar del sistema. Al presionar, se abre la app estándar de Agenda.

Permite que los usuarios seleccionen proveedores de datos

Wear OS proporciona una interfaz de usuario (a través de una Actividad) que permite que los usuarios seleccionen proveedores para una complicación específica. Las caras de reloj pueden llamar al método createProviderChooserHelperIntent a fin de obtener un intent que se puede usar para mostrar la interfaz del selector.

Cuando una cara de reloj llama a createProviderChooserHelperIntent, esta proporciona un ID de complicación y una lista de tipos compatibles. Los tipos se deben indicar por orden de preferencia, generalmente con los que ofrezcan más información (como el valor de intervalos) en una posición de mayor preferencia.

Cuando el usuario selecciona un proveedor de datos, se guarda automáticamente la configuración; no se requiere nada más de la cara de reloj.

Observa el ejemplo de la app de Watch Face y accede al código completo recomendado para la interfaz de usuario de configuración.

Ese código incluye lo siguiente:

  • Una interfaz estándar para la configuración de complicaciones
  • Acceso sencillo a otras configuraciones

Un punto de partida para revisar el código es la clase AnalogComplicationConfigActivity (tiene un método getDataToPopulateAdapter() que muestra una lista de las entradas de configuración disponibles en la IU).

Cómo abrir el selector de proveedores

Una cara de reloj debe tener el siguiente permiso para recibir datos de complicación y abrir el selector de proveedores:

    com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
    

Si a una cara de reloj no se le otorga el permiso anterior, no podrá iniciar el selector de proveedores.

Para facilitar la solicitud del permiso y el inicio del selector, se encuentra disponible la clase ComplicationHelperActivity en la biblioteca de compatibilidad de wearables. En aproximadamente todos los casos, para iniciar el selector, se debe usar esta clase en lugar de ProviderChooserIntent.

Cómo solicitar el permiso necesario

Para usar ComplicationHelperActivity, agrégala a la cara de reloj en el archivo de manifiesto:

    <activity android:name="android.support.wearable.complications.ComplicationHelperActivity"/>
    

Para iniciar el selector de proveedores, llama al método ComplicationHelperActivity.createProviderChooserHelperIntent a fin de obtener un intent.

El nuevo intent se puede usar con startActivity o startActivityForResult para iniciar el selector.

A continuación, te mostramos un ejemplo de uso del nuevo intent con startActivityForResult:

Kotlin

    startActivityForResult(
            ComplicationHelperActivity.createProviderChooserHelperIntent(
                    activity,
                    watchFace,
                    complicationId,
                    ComplicationData.TYPE_LARGE_IMAGE
            ),
            PROVIDER_CHOOSER_REQUEST_CODE
    )
    

Java

    startActivityForResult(
      ComplicationHelperActivity.createProviderChooserHelperIntent(
         getActivity(),
         watchFace,
         complicationId,
         ComplicationData.TYPE_LARGE_IMAGE),
      PROVIDER_CHOOSER_REQUEST_CODE);
    

Cuando se inicia la actividad auxiliar, esta comprueba si se otorgó el permiso. Si no se lo otorgó, la actividad auxiliar realizará una solicitud de permiso durante el tiempo de ejecución. Si se acepta la solicitud (o si no es necesaria), se mostrará el selector de proveedor.

Si se usó startActivityForResult con el intent, el resultado entregado a la Actividad que realiza la llamada tendrá un código de resultado de RESULT_OK si se configuró correctamente un proveedor, o bien RESULT_CANCELLED si no se configuró ninguno.

Cuando se establezca un proveedor, se incluirá la clase ComplicationProviderInfo para el proveedor seleccionado en el intent de datos del resultado como elemento adicional con la clave ProviderChooserIntent#EXTRA_PROVIDER_INFO.

Cómo recibir datos de complicación

Para comenzar a recibir datos de complicación, una cara de reloj llama a setActiveComplications() en la clase WatchFaceService.Engine con una lista de ID de complicaciones de cara de reloj. Una cara de reloj crea estos ID para identificar de forma exclusiva las ranuras en las que pueden aparecer complicaciones y los pasa al método createProviderChooserIntent() a fin de permitir que el usuario decida qué complicación debe ir en cada ranura. Los datos de complicación se envían a través de la devolución de llamada onComplicationDataUpdate().

En general, las caras de reloj necesitan el permiso anterior para poder recibir datos de complicación, pero hay algunas excepciones. Específicamente, una cara de reloj solo puede recibir datos de un proveedor si se da una de las siguientes condiciones:

  • El proveedor es un proveedor de sistemas "seguro".
  • El proveedor y la cara de reloj pertenecen a la misma app.
  • El proveedor incluye en la lista blanca la cara de reloj como un elemento "seguro".
  • La cara de reloj tiene el permiso.

En caso de que no se cumpla ninguna de las condiciones anteriores, si un proveedor normalmente envía ComplicationData a una cara de reloj, el sistema envía como alternativa datos de tipo TYPE_NO_PERMISSION, que incluye un ícono (un signo de exclamación) y texto corto ("--") para permitir su representación como si fuera de tipo de texto corto o tipo de ícono, por cuestiones de conveniencia.

Cuando una cara de reloj recibe datos de TYPE_NO_PERMISSION, debe representar esto correctamente, de modo que el usuario pueda ver que se debe hacer algo para que funcione la complicación. Si fuera posible, con solo presionar una complicación en este estado, debería iniciarse una solicitud de permiso. Esto se puede hacer usando ComplicationHelperActivity.createPermissionRequestHelperIntent(), si se agregó la actividad auxiliar a la app de cara de reloj.

Si un usuario acepta la solicitud de permiso creada por la actividad auxiliar, se solicitarán actualizaciones para todas las complicaciones activas en la cara de reloj de forma automática, lo que permitirá que se reemplacen los datos de TYPE_NO_PERMISSION por información real.

Cómo renderizar complicaciones

La cara de reloj puede renderizar los datos de la forma deseada, siempre que se representen los campos previstos (se deben incluir los campos obligatorios en todo momento). Según el tipo, también se pueden incluir algunos campos opcionales (consulta la columna "Notas" de la que tabla que aparece a continuación).

Proporcionamos pautas de diseño para nuestro estilo, como sugerencias para complicaciones estándares, pero los desarrolladores pueden usar sus propios estilos o incorporar los datos a la cara de reloj de diferentes maneras.

Cómo diseñar complicaciones

La clase ComplicationDrawable te permite representar una complicación completa en un lienzo.

Admite los seis tipos de complicación principales y hace lo siguiente:

  • Controla todos los aspectos de diseño y estilo para las complicaciones.
  • Diseña fondos, íconos, texto, etc. dentro de los límites establecidos.
  • Te permite configurar muchas opciones, entre las que se incluyen: color de fondo, forma y radio de las esquinas, borde (o ausencia de este), color de texto y tipo de letra.
  • Decodifica y guarda imágenes en caché.

Si el nivel de API de destino es 24, se puede definir un objeto ComplicationDrawable en XML como recurso. También puedes crear un objeto ComplicationDrawable de manera programática. Debes usar draw() a fin de diseñar una complicación y configurar las opciones de estilo para los modos ambiente e interactivo.

ComplicationDrawable usará íconos e imágenes de protección de pantalla si se los proporcionó y si los requiere el dispositivo. Para habilitar esto, llama al método ComplicationDrawable.setBurnInProtection() cuando se reciban las propiedades del dispositivo.

Si deseas obtener instrucciones detalladas y ejemplos para diseñar complicaciones, consulta ComplicationDrawable, que incluye XML de ejemplo. Para acceder a un ejemplo de cara de reloj que utilice esta clase e incluya XML de ejemplo, consulta el ejemplo AnalogComplicationWatchFaceService en el ejemplo de app de Watch Face.

Si no utilizas un objeto ComplicationDrawable, usa TextRenderer para el texto de una complicación.

Cómo renderizar texto

La clase TextRenderer está pensada para usarse en complicaciones y facilita el diseño de texto en un lienzo. Incluye estas características:

  • Si no entran siete caracteres en los límites del tamaño de texto solicitado (la cantidad máxima en el campo de texto corto), la clase reducirá el tamaño del texto hasta que entre.
  • El texto puede ocupar una cantidad de líneas especificada.
  • Si no entra, se puede acortar.
  • La representación se ajusta para una pantalla siempre visible (modo ambiente).

Cuando inicializas el motor de tu cara de reloj, puedes crear un objeto TextRenderer y pasar el TextPaint que quieras que use TextRenderer. El objeto TextPaint define, entre otras opciones, la fuente, el tamaño del texto y el color. Debes crear un objeto TextRenderer para cada campo (p. ej., uno para un campo de texto y otro para uno de título).

Para acceder a código de ejemplo, incluido el necesario para especificar límites en el texto que quieras renderizar, consulta TextRenderer.

Cómo presionar complicaciones

Use el método ComplicationDrawable.onTap() para permitir que tu cara de reloj pase los eventos de toque a complicaciones. Este método se basa en la funcionalidad en la que un toque en la cara de reloj activa el método WatchFaceService.Engine.onTapCommand().

Puede pasar coordenadas a un objeto ComplicationDrawable con una llamada a onTap. Esto iniciará la acción asociada con el ComplicationDrawable que contiene las coordenadas de toque. Cuando se llame al método, si un ComplicationDrawable inició la acción asociada, recibirás un valor de resultado verdadero.

Usa el método setHighlightDuration() para establecer el tiempo que una complicación permanecerá destacada luego de que se llame al método onTap.

Si no usas ComplicationDrawable para una complicación, deberás detectar toques y activar la acción de toque PendingIntent tú mismo. Consulta Cómo crear caras de reloj interactivas para aprender a crear elementos que respondan a los toques de los usuarios.

Tipos de complicaciones

Los tipos de complicaciones determinan la clase de datos que se muestran en una complicación. Por ejemplo, el tipo SHORT_TEXT está disponible cuando los datos clave conforman una string corta. En el ejemplo de SHORT_TEXT, los datos opcionales son un ícono y un título corto.

Los proveedores de datos usan estos tipos de complicaciones de forma diferente en comparación con los de caras de reloj:

  • Un proveedor de datos selecciona los tipos de datos de complicaciones que proporcionará. Por ejemplo, un proveedor de conteo de pasos podría admitir los tipos RANGED_VALUE y SHORT_TEXT, mientras que un proveedor de "próxima reunión" podría admitir SHORT_TEXT y LONG_TEXT. El proveedor de datos también selecciona los campos opcionales de esos tipos que incluirá.
  • Un proveedor de caras de reloj selecciona la cantidad de tipos de complicaciones que admitirá. Por ejemplo, una complicación redonda en una cara de reloj podría admitir los tipos SHORT_TEXT, ICON y RANGED_VALUE, mientras que un medidor podría admitir solo RANGED_VALUE.

Un objeto ComplicationData siempre tendrá un solo tipo de complicación. Cada tipo de complicación tiene campos obligatorios y opcionales. Por lo general, un campo obligatorio representa los datos más importantes; la mayoría de los tipos toman su nombre del campo obligatorio.

Un tipo determinado puede incluir diferentes conjuntos de campos. Por ejemplo, SHORT_TEXT puede ser solo texto, un título y texto, o un ícono y texto. Una complicación compatible con un tipo determinado debe poder mostrar todas las variantes previstas. No obstante, no es necesario mostrar algunos campos opcionales (consulta la columna Notas de la siguiente tabla). Por ejemplo, el campo "Short title" del tipo RANGED_VALUE no es obligatorio, de modo que, por ejemplo, es posible mostrar medidores sin texto.

Ejemplos de tipos de complicaciones

A continuación, se muestran ejemplos de tipos de complicaciones:

Tipos de complicaciones

Tipos y campos

En la siguiente tabla, se describen los tipos y campos del objeto ComplicationData. Si una cara de reloj solicita un campo que no es válido para un tipo de complicación, se mostrará un valor predeterminado. Por ejemplo, si una cara de reloj intenta acceder a un campo Long text en un tipo SHORT_TEXT, se mostrará el valor predeterminado del campo Long text (null).

Tipo Campos obligatorios Campos opcionales Notas
SHORT_TEXT Short text Icon
Burn-in protection icon
Short title
Se prevé que se muestre "Icon" o "Short title" si se proporciona uno de ellos o ambos.
ICON Icon Burn-in protection icon Se usa cuando no se necesita texto. Se prevé que el ícono sea de un solo color y que lo ajuste la cara de reloj.
RANGED_VALUE Value
Min value
Max value
Icon
Burn-in protection icon
Short text
Short title
No se garantiza que se muestren los campos opcionales. Si prefieres dibujar tu propia barra de progreso, puedes usar el método setRangedValueProgressHidden() para ocultar la barra que proporciona la clase ComplicationDrawable.
LONG_TEXT Long text Long title
Icon
Burn-in protection icon
Small image
Se prevé que se muestre un título si se proporciona.
SMALL_IMAGE Small image Una imagen pequeña puede tener dos estilos: de foto o de ícono. El estilo de foto implica que debe llenar el espacio y se puede recortar; el de ícono, que no se debe recortar y que se puede rellenar. La variabilidad de la imagen puede producir una imagen no apta para exhibición en el modo ambiente en dispositivos con protección de pantalla o en modo ambiente con baja velocidad de bits. Cuando están habilitados la protección de pantalla o el modo ambiente con baja velocidad de bits, la cara de reloj puede usar Burn-in protection small image, ya que es seguro. De lo contrario, debido a que para una cara de reloj es difícil determinar la aptitud, no debería mostrarse la imagen.
LARGE_IMAGE Large image Se prevé que esta imagen sea suficientemente grande como para llenar la cara de reloj. La variabilidad de la imagen puede producir una imagen no apta para exhibición en el modo ambiente en dispositivos con protección de pantalla o en modo ambiente con baja velocidad de bits. Debido a que es difícil para una cara de reloj determinar si una imagen es apta para mostrar, no debe mostrar una imagen en modo ambiente si se habilita la protección de pantalla o el modo ambiente con baja velocidad de bits.

Los tipos que se indican en la siguiente tabla corresponden a datos vacíos y se pueden enviar para cualquier ranura de complicación. No tienen campos y no es necesario incluirlos en una lista de tipos compatibles. Permiten a las caras de reloj diferenciar entre estos tres casos:

  • No se seleccionó ningún proveedor.
  • El usuario seleccionó "empty" para una ranura.
  • Un proveedor no tiene datos para enviar.

Los proveedores no deben enviar TYPE_EMPTY en respuesta a solicitudes de actualización. En su lugar, deben enviar TYPE_NO_DATA.

Los detalles correspondientes a los tipos de complicaciones para datos "vacíos" se encuentran en la siguiente tabla:

Tipo de complicación Descripción
TYPE_NOT_CONFIGURED Lo envía el sistema cuando se activa una complicación y el usuario no selecciona un proveedor o no se establece un valor predeterminado.

No lo pueden enviar los proveedores.

TYPE_EMPTY Lo envía el sistema cuando se activa una complicación y el usuario selecciona "empty" en lugar de un proveedor, o bien cuando la cara de reloj no selecciona un proveedor ni este tipo como valor predeterminado.

No lo pueden enviar los proveedores.

TYPE_NO_DATA Lo envía el sistema cuando se activa una complicación (que tiene un proveedor) para borrarla antes de que el proveedor envíe datos reales.

Lo deben enviar los proveedores si no tienen datos reales para enviar.

Cómo usar campos para los datos de una complicación

Los campos de un objeto ComplicationData tienen funciones diferentes. Por ejemplo, un campo de texto contiene los datos primarios mientras que uno de título es descriptivo; una complicación de conteo de pasos puede tener un valor de campo de texto de "2,543" con un valor de campo de título de "pasos".

La siguiente tabla contiene descripciones de los campos de un objeto ComplicationData. Pueden completarse o no, según el tipo de complicación.

Campo Descripción
Short text Es el campo de texto principal para complicaciones pequeñas. La longitud máxima de este campo no debe superar los siete caracteres (incluido el texto temporal). Se prevé que las caras de reloj tengan la capacidad de representar cualquier string de siete caracteres. Las strings varían respecto del ancho, según los caracteres que se utilicen. Una cara de reloj debe ajustar el tamaño del texto para permitir que quepa en la complicación. Si el texto supera los siete caracteres, podría truncarse.
Icon Es una imagen de un solo color que representa los datos o su fuente. Debe poder ajustarse el tono de su color. Se recomienda usar diseños vectoriales para este campo.
Burn-in protection icon Es un campo que permite que se muestre un ícono en el modo ambiente en dispositivos que usan protección de pantalla. En el modo ambiente, las caras de reloj en dispositivos que usan protección de pantalla no deben mostrar bloques sólidos de píxeles. El campo Burn-in protection icon es opcional para cualquier tipo de complicación que incluya icon. El campo Burn-in protection icon no debe contener bloques sólidos de píxeles. Los proveedores deben proporcionar el campo Burn-in protection icon si su ícono estándar no es adecuado para la protección de pantalla. Una cara de reloj que se represente en el modo ambiente en un dispositivo con protección de pantalla debe usar el campo Burn-in protection icon, si está disponible, en lugar de icon.
Burn-in protection small image Es el campo que permite que se muestre una imagen en el modo ambiente en dispositivos que usan protección de pantalla. En el modo ambiente, las caras de reloj en dispositivos que usan protección de pantalla no deben mostrar bloques sólidos de píxeles. El campo Burn-in protection small image es opcional para cualquier tipo de complicación que incluya un campo small image. El campo Burn-in protection small image no debe contener bloques sólidos de píxeles. Los proveedores deben proporcionar el campo Burn-in protection small image si su imagen pequeña estándar no es adecuada para la protección de pantalla. Una cara de reloj que se represente en el modo ambiente en un dispositivo con protección de pantalla debe usar el campo Burn-in protection small image, si está disponible, en lugar de small image.
Short title Campo descriptivo para complicaciones pequeñas. Solo tiene relevancia si se combina con el campo Short text. La longitud máxima de este campo no debe superar los siete caracteres (incluido el texto temporal). Se prevé que las caras de reloj tengan la capacidad de representar cualquier string de siete caracteres. Las strings varían respecto del ancho, según los caracteres que se utilicen. Una cara de reloj debe ajustar el tamaño del texto para permitir que quepa en la complicación. Si el texto supera los siete caracteres, podría truncarse.
Long text Es el campo de datos principal para complicaciones amplias basadas en texto.
Long title Es el campo descriptivo para complicaciones amplias basadas en texto. Solo tiene relevancia si se combina con Long text.
Value Es la representación numérica (decimal) de los datos. Se prevé que se represente de acuerdo con los límites de los campos Min value y Max value (aunque no es obligatorio que se encuentre dentro de esos límites).
Min value Es el límite inferior correspondiente al rango dentro del que se debe representar Value. Solo tiene relevancia si se combina con Value y Max value.
Max value Es el límite superior correspondiente al rango dentro del que se debe representar Value. Solo tiene relevancia si se combina con Value y Min value.
Small image Es una imagen pequeña para representar los datos o su fuente. Puede estar en color. No se prevé que ocupe toda la cara de reloj.
Large image Imagen con suficiente resolución para ocupar la cara de reloj. Puede estar en color.

Cómo probar tipos de complicación

Cada tipo de complicación tiene campos, como los de texto e íconos. Si tu cara de reloj admite un tipo de complicación, debes admitir todas las combinaciones de campos válidas.

Puedes probar la manera en la que se muestran los datos de complicación en una cara de reloj. Específicamente, un conjunto de pruebas te permite evaluar la representación de los tipos de complicaciones. Por lo tanto, no es necesario escribir código a fin de probar las combinaciones de campos válidas para un objeto ComplicationData.

El conjunto de pruebas es un proveedor de datos, disponible como ejemplo, que alterna las combinaciones de campos válidas para un tipo de complicación determinado.

Para usar este conjunto de pruebas, haz lo siguiente:

  1. Instala el APK del conjunto de pruebas en un dispositivo o emulador.
  2. Accede a tu cara de reloj y presiona su ícono de configuración principal.
  3. Usa la IU de configuración para elegir el conjunto de pruebas WearComplication-ProviderTestSuite.
  4. Selecciona un tipo de datos de complicación para probarlo.
  5. Presiona tu complicación para ver las variaciones del tipo de datos.
  6. Presiónala repetidamente a fin de verificar que se muestren de forma correcta todas las combinaciones de campos pertinentes.

Por ejemplo, si una complicación admite texto corto, presiónala para ver todas las combinaciones de campos principales para texto corto.