В WebOS пользователь может вручную указать интервал, по истечению которого, если устройство не используется, оно переходит в спящий режим. Этот интервал может варьироваться вдиапазоне от 30 секунд до 3х минут.

В некоторых приложениях может возникнуть необходимость держать устройство включенным по истечению интервала, заданного пользователем (это может быть актуально, например, для приложений, воспроизводящих видео или аудио). Для поддержания устройства в активном состоянии в WebOS существует специальный API. О нем и пойдет речь в этот раз.

Итак, нам понадобится тестовое приложение. Создаем проект и в нем сцену main.

app/views/main/main-scene.html

<div class="palm-hasheader">
  <div class="palm-header">Power Management Test</div>
</div>
<div class="palm-header-spacer"></div>
<div id="TimeoutPicker" x-mojo-element="IntegerPicker"></div>
<div id="StartActivityButton" x-mojo-element="Button"></div>
<div id="StopActivityButton" x-mojo-element="Button"></div>
<div id="ExitButton" x-mojo-element="Button"></div>
<div id="info" class="palm-body-text"></div>

Сцена содержит виджет для выбора таймаута, в течении которого устройство не должно засыпать, а также кнопки:

  • Переход в активносе состояние
  • Выход из активного состояния
  • Выход из приложения

app/assistants/main-assistant.js

function MainAssistant() {
}

MainAssistant.prototype.setup = function() {
    this.controller.setupWidget("TimeoutPicker",
        {
            modelProperty: 'value',
            label: 'Timeout (minutes)',
            min: 01,
            max: 15,
            padNumbers: true
        },
        this.timeoutModel =
        {
            value: 1
        });
    this.controller.setupWidget("StartActivityButton", {},
        this.startButtonModel = {label: "Start Activity"});
    this.controller.setupWidget("StopActivityButton", {},
        this.stopButtonModel = {label: "Stop Activity", disabled: true});
    this.controller.setupWidget("ExitButton", {}, {label: "Exit"});

    Mojo.Event.listen($(StartActivityButton), 
        Mojo.Event.tap, this.onStartActivity.bind(this));
    Mojo.Event.listen($(StopActivityButton), 
        Mojo.Event.tap, this.onStopActivity.bind(this));
    Mojo.Event.listen($(ExitButton), Mojo.Event.tap, this.onExit.bind(this));

    this.counter = 0;
}

MainAssistant.prototype.onStartActivity = function(event) {
}

MainAssistant.prototype.onStopActivity = function() {
}

MainAssistant.prototype.onExit = function(event) {
    this.controller.stageController.getAppController().closeAllStages();
    window.close();
}

MainAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening($(StartActivityButton), Mojo.Event.tap, this.onStartActivity);
    Mojo.Event.stopListening($(StopActivityButton), Mojo.Event.tap, this.onStopActivity);
    Mojo.Event.stopListening($(ExitButton), Mojo.Event.tap, this.onExit);
}

В результате получим такой внешний вид приложения:

WebOS Power Management Sample Application

Теперь можно писать логику для обработчиков событий.

Для запуска активного режима приложения необходимо вызвать метод activityStart сервиса palm://com.palm.power/com/palm/power.

MainAssistant.prototype.onStartActivity = function(event) {
    this.counter++;
    this.activity = /* "com.palm.app."  + */
        Mojo.appName + ".activity-" + this.counter;
    this.controller.serviceRequest("palm://com.palm.power/com/palm/power",
    {
         method: "activityStart",
         parameters:
         {
             id: this.activity,
             duration_ms: this.timeoutModel.value * 60 * 1000
         },
         onSuccess: this.activityStartSuccess.bind(this),
         onFailure: this.activityStartFailure.bind(this)
        });
    this.timer = setTimeout(this.onTimer.bind(this),
        this.timeoutModel.value * 60 * 1000 / 2.0);
}

