- PVSM.RU - https://www.pvsm.ru -
С наращиванием функциональности и увеличением сложности приложения возникает необходимость дать пользователю возможность самому настраивать необходимые ему параметры. Приложение в свою очередь должно уметь сохранять эти настройки и предоставить пользователю интерфейс для управления ими. Какие средства и возможности для этого дали нам разработчики Pebble?
Документация у проекта Pebble хорошая и целью изложенного не является её дублирования. Это попытка собрать то, что касается хранения данных и возможностей по конфигурированию приложения в одном месте. Далее присутствуют краткие выдержки из документации и немного кода в виде примера проекта.
Разработчики предусмотрели следующие варианты хранить данные приложения:
PebbleKit JavaScript позволяет отобразить на экране смартфона окно конфигурации (web-приложение) размещенное и доступное по определенному разработчиком URL'у. [3] [3]
После завершения работы пользователя с web-приложением, оно вызывает особый URL «pebblejs://close» и передает в мобильное приложение необходимые данные.
Для полноценной работы приложения с настройками необходимо реализовать следующее:
Обо всем по порядку, добавим в простое приложение, которое показывает на экране время, следующие опции:
Настройки будем хранить не отдельными параметрами, а в структуре.
Данные, по рекомендации из документации, будем упаковывать, так как компилятор каждое поле структуры выравнивает по границе 32 bit.
Также зададим значения по умолчанию — вибрировать при смене статуса bluetooth соединения и молчать при смене минут:
#define STORAGE_KEY 99
typedef struct persist {
bool vibe_bt;
bool vibe_min;
} __attribute__((__packed__)) persist;
persist settings = {
.vibe_bt = true,
.vibe_min = false
};
Чтение и запись данных будет выглядеть следующим образом:
/*...*/
persist_read_data(STORAGE_KEY, &settings, sizeof(settings));
/*...*/
persist_write_data(STORAGE_KEY, &settings, sizeof(settings));
Задаем обработчики событий, подписываемся и отписываемся от событий, добавляем чтение из хранилища при старте приложения и запись при завершении его работы:
static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {
/*...*/
if ((units_changed & MINUTE_UNIT) && (settings.vibe_min)) {
vibes_double_pulse();
};
}
void bt_handler(bool connected) {
if (settings.vibe_bt) {
vibes_long_pulse();
};
}
static void init(void) {
if (persist_exists(STORAGE_KEY)) {
persist_read_data(STORAGE_KEY, &settings, sizeof(settings));
} else {
persist_write_data(STORAGE_KEY, &settings, sizeof(settings));
};
/*...*/
window_stack_push(window, animated);
tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);
bluetooth_connection_service_subscribe(bt_handler);
}
static void deinit(void) {
/*...*/
persist_write_data(STORAGE_KEY, &settings, sizeof(settings));
tick_timer_service_unsubscribe();
bluetooth_connection_service_unsubscribe();
}
Теперь, когда приложение умеет сохранять состояние своих настроек, переходим к организации хранилища на телефоне.
Для отображения значка шестеренки по клику на который вызывается окошко с настройками необходимо включить соотвествующую опцию в appinfo.json:
{
/* ... */
"capabilities": [ "configurable" ],
/* ... */
}
Нажатие на шестеренку генерирует событие showConfiguration, в WebView загружается страничка указанная в обработчике pebble-js-app.js:
Pebble.addEventListener('showConfiguration',
function(e) {Pebble.openURL("http://domain.tld/index.html"); })
Для примера простой интерфейс из двух чекбоксов и кнопки «Submit», их даже не принципиально «оборачивать» в форму.
Сначала считываем значения из localStorage и в соответствии с этим расставляем галочки на чекбоксах, если параметр отсутствует в хранилище инициализируем его значением по умолчанию:
<script>
$().ready(function() {
var vibe_bt = parseInt(localStorage.getItem("vibe_bt"));
var vibe_min = parseInt(localStorage.getItem("vibe_min"));
if (isNaN(vibe_bt)) {
vibe_bt = 1;
};
if (vibe_bt) {
$('#vibe_bt').prop('checked', true);
} else {
$('#vibe_bt').prop('checked', false);
};
if (isNaN(vibe_min)) {
vibe_min = 0;
};
if (vibe_min) {
$('#vibe_min').prop('checked', true);
} else {
$('#vibe_min').prop('checked', false);
};
});
/*...*/
</script>
Отслеживаем нажатие кнопки и отправляем в приложение выбор пользователя, попутно сохраняя новые значения в хранилище:
<script>
/*...*/
var submitButton = document.getElementById("b_submit");
submitButton.addEventListener("click",
function() {
localStorage.setItem("vibe_bt",
$('#vibe_bt').prop('checked') ? 1 : 0);
localStorage.setItem("vibe_min",
$('#vibe_min').prop('checked') ? 1 : 0);
var result = {
vibe_bt: $('#vibe_bt').prop('checked') ? 1 : 0,
vibe_min: $('#vibe_min').prop('checked') ? 1 : 0,
};
var location = "pebblejs://close#"+JSON.stringify(result);
document.location = location;
},
false);
</script>
Полный код страничики, не обошлось без jquery для выполнения кода при открытии страницы:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="js/jquery/jquery.min.js"></script>
<title>Configuration window</title>
<style>
</style>
</head>
<body>
<div>
<div>
<input id="vibe_bt" type="checkbox" checked />
<span>vibe bluetooth on/off</span>
</div>
<div>
<input id="vibe_min" type="checkbox" checked />
<span>vibe every minute</span>
</div>
<div>
<input id="b_submit" type="submit" value="Save" />
</div>
</div>
<script>
$().ready(function() {
var vibe_bt = parseInt(localStorage.getItem("vibe_bt"));
var vibe_min = parseInt(localStorage.getItem("vibe_min"));
if (isNaN(vibe_bt)) {
vibe_bt = 1;
};
if (vibe_bt) {
$('#vibe_bt').prop('checked', true);
} else {
$('#vibe_bt').prop('checked', false);
};
if (isNaN(vibe_min)) {
vibe_min = 0;
};
if (vibe_min) {
$('#vibe_min').prop('checked', true);
} else {
$('#vibe_min').prop('checked', false);
};
});
var submitButton = document.getElementById("b_submit");
submitButton.addEventListener("click",
function() {
localStorage.setItem("vibe_bt",
$('#vibe_bt').prop('checked') ? 1 : 0);
localStorage.setItem("vibe_min",
$('#vibe_min').prop('checked') ? 1 : 0);
var result = {
VIBE_BT: $('#vibe_bt').prop('checked') ? 1 : 0,
VIBE_MIN: $('#vibe_min').prop('checked') ? 1 : 0,
};
var location = "pebblejs://close#"+JSON.stringify(result);
document.location = location;
},
false);
</script>
</body>
</html>
Закрытие окна-странички порождает событие webviewclosed обработчик которого необходимо прописать в pebble-js-app.js:
Pebble.addEventListener('webviewclosed',
function(e) {
Pebble.sendAppMessage(JSON.parse(e.response),
function(e) {}, function(e) {});
})
Подошли к тому моменту, когда показали пользователю всё что хотели, он сделал свой выбор и дело за малым, сохранить этот выбор в приложении на часах.
Как сообщает нам документация, AppMessage API реализует push-ориентированный протокол обмена. Либо часы, либо смартфон может инициировать передачу сообщения. Обработка принимающей стороной осуществляется callback'ами.
Каждое сообщение — словарь, который содержит список пар key-value.
Чтобы и часы и смартфон «понимали», чем они обмениваются, необходимо описать параметры этого словаря минимум в двух местах, в основном Си файле:
#define VIBE_BT 1
#define VIBE_MIN 2
и в appinfo.json:
{
/* ... */
"appKeys": {
"VIBE_BT": 1,
"VIBE_MIN": 2,
}
/* ... */
}
Регистрируем обратный вызов и инициализируем AppMessage:
static void init(void) {
/*...*/
app_message_register_inbox_received(in_received_handler);
const uint32_t inbound_size = 128;
const uint32_t outbound_size = 128;
app_message_open(inbound_size, outbound_size);
/*...*/
}
И завершающий штрих, описываем callback для входящих сообщений:
void in_received_handler(DictionaryIterator *received, void *context) {
Tuple *vibe_bt_tuple = dict_find(received, VIBE_BT);
Tuple *vibe_min_tuple = dict_find(received, VIBE_MIN);
settings.vibe_bt = (bool)vibe_bt_tuple->value->int16;
settings.vibe_min = (bool)vibe_min_tuple->value->int16;
}
В итоге, приложение при первом запуске/установке инициализирует persistent storage, умеет читать и сохранять данные, имеет собственное страничку для настройки параметров.
Полный код проекта [4] на Bitbucket [5].
[1] Pebble Developers // Persisting App Data [1]
[2] Pebble Developers // Extending App Capabilities // Storing Data [2]
[3] Pebble Developers // App Configuration [3]
[4] Pebble SDK 2.0 Tutorial #8: Android App Integration | try { work(); } finally { code(); } [6]
[5] Pebble SDK 2.0 Tutorial #9: App Configuration | try { work(); } finally { code(); } [7]
Автор: tmnhy
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/76564
Ссылки в тексте:
[1] [1]: http://developer.getpebble.com/guides/pebble-apps/app-structure/persistent-storage/
[2] [2]: http://developer.getpebble.com/guides/js-apps/pebblekit-js/js-capabilities/#storing-data
[3] [3]: http://developer.getpebble.com/guides/js-apps/pebblekit-js/app-configuration/
[4] Полный код проекта: https://bitbucket.org/tmnhy/config-ex/src
[5] Bitbucket: https://bitbucket.org/
[6] [4] Pebble SDK 2.0 Tutorial #8: Android App Integration | try { work(); } finally { code(); }: http://ninedof.wordpress.com/2014/04/03/pebble-sdk-2-0-tutorial-8-android-app-integration/
[7] [5] Pebble SDK 2.0 Tutorial #9: App Configuration | try { work(); } finally { code(); }: http://ninedof.wordpress.com/2014/05/24/pebble-sdk-2-0-tutorial-9-app-configuration/
[8] Источник: http://habrahabr.ru/post/245247/
Нажмите здесь для печати.