Pebble: приложения в фоне на примере «всплывающих» уведомлений

b4126ff68b79482cafcc453cd65b62c6.png Для большого количества приложений разработчики отдельно отмечают в особенностях возможность отображения на экране состояние устройства, а точнее — состояние аккумулятора и статус bluetooth-соединения со смартфоном.Но не всегда значки батарейки и bluetooth органично вписываются в оформление приложения, да и имеет ли смысл занимать пространство информацией, которая требуется пару раз в сутки? Ниже, как смотреть информацию о заряде и уведомление о потере соединения без дополнительных усилий и не прекращая работы (условно) любимого ватчфейса. А заодно о том, как работают в Pebble фоновые приложения.

Получается, что без использования приложения-компаньона необходимо реализовать следующую схему:

приложение в фоне отслеживает наступление какого-либо события или действие пользователя; по наступлению события на экране отображается оповещение, закрывающееся по тайм-ауту. Background Worker APIPebble 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

#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-statusPebble App Store: Device status

1. Pebble Developers // Implementing the Background Worker2. Pebble Developers // AppWorker3. Pebble Developers // Launch Reason

© Habrahabr.ru