Раньше ты мог десятками лет наблюдать один и тот же экран старых аналоговых часов. То ли дело сейчас — распаковав коробку со своими первыми часами на Андроиде, ты начинаешь постоянно экспериментировать с циферблатами в надежде найти «тот самый». На одних будет информация о погоде, на других количество пройденных шагов, на третьих просто красивая картинка... А если не отыщется нужный, то можно написать свой собственный и вывести на экран какую хочешь информацию — от погоды и курса валют до счетчика оставшегося до дня рождения любимого кота времени. И мы тебе в этом сегодня поможем!

Свой циферблат
Свой циферблат

Написать такое приложение можно как при помощи Eclipse, так и в Android Studio. Я предпочитаю последнюю, поскольку в ней уже есть готовые шаблоны и примеры, к тому же ее рекомендует и поддерживает сама Google. Можно написать приложение только для часов, а можно и такое, которое будет обмениваться данными со смартфоном. Во втором случае мы на выходе получим один APK-файл для смартфона, в котором, как в матрешке, будет еще один APK для часов. Распаковка произойдет автоматически при установке.

 

Архитектура циферблата

Циферблат (Watch Face), находящийся на основном экране, является сервисом (наследник СanvasWatchFaceService), который в заданный период отрисовывает экран.

Список доступных циферблатов можно увидеть как на самих часах, так и на сопряженном смартфоне в приложении Android Wear.

Циферблаты в приложении Android Wear
Циферблаты в приложении 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).

Схема взаимодействия устройств
Схема взаимодействия устройств

Обмен данными можно реализовать через три метода:

  1. Data Items, общий объект, состояние которого автоматически синхронизируется между устройствами.
  2. Messages, сообщения, отправляемые устройствами друг другу.
  3. 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.

 

Архитектура проекта

В конечном итоге у нас получится проект из двух модулей — один для смартфона, другой для часов. В смартфонном модуле расположится сервис, который будет принимать и отправлять сообщения об уровне заряда батареи. В этом модуле можно смело реализовывать какую угодно функциональность, например скачивание из интернета прогноза погоды и отправку его на часы. В модуле часов у нас будет два сервиса — один для обмена сообщениями, другой для отрисовки циферблата.

Оставить мнение