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

в 17:45, , рубрики: Pebble, pebble watch, tutorial, Программирование, метки:

Pebble: приложения в фоне на примере «всплывающих» уведомлений - 1 Для большого количества приложений разработчики отдельно отмечают в особенностях возможность отображения на экране состояние устройства, а точнее — состояние аккумулятора и статус 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

Автор: tmnhy

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js