Раньше ты мог десятками лет наблюдать один и тот же экран старых аналоговых часов. То ли дело сейчас — распаковав коробку со своими первыми часами на Андроиде, ты начинаешь постоянно экспериментировать с циферблатами в надежде найти «тот самый». На одних будет информация о погоде, на других количество пройденных шагов, на третьих просто красивая картинка... А если не отыщется нужный, то можно написать свой собственный и вывести на экран какую хочешь информацию — от погоды и курса валют до счетчика оставшегося до дня рождения любимого кота времени. И мы тебе в этом сегодня поможем!
Написать такое приложение можно как при помощи Eclipse, так и в Android Studio. Я предпочитаю последнюю, поскольку в ней уже есть готовые шаблоны и примеры, к тому же ее рекомендует и поддерживает сама Google. Можно написать приложение только для часов, а можно и такое, которое будет обмениваться данными со смартфоном. Во втором случае мы на выходе получим один APK-файл для смартфона, в котором, как в матрешке, будет еще один APK для часов. Распаковка произойдет автоматически при установке.
Архитектура циферблата
Циферблат (Watch Face), находящийся на основном экране, является сервисом (наследник СanvasWatchFaceService), который в заданный период отрисовывает экран.
Список доступных циферблатов можно увидеть как на самих часах, так и на сопряженном смартфоне в приложении Android Wear.
Для уведомления системы о циферблате нужно описать в манифесте приложения сам сервис. При разработке надо учитывать особенности экранов (круглые или квадратные).
Пример описания сервиса в манифесте:
<service
android:name=".BatteryWatchFace"
android:label="@string/my_digital_name"
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_digital" />
<meta-data
android:name="com.google.android.wearable.watchface.preview_circular"
android:resource="@drawable/preview_digital_circular" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>
</service>
Циферблат может быть с настройками и без.
Для установки настроек циферблата нужно создать отдельный класс Activity и описать его в манифесте приложения. Настройки можно вызвать на часах или создать класс настроек для смартфона.
Описание этих настроек доступно тут и тут.
Обмен данными
Для обмена данными между устройствами используется специальный слой данных (Wearable Data Layer).
Физически обмен происходит по Bluetooth 4.0 и Wi-Fi.
Смартфон для работы с ним должен иметь версию ОС не ниже Android 4.3 (API Level 18).
Обмен данными можно реализовать через три метода:
- Data Items, общий объект, состояние которого автоматически синхронизируется между устройствами.
- Messages, сообщения, отправляемые устройствами друг другу.
- Asset, большой объект для отправки двоичных данных (например, картинка), прикрепляется к объекту типа Data Items.
Рассмотрим обмен сообщениями между устройствами подробнее.
Для прослушивания событий используется специальный сервис WearableListenerService.
Его нужно описать в манифесте:
<service android:name=".ListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
Сервис будет принимать сообщения и обрабатывать их в методе onMessageReceived.
Пример:
@Override
public void onMessageReceived(MessageEvent messageEvent) {
if (messageEvent.getPath().equals(WEAR_MESSAGE_PATH)) {
final String message = new String(messageEvent.getData());
if (message.equals("get_level")) {
WatchFace.sendMessage(this, getBatteryLevel(this));
return;
}
// Broadcast message to wearable activity for display
Intent messageIntent = new Intent();
messageIntent.setAction(Intent.ACTION_SEND);
messageIntent.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
} else {
super.onMessageReceived(messageEvent);
}
}
}
Для отправки сообщений нужно сначала подключиться к слою данных.
Подключение к слою:
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
googleClient.connect();
Потом в отдельном от UI потоке отправить сообщение.
Отправка сообщения:
if (googleClient.isConnected()) {
new Thread(new Runnable() {
@Override
public void run() {
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
for (Node node : nodes.getNodes()) {
Wearable.MessageApi.sendMessage(googleClient, node.getId(), WEAR_MESSAGE_PATH, param1.getBytes()).await();
}
}
}).start();
Отображение данных
Для создания собственного циферблата достаточно воспользоваться стандартным конструктором проектов в Android Studio, а после уже доработать его под свои нужды.
Готовый проект циферблата, который выводит на экран время и уровень заряда устройства, я выложил для тебя на гитхабе.
Основой для циферблата служит класс CanvasWatchFaceService.
В его методе onCreateEngine будет создан свой экземпляр класса Engine (наследник CanvasWatchFaceService.Engine)
Далее запустится циклический таймер, в котором будут обновляться значения времени.
Метод отображения на экран информации реализован в событии onDraw(Canvas canvas, Rect bounds). В нем нам дается холст и определяются его границы. Исходя из того, круглый у нас циферблат или квадратный, и нужно рисовать все, что нам захочется (текст, картинки, графические примитивы).
Подобную работу мы уже проделывали, когда с помощью стандартных средств рисовали игру Xonix в позапрошлом номере.
Следует обратить внимание, что часы имеют два состояния: активное и обтекаемое. Сделано это для экономии энергии, мы не будем отрисовывать часть элементов в обтекаемом режиме. Для выявления этих параметров есть событие onAmbientModeChanged(boolean inAmbientMode),
где входным параметром будет логический флаг inAmbientMode.
Архитектура проекта
В конечном итоге у нас получится проект из двух модулей — один для смартфона, другой для часов. В смартфонном модуле расположится сервис, который будет принимать и отправлять сообщения об уровне заряда батареи. В этом модуле можно смело реализовывать какую угодно функциональность, например скачивание из интернета прогноза погоды и отправку его на часы. В модуле часов у нас будет два сервиса — один для обмена сообщениями, другой для отрисовки циферблата.