MainAssistant.prototype.onTimer = function(event) {
    if(this.timer)
    {
        clearTimeout(this.timer);
        delete this.timer;
    }
    this.onStopActivity();
}

MainAssistant.prototype.activityStartSuccess = function(event) {
    this.startButtonModel.disabled = true;
    this.stopButtonModel.disabled = false;
    this.controller.modelChanged(this.startButtonModel);
    this.controller.modelChanged(this.stopButtonModel);
    $(info).update("Activity started: " + this.activity);
}

MainAssistant.prototype.activityStartFailure = function(event) {
    $(info).update("Error:<br>" + Object.toJSON(event));
}

Параметры метода activityStart:

  • id – уникальный идентификатор вызова активного режима (можно использовать формат ID-приложения + ID-операции + счетчик).
  • duration_ms – длительность активного режима в миллисекундах. Максимальное значение єтого параметра 900000, что соответствует 15ти минутам.

Возможные проблемы:

  • На эмуляторе вызов activityStart не дает видимого эффекта. Виртуальная машина остается активной всегда.
  • На официальном форуме разработчиков WebOS-приложений неоднократно появлялась информация о том, что активный режим работает только для системных приложений (с идентификатором, начинающимся на com.palm.app). Также была информация что эту проблему исправили и активный режим доступен для разработчиков сторонних приложений, но без устройства это подтвердить нет никакой возможности.
  • По окончанию активного режима приложение не получает никаких уведомлений, и в случае, когда активный режим завершился, а приложение все еще должно держать устройство включенным, надо перезапускать активный режим заново, указывая новый идентификатор вызова. В таком случае очень удобно пользоваться счетсиком. Для того, чтобы вовремя продлить активный режми, можно использовать таймер.

В примере, вместе с переходом в активный режим, у нас создается таймер, длительность задержки которого равна половине длительности активного режима. При вызове обработчика собфтия таймера, мы выходим из активного режима.

MainAssistant.prototype.onStopActivity = function() {
    if(this.activity)
    {
        this.controller.serviceRequest("palm://com.palm.power/com/palm/power", {
             method: "activityEnd",
             parameters:
             {
                 id: "com.palm.app.news.update-1"
             },
             onSuccess: this.activityStopSuccess.bind(this),
             onFailure: this.activityStopFailure.bind(this)
        });
    }
}

MainAssistant.prototype.activityStopSuccess = function(event) {
    this.startButtonModel.disabled = false;
    this.stopButtonModel.disabled = true;
    this.controller.modelChanged(this.startButtonModel);
    this.controller.modelChanged(this.stopButtonModel);
    $(info).update("Activity stopped: " + this.activity);
    delete this.activity;
}

MainAssistant.prototype.activityStopFailure = function(event) {
    $(info).update("Error:<br>" + Object.toJSON(event));
}

MainAssistant.prototype.onExit = function(event) {
    this.controller.stageController.getAppController().closeAllStages();
    window.close();
}

При выходе из приложения, автоматического останова активного режима не происходит, поэтому в методе cleanup() главной формы все вызовы активного режима должны быть завершены.

MainAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening($(StartActivityButton), Mojo.Event.tap, this.onStartActivity);
    Mojo.Event.stopListening($(StopActivityButton), Mojo.Event.tap, this.onStopActivity);
    Mojo.Event.stopListening($(ExitButton), Mojo.Event.tap, this.onExit);
    this.onStopActivity();
}

На этом все.

Скачать исходный код примера.

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

М.

Мой путь в Palm App Catalog – Часть II – Palm такой Palm…

Ну вот, в этот раз вторая часть поучительной истории о моих попытках зохватить голактеку начать разрабатывать платные приложения для Palm WebOS и о продаже приложений в Palm App Catalog.

В прошлой серии мы узнали какие лишения ждут молодых падаванов разработчиков мобильных приложений для WebOS, а сейчас я расскажу о том, чего можно жлать после начала продаж.

О всяком

