Processing:Библиотеки/Processing for Android/Руководства/Циферблаты

Материал из Онлайн справочника
Версия от 11:56, 20 мая 2023; EducationBot (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску


Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.



Циферблаты[1]

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

Циферблаты

Операционная система Android Wear позволяет создавать кастомные циферблаты для смарт-часов, которые, используя возможности дисплея и интерактивные функции этих устройств, могут показывать время каким-либо нестандартным образом. Кроме того, вы можете считывать данные датчиков тела (шагомеров, пульсометров и т.д.), чтобы визуализировать физическую активность пользователя. Разработка циферблатов, впрочем, требует определенных опыта и знаний – из-за ограничений этих устройств, связанных с размером экрана и максимальным зарядом батареи. Руководства Google по созданию циферблатов можно почитать тут.

Подготовка

Во-первых, разработка циферблатов требует двух устройств – смарт-часов и смартфона, который будет служить «мостиком» между компьютером, на котором запущен Processing, и смарт-часами. Для этого вам нужно настроить в устройствах отладку через Bluetooth, и о том, как это сделать, можно почитать тут. Разобравшись с этим, кликните в PDE на Android > Watch Face.

После того, как вы настроите отладку Bluetooth и выберите в PDE опцию Watch Face, смарт-часов в списке подключенных устройств по-прежнему не будет. Это нормально, потому что циферблаты не устанавливаются в смарт-часы напрямую – сначала они устанавливаются на телефон, с которым сопряжены смарт-часы, а затем через Bluetooth автоматически копируются на смарт-часы.

Создание очень простого циферблата

Давайте создадим максимально простой циферблат, который будет просто показывать время при помощи текста. Структура этого скетча проста:

void setup() {
  fullScreen();
  frameRate(1);
  textFont(createFont("SansSerif", 30 * displayDensity));
  fill(255);
}

void draw() {
  background(0);
  translate(0, +wearInsets().bottom/2);
  if (!wearAmbient()) {
    String str = hour() + ":" + minute() + ":" + second();
    float w = textWidth(str);
    text(str, (width - w)/2, height/2 + 24);     
  }
}

В этом коде есть несколько любопытных вещей. Во-первых, это частота кадров в размере «1», поскольку текст будет меняться только раз в секунду и обновлять его чаще нет никакого смысла (тем более, что это будет расходовать заряд батареи). Кроме того, циферблат будет нарисован, только если встроенная функция wearAmbient() вернет false. Причина в том, что если она вернет true, то это значит, что человек, носящий эти смарт-часы, на них не смотрит, в результате чего они переключаются в режим ожидания (англ. «ambient mode»), чтобы сэкономить заряд батареи. В режиме ожидания дисплей обновляется только раз в минуту, и рекомендуется, чтобы большая часть экрана была черной и показывала только упрощенную версию циферблата.

Кроме того, мы используем в этом коде функцию wearInsets(), чтобы получить данные о вставках на экране. В частности, нижняя вставка позволяет правильно отцентрировать графику скетча на циферблатах с «подбородком» в нижней части экрана (вроде Moto 360) и в результате весь кадр, чтобы получить правильную отцентровку, сдвигается вниз на половину этого значения. Есть еще одна важная встроенная переменная, которую мы здесь не используем – это isRound, которая сообщает форму циферблата (т.е. квадратную или круглую). Полный список встроенных переменных для циферблатов смотрите в справочнике библиотеки Android for Processing.

Время показа

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

ArrayList<PVector> dots;
int totalMin = 24 * 60;

void setup() {
  fullScreen();
  frameRate(1);
  dots = new ArrayList<PVector>();
}

void draw() {
  int time = hour() * 60 + minute();
  if (time == 0) dots.clear();
  float x = map(time, 0, totalMin, 0, width);
  if (wearAmbient()) {
    background(0);
    noFill();
    stroke(255);    
    line(x, 0, x, height);
    for (PVector d: dots) {
      ellipse(d.x, d.y, 10, 10);
    }    
  } else {
    background(255);
    fill(0);
    noStroke();
    rect(0, 0, x, height);
    for (PVector d: dots) {
      ellipse(d.x, d.y, 10, 10);
    }    
  }
  
  for (int i = dots.size()-1; i >= 0; i--) {
    PVector d = dots.get(i);
    if (d.x < x) {
      dots.remove(i);
    }
  }  
} 

void mousePressed() {
  dots.add(new PVector(mouseX, mouseY));
}

Теперь давайте сделаем так, чтобы смарт-часы вибрировали с каждым разом, когда черная «пелена» поглощает добавленную пользователем точку! Чтобы получить доступ к вибрирующему механизму в смарт-часах, вам нужно включить соответствующее разрешение. Для этого в среде разработки Processing нужно нажать на Android > Sketch Permissions, а затем поставить галочку у опции VIBRATE.

Импортировав классы Vibrator и Context, инициализируем в блоке setup() экземпляр класса Vibrator:

import android.os.Vibrator;
import android.content.Context;
  
ArrayList<PVector> dots;
int totalMin = 24 * 60;
Vibrator vibrator;

void setup() {
  fullScreen();
  frameRate(1);
  dots = new ArrayList<PVector>();
  Context context = getContext();
  vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}

Метод vibrator() позволяет нам задать вибрацию на определенное время (в миллисекундах). Делаем вибрацию длиной в полсекунды:

for (int i = dots.size()-1; i >= 0; i--) {
    PVector d = dots.get(i);
    if (d.x < x) {
      dots.remove(i);
      vibrator.vibrate(500);
    }
  }

Счетчик шагов

Большинство устройств Android, включая смарт-часы, оснащены шагомером, доступ к которому можно получить тем же способом, которым мы пользовались в предыдущих руководствах для доступа к данным других датчиков. «Скелет» этого скетча будет выглядеть следующим образом:

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;

SensorManager manager;
Sensor sensor;
SensorListener listener;

void setup() {
  fullScreen();
  frameRate(1);
  
  Context context = getContext();
  manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
  sensor = manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);  
  listener = new SensorListener();  
  manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
}

void draw() {
}

public void resume() {
  if (manager != null) {
    manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
  }
}

public void pause() {
  if (manager != null) {
    manager.unregisterListener(listener);
  }
}

class SensorListener implements SensorEventListener {
  public void onSensorChanged(SensorEvent event) { }
  public void onAccuracyChanged(Sensor sensor, int accuracy) { }
}

В этом коде мы задаем менеджера, датчик и слушателя так же, как и в предыдущих похожих скетчах-примерах. Значение, хранящее в себе данные о насчитанных шагах – это event.values[0], которое мы можем сохранить в нашу собственную переменную.

int offset = -1;
int steps;

...

class SensorListener implements SensorEventListener {
  public void onSensorChanged(SensorEvent event) {
    if (offset == -1) offset = (int)event.values[0]; 
    steps = (int)event.values[0] - offset;
  }
  public void onAccuracyChanged(Sensor sensor, int accuracy) { }
}

Наконец, мы можем добавить в блок setup() инициализацию шрифта, а затем воспользоваться данными о посчитанных шагах в блоке draw(). К примеру, ниже они просто печатаются как текст:

void setup() {
  fullScreen();
  frameRate(1);

  textFont(createFont("SansSerif", 30 * displayDensity));
  textAlign(CENTER, CENTER);
  fill(255);  
  
  Context context = getContext();
  manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
  sensor = manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);  
  listener = new SensorListener();  
  manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);  
}

void draw() {
  background(0);
  translate(0, +wearInsets().bottom/2);
  if (!wearAmbient()) {
    String str = steps + " steps";
    float w = textWidth(str);
    text(str, 0, 0, width, height);     
  }
}

Вы, возможно, захотите сохранить данные о посчитанных шагах, чтобы отслеживать профиль активности пользователя. В языке Processing есть несколько функций для сохранения и загрузки данных в циферблат – к примеру, saveStrings() и loadStrings(). Впрочем, вам также нужно удостовериться, что у вас включено разрешение WRITE_EXTERNAL_STORAGE.

Примечание: Если вы имеете дело с опасным разрешением (вроде WRITE_EXTERNAL_STORAGE), то его запрос в коде нужно сделать явно – как объясняется в этом руководстве. После этого вам также надо дать соответствующее разрешение в самом устройстве – либо через уведомление, которое будет запущено циферблатом, либо перейдя в настройки разрешений для циферблата (о том, как это сделать, можно прочесть тут).

См.также

Внешние ссылки