El tutor de nuestro curso online de Desarrollo de Aplicaciones para Android, Víctor Ramírez Las,…

Desarrollo de diseños Watch Faces para smartwatch Android
2.
Desarrollo de diseños Watch Faces para smartwatch Android
En este publicación, se detallarán los pasos necesarios para el desarrollo e implementación de diseños Watch Faces para dispositivos smartwatch Android además de describir las directrices que se deberán tener en cuenta a la hora del diseño de la interfaz del reloj.
Como ya comentamos en la publicación anterior de esta serie, con la llegada de la nueva versión Android Lollipop, y la liberación de la API 21, se proporcionan las herramientas necesarias para un mayor acceso a la capa de diseño y configuración del dispositivo wearable. Dentro de esta nueva actualización, destaca la posibilidad de desarrollar nuevos diseños para la pantalla principal del dispositivo, y más concretamente la implementación de Watch Faces para la consulta de la hora.
Vamos por tanto a ver cómo desarrollar nuestros propios diseños para la interfaz principal del reloj, utilizando el IDE Android Studio:
Creación del proyecto
- Se creará un nuevo proyecto (File > New project… o en pantalla de bienvenida en la opción «Start a new Android Studio Project«), seleccionando tanto la plataforma de teléfonos y tablets (SDK mínimo API 18 con Android 4.3 o superior) como la plataforma wear (SDK mínimo API 21 con Android 5.0 o superior).
- A continuación, se indica la opción Add No Activity en las dos ventanas que solicite añadir tanto una Activity para la plataforma móvil, como para la plataforma wear.
- Una vez se ha construido el proyecto, si seleccionamos el listado «Project«, podrán apreciarse los módulos wear y mobile.
Dependencias
- Añadir las siguientes dependencias dentro de los archivo build.gradle de cada módulo:Módulo mobile:
12345678910apply plugin: 'com.android.application'android { ... }dependencies {...wearApp project(':wear')compile 'com.google.android.gms:play-services:6.5.+'}
12345678910apply plugin: 'com.android.application'android { ... }dependencies {...compile 'com.google.android.support:wearable:1.1.+'compile 'com.google.android.gms:play-services-wearable:6.5.+'}
La librería de servicios de Google Play (compile 'com.google.android.gms:play-services-wearable:6.5.+'
y compile 'com.google.android.gms:play-services:6.5.+'
), permite la sincronización de la capa de datos entre el dispositivo móvil y el smartwatch. Además, la librería de compatibilidad (compile 'com.google.android.support:wearable:1.1.+'
) proporciona las clases necesarias para el desarrollo de Watch Faces.
Permisos a declarar en AndroidManifest.xml
- Estos permisos deberán declararse tanto en el archivo AndroidManifest.xml del módulo «mobile» como del módulo «wear». Como se puede apreciar los permisos declarados permiten la gestión en segundo plano, y el control del uso de energía oscureciendo la pantalla o manteniendo el procesador en un estado de bloqueo:
12345678<manifest ... ><uses-permissionandroid:name = "com.google.android.permission.PROVIDE_BACKGROUND" /><uses-permissionandroid:name = "android.permission.WAKE_LOCK" />[...]</manifest>
Implementación del servicio
A la hora del desarrollo de Watch Faces, es imprescindible comprender que será necesaria la implementación de un servicio, que controle en todo momento la atenuación de la pantalla por inactividad, o incluso las notificaciones entrantes sincronizadas con el dispositivo. Para realizar esta tarea, se deberá heredar de la clase CanvasWatchFaceService
, y de la clase CanvasWatchFaceService.Engine
.
1 2 |
public class AnalogWatchFaceService extends CanvasWatchFaceService { |
- Proporciona el Watch Face implementado:
12345@Overridepublic Engine onCreateEngine() {return new Engine();}
- Implementación del servicio, que sobrescribe una serie de métodos:
12private class Engine extends CanvasWatchFaceService.Engine {
- Se inicializa Whatch Face:
1234@Overridepublic void onCreate(SurfaceHolder holder) {}
- Obtiene las funciones del dispositivo:
1234@Overridepublic void onPropertiesChanged(Bundle properties) {}
- Actualización de la hora:
1234@Overridepublic void onTimeTick() {}
- El dispositivo controla el cambio entre modos:
1234@Overridepublic void onAmbientModeChanged(boolean inAmbientMode) {}
- Método encargado de dibujar el diseño de la cara del reloj:
1234@Overridepublic void onDraw(Canvas canvas, Rect bounds) {}
- Watch Face se convierte en visible o invisible:
123456@Overridepublic void onVisibilityChanged(boolean visible) {}}}
Registro del servicio en AndroidManifest.xml en el módulo «wear»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[...] <!--Se define dentro del elemento application.--> <application... <service android:name=".AnalogWatchFaceService" android:label="@string/analog_name" android:allowEmbedded="true" android:taskAffinity="" android:permission="android.permission.BIND_WALLPAPER" > <meta-data android:name="android.service.wallpaper" android:resource="@xml/watch_face" /> <meta-data android:name="com.google.android.wearable.watchface.preview" android:resource="@drawable/preview_analog" /> <meta-data android:name="com.google.android.wearable.watchface.preview_circular" android:resource="@drawable/preview_analog_circular" /> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> <category android:name= "com.google.android.wearable.watchface.category.WATCH_FACE" /> </intent-filter> </service> </application> [...] |
Directrices de diseño para Watch Faces
Una de las principales premisas a la hora del diseño de un Watch Face, es controlar que el comportamiento del reloj diseñado, funcione correctamente en diferentes situaciones. Con este motivo, se describirán los aspectos más destacados para un correcto diseño de un Watch Face:
- Diseño compatible con dispositivos que presenten tanto pantallas que tengan formas redondas, como cuadradas.
- Integración con la capa de datos, que proporcione información sobre notificaciones o citas en el calendario, directamente desde la pantalla del reloj.
- Implementación de capa de configuración para la modificación del estilo, como pueden ser modificar los colores, e incluso añadir una imagen de fondo propia, realizando esta tarea tanto desde el smartwatch como desde el dispositivo móvil vinculado con la app Android Wear.
- Permitir que la funcionalidad del Wath Face diseñado no se vea alterada al recibir cualquier notificación del dispositivo vinculado (por ejemplo, que las agujas del reloj o los números sean visibles al recibir cualquier alerta).
- Soporte de los modos ambiente e interactivo, con diseños adaptados a conservar la batería del dispositivo, y por otro lado, diseños más acorde al uso de colores en el modo interactivo.
En la web de Android Developers, puedes encontrar información oficial adicional, para el diseño e implementación de Watch Faces
(créditos: las imágenes proceden de dicha documentación con licencia Creative Commons Attribution 2.5)
Capa de información en Watch Faces
Cuando un usuario accede a su dispositivo Android Wear, no sólo desea visualizar la hora del día, sino que gran parte de su atractivo consiste en mostrar información relevante, sincronizada con el dispositivo móvil vinculado, como pueden ser las diferentes notificaciones recibidas. Con el fin de comprender las posibilidades de comunicación con la capa de datos del dispositivo wearable, se describirá un ejemplo en tres simples pasos, para el proceso de mostrar información almacenada en el calendario, y todo esto desde la aplicación encargada de mostrar la hora:
- Definir una tarea que recupere los datos:
Para realizar este proceso, se deberá crear una clase dentro deCanvasWatchFaceService.Engine
, que herede de la clase baseAsynctask
, en la que una tarea asíncrona cargará las reuniones almacenadas en el calendario, a partir de un content provider, y devolverá el número con el métodoonMeetingsLoaded()
:
12345private class LoadMeetingsTask extends AsyncTask<Void, Void, Integer> {@Overrideprotected Integer doInBackground(Void... voids) {long begin = System.currentTimeMillis(); - La clase
WearableCalendarContract
, proporciona acceso directo a los eventos del calendario del dispositivo vinculado:
12345678Uri.Builder builder = WearableCalendarContract.Instances.CONTENT_URI.buildUpon();ContentUris.appendId(builder, begin);ContentUris.appendId(builder, begin + DateUtils.DAY_IN_MILLIS);final Cursor cursor = getContentResolver() .query(builder.build(), null, null, null, null);int numMeetings = cursor.getCount();return numMeetings;} - Devuelve el número de reuniones:
123456@Overrideprotected void onPostExecute(Integer result) {onMeetingsLoaded(result);}} - Creación de un temporizador personalizado:
A continuación, se deberá crear un temporizador que actualice periódicamente los datos. Para ello se instancia la claseHandler
, que enviará y procesará la cola de mensajes.
12345private class Engine extends CanvasWatchFaceService.Engine {[...]int mNumMeetings;private AsyncTask<Void, Void, Integer> mLoadMeetingsTask; - Handler que carga las reuniones almacenadas una vez por minuto en modo interactivo:
123456789101112131415final Handler mLoadMeetingsHandler = new Handler() {@Overridepublic void handleMessage(Message message) {switch (message.what) {case MSG_LOAD_MEETINGS:cancelLoadMeetingTask();mLoadMeetingsTask = new LoadMeetingsTask();mLoadMeetingsTask.execute();break;}}};[...]} - El siguiente método se encargará de inicializar el temporizador una vez que Watch Face es visible. Al invocar el método
sendEmptyMessage()
, mostrará el número de reuniones previstas del calendario en la aplicación del reloj:
1234567891011@Overridepublic void onVisibilityChanged(boolean visible) {super.onVisibilityChanged(visible);if (visible) {mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS);} else {mLoadMeetingsHandler.removeMessages(MSG_LOAD_MEETINGS);cancelLoadMeetingTask();}} - Redibujar Watch Face con los datos actualizados:
Con el siguiente método se controla que la tarea ha recuperado los datos, para posteriormente invocar al métodoinvalidate()
, que redibujará el Watch Face. La variablemNumMeetings
, variable miembro (variable declarada a nivel de clase, fuera de cualquier método o constructor), recibirá los datos, que ya podrán ser tratados directamente desde el métodoonDraw()
.
12345678910private void onMeetingsLoaded(Integer result) {if (result != null) {mNumMeetings = result;invalidate();}if (isVisible()) {mLoadMeetingsHandler.sendEmptyMessageDelayed(MSG_LOAD_MEETINGS, LOAD_MEETINGS_DELAY_MS);}}
Podrás acceder a ejemplos para la creación de Watch Faces (además de ejemplos para otros componentes y plataformas) desde Android Studio 1.0, a través de File > Import Sample…, y dentro del campo de búsqueda indicar «Watch Face». Además, desde la documentación oficial para desarrolladores Android, se recomienda utilizar la versión 1.0 o superior de Android Studio como entorno para la realización de proyectos sobre Android Wear.