Итак, прошел месяц продаж и наконец-то Palm опубликовали статистику загрузок/продаж за февраль, и отчеты с этой информацией стали доступны в Web-интерфейсе разработчика. Отчеты, как оказалось, неплохие, довольно подробные. Во0первых, можно посмотреть статистику по каждому приложению и по каждой версии приложения. В принципе, информация о загрузках вся публичная, цена приложения известна, так что не вижу смысла затирать цифры и выкладываю скрины как есть.

Есть и более детальные отчеты, в которых указано, в каком штате сколько покупок было сделано за месяц. Я подозреваю что после того, как платные приложения станут доступны желающим в других странах, для каждой страны будет тоже отдельная строка в отчетах.

Все, вроде бы, нормально, приложение продавалось, положительные отзывы поступали, все были довольны и счастливы, даже ревью написали чудесное в Pre Central. Все это продолжалось до тех пор, пока я не решил обновить приложение, добавив новый функционал.

Как обычно, запостил новый бинарник, отдал на ревью. Прошло три дня и.. вот оно! Больше тысячи загрузок в за первые сутки после публикации! Я прям даже обрадовался.

Epic Fail

У меня есть привычка, я время от времени ищу информацию о своих приложениях в Гугле. Просто ради спортивного интереса, узнать что люди пишут.

Подождав денек после публикации, решил посмотреть, что же пишут люди по поводу моего чудесного творения. А, как оказалось, пишут они странное. Наиболее странным мне показалась фраза о том что “Круто что в этой версии они снизили цену до $0”. Вобще, более тысячи загрузок в сутки мне тоже показалось странным, учитывая то, что за половину февраля было куплено всего 388 копий приложения. Пошел проверять в админку. И таки-да, уважаемые товарищи из Palm выложили новую версию моего приложения с ценой $0 вместо заявленных при сабмите $0.99.

В этом месте мне пришлось грязно выругаться стало не по себе, но, как показывает опыт, в таких случаях лучше не психовать, а просто планомерно решать проблему. Написал в саппорт Palm’у что вот, у меня проблема с последней версией приложения. Я заплатил $50 за сабмит, прошлая версия приложения была платной, а тут почему-то стала бесплатной. Можете мне откатить все загрузки текущей версии и снова сделать мое приложение платным? Также я описал последовательность действий по сабмиту приложения с самого начала. Рассказал о том, что первая версия была бесплатной бетой, потом я засабмитил платное приложение, потом обновил версию, после чего произошла бяка.

На самом деле, при общении с саппортом, я особо на результат не рассчитывал. Вернее даже не так, судя по прошлому общению, ответ я ожидал недели через полторы, кгда все, кому это надо, уже скачают бесплатную версию и смысла продавать приложение уже не будет совсем. Но в этот раз все было быстро. Первый ответ пришел через 4 часа с вопросами, действительно ли мое приложение было платное. Я ответил что да, и они могут посмотреть тчеты по продажам за февраль. Следующим письмом было уведомление о том, что мое приложение убрали из каталога (suspended) до выяснения источника проблем и до того момента, когда они смогут сделать приложение снова платным.

До того момента как приложение засаспендили, его успело скачать около 2900 леммингов, но вцелом в этот раз саппортом я доволен, порешали все в течении суток.

Еще через сутки мне сказали что кина не будет и засабмитить приложение заново как платное нельзя, только надо сабмитить приложение с новым package ID и платить $50.

В этом месте мне снова пришлось грязно выругаться задуматься. А как же мои денежки, которые я потратил на сабмит этого приложения? Ведь бяка произошла не по моей вине, а из-за бага у них в системе в системе. О своих размышлениях на эту тему я довольно деликатно намекнул саппорту.

И о чудо! Они пообещали попробовать обдумать возможность возврата мне денег за прошлый сабмит. Так и написали – попробовать обдумать возможноть.

Зная, как все делается у нас, я особо на результат не рассчитывал, ведь папуас папуасу друг, товарищ и.. корм. Поэтому я просто подготовил новую версию приложения, добавив к нему слово Pro в конце, а также вставив несколько полезных фич по настройке загружаемых PDF файлов, и… отдал еще $50 за новый сабмит 😉

А, да, еще +$20 отдал дизайнеру-фрилансеру за перевод иконки в вектор и за то что слепил мне ICO файл (глядя на все это, решил еще и для остальных мобильных платформ версии делать).

Ну хоть что-то хорошее

Еще чере сутки (пока проходило ревью нового приложения), получил радостную новость от Palm что таки-да, они сжалились надо мной и вернули $50. А откатывать бесплатные загрузки старого приложения никто так и не пытался. Итого получается что из-за бага в системе у Palm в мире стало на 3000 счастливых леммингов больше. Ну что же, ладно, будем считать что мне зачтется доброе дело и я получу +10 к пепяке.

И вот, настало сегодня. И сегодня у меня получилось сразу две радостные новости.

Первая – пришли документы, подтверждающие валидность EIN, который я поиспользовал в Google Checkout и Palm App Catalog.

Вторая – что мое приложение прошло ревью и доступно для загрузки.

Теперь снова остается только ждать. Посмотрим, как отнесутся пользователи, купившие прошлую платную версию приложения, к тому, что его больше нет в каталоге, обновлений они не получат, а есть другое приложение почти с таким же функционалом, с таким же названием, от того же разработчика, но стоит дороже.

Напоследок видео

И еще ссылка на Pre Central, где можно проголосовать за приложение и посмотреть статистику.

В.

Впечатления от вебкаста по Palm webOS

Palm PreПоучаствовал в вебкасте по разработке для Palm webOS.

Как это было? Это было ммм.. довольно странно. Видео тормозило просто жутчайшим образом, а звука вобще не было. Вернее вместо этого был только шум. Как вариант предлагалось позвонить по телефону и послушать таким образом о чем там идет речь, но… как-то межлународный звонок в течении часа.. ну не каждый осилит.

Но в общем ладно. Теперь о хорошем. Как-то так постараюсь тезисно свое мнение изложить:

  1. Palm OS это прикольно. 😉
  2. Т.к. приложения пишутся на JavaScript, то для разоаботки GUI кроме текстового редактора ничего не нужно.
  3. В вебкасте чудо-человек разработчик демонстрировал все под Mac OS но т.к. JavaScript отрабатывает на клиенте, то писать можно и под Windows и под Linux
  4. JavaScript как и реньше не имеет доступа к системным ресурсам, зато для этого предусмотрен серверный функционал. Для получения, например, данных о GPS координатах из JavaScript выполняется запрос к локальному Web-сервису (URL начинается как-то так с “palm://…”, целиком не запомнил)
  5. Архитектура приложения на вид напоминает MVC. В подробности особо не вдавались, вебкаст короткий.
  6. Форматирование и GUI-контролы реализуются с помощью предустановленных CSS-стилей. На вид выглядит довольно аккуратно и юзабельно.
  7. SDK будет включать (по крайней мере по обещаниям) какое-то подобие веб-сервера, реализующего эмуляцию серверной части API для webOS (тех веб-сервисов, которые доступны в самой OS и которые можно использовать из JS).
  8. Не очень понятно пока каким образом можно реализовывать свой серверный функционал (т.е. например какой-нибудь сервис, который могут дергать все приложения, запущенные на устройстве, это пока загадка).
  9. Не очень понятно как поучаствовать в закрытом бета-тестировании SDK (оно пока не доступно для широкой общественности).
  10. Записанный вариант вебкаста обещали выложить (не знаю пока, в публичном доступе или только для участников) и прислать адрес в почту. Если пришлют, обязательно выложу информацию здесь на сайте.

Ну вот как-то так. Жаль, конечно, что из-за недостаточного качества организации мероприятия не получилось узнать больше, но тема сама по себе очень интересная.