Для большого количества приложений разработчики отдельно отмечают в особенностях возможность отображения на экране состояние устройства, а точнее — состояние аккумулятора и статус bluetooth-соединения со смартфоном.
Но не всегда значки батарейки и bluetooth органично вписываются в оформление приложения, да и имеет ли смысл занимать пространство информацией, которая требуется пару раз в сутки?
Ниже, как смотреть информацию о заряде и уведомление о потере соединения без дополнительных усилий и не прекращая работы (условно) любимого ватчфейса. А заодно о том, как работают в Pebble фоновые приложения.
Получается, что без использования приложения-компаньона необходимо реализовать следующую схему:
- приложение в фоне отслеживает наступление какого-либо события или действие пользователя;
- по наступлению события на экране отображается оповещение, закрывающееся по тайм-ауту.
Background Worker API
Pebble SDK предоставляет такую возможность через Background Worker API [1]: механизм создания и управления вторым экземпляром приложения с ограниченной функциональностью — сбор показаний датчиков и выполнения задач не требующих пользовательского интерфейса.
Что же представляет из себя Worker, немного из документации:
- это отдельный процесс, дополняющий «стандартное» приложения, может быть запущен как вместе, так и отдельно от «стандартного»;
- Worker ограничен 10.5kB памяти;
- доступны большинство API, кроме интерфейса и AppMessage;
- в один момент времени может быть запущен только один фоновый процесс;
- работающий процесс выбирается в меню «Настройки», раздел «Activity»;
- Worker может запускать foreground часть приложения.
Получение данных из Worker’а
Разработчики предлагают три способа получения данных из фонового приложения:
- сохранение данных в persistent storage с последующим чтением из основного приложения;
- отправка сообщений в основное приложение через AppWorkerMessage;
- использование приложения-компаньона и Data Logging API.
AppWorker
Основное приложение может управлять фоновым процессом[2]:
- получать состояние фонового процесса;
- запускать Worker текущего приложения;
- завершать работу фонового процесса текущего приложения;
- подписываться на сообщения фонового процесса.
Приложение: pop-up уведомления
Worker
Для создания шаблона приложения, используется ключ —worker:
$ pebble new-project --worker project_name
На одном уровне с каталогом src, создается каталог worker_src, в котором будет исходный код фонового процесса. Кода немного, поэтому привожу его целиком:
#include <pebble_worker.h> #define WORKER_DUMMY 0 #define WORKER_WRIST 1 #define WORKER_BT 2 #define PERSIST_KEY 99 static void tap_handler(AccelAxisType axis, int32_t direction) { persist_write_int(PERSIST_KEY, WORKER_WRIST); worker_launch_app(); } static void bt_handler(bool connected) { persist_write_int(PERSIST_KEY, WORKER_BT); worker_launch_app(); } static void worker_init() { accel_tap_service_subscribe(tap_handler); bluetooth_connection_service_subscribe(bt_handler); } static void worker_deinit() { accel_tap_service_unsubscribe(); bluetooth_connection_service_unsubscribe(); } int main(void) { worker_init(); worker_event_loop(); worker_deinit(); }
Подписываемся на два события: смену статуса bluetooth и на определение жеста рукой.
В зависимости от события в хранилище записывается соответствующий флаг и запускается основное приложение.
Основное приложение
При инициализации приложения проверяем запущен ли Worker, если нет, то делаем попытку запустить в фоне:
bool running = app_worker_is_running(); if (!running) { app_worker_launch(); };
Проверяем, каким образом было запущено приложение [3], если не из фонового, то закрываем приложение, в противном случае запускаем таймер (сколько миллисекунд отображается уведомление) и закрываем:
AppLaunchReason app_reason = launch_reason(); if (app_reason == APP_LAUNCH_WORKER) { app_timer = app_timer_register(ALERT_TIME*1000, close_app, NULL); } else { close_app(); };
Для «программного» выхода из приложения используется небольшой трюк:
static void close_app() { window_stack_pop_all(animated); }
Для отображения уведомлений создаем слой и задаем колбэк для отрисовки контекста:
layer_set_update_proc(layer, update_layer);
В обработчике читаем флаг из persistent storage и рисуем соответствующую картинку:
static void update_layer(Layer *layer, GContext *ctx) { if (persist_exists(PERSIST_KEY)) { int worker_event = persist_read_int(PERSIST_KEY); switch (worker_event) { case WORKER_WRIST: battery_state(ctx); break; case WORKER_BT: bluetooth_state(ctx); break; }; } else { close_app(); }; }
Получилось приложение:
- в фоне работает процесс;
- если определяется жест запястьем, то «поверх» текущего фейса на 5 сек. отображается иконка с зарядом батареи, после чего возвращается текущий ватчфейс;
- если определяется смена статуса bluetooth, то «поверх» текущего фейса на 5 сек. отображается соответствующая иконка, после чего возвращается текущий ватчфейс.
Исходники: bitbucket/pebble-device-status
Pebble App Store: Device status
1. Pebble Developers // Implementing the Background Worker
2. Pebble Developers // AppWorker
3. Pebble Developers // Launch Reason
ссылка на оригинал статьи http://habrahabr.ru/post/253221/
Добавить комментарий