Processing:Библиотеки/Processing for Android/Руководства/Циферблаты
Содержание | Среда разработки Processing | Справочник языка Processing | Библиотеки | Примеры | Режимы программирования |
Циферблаты[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), то его запрос в коде нужно сделать явно – как объясняется в этом руководстве. После этого вам также надо дать соответствующее разрешение в самом устройстве – либо через уведомление, которое будет запущено циферблатом, либо перейдя в настройки разрешений для циферблата (о том, как это сделать, можно прочесть тут).
См.также
Внешние ссылки
Примеры на Processing | |
---|---|
Основы |
|
Продвинутые графические эффекты |
|
Примеры из сторонних библиотек |