В прошлый раз я рассказывал о том, как выполнить телефонный звонок из приложения в Palm WebOS. Все манипуляции выполнялись с помощью сервиса Application Manager, который запускал приложение дозвона с параметрами.

В этот раз мы более детально рассмотрим возможность запуска приложений в Palm WebOS, а также механизмы, позволяющие обработать параметры, которые были переданы приложению при запуске.Итак, наша цель – создать приложение, корректно обрабатывающее параметры запуска.

Чтобы оно заработало, нам эти параметры надо как-то этому приложению передать. И вот для этих целей мы напишем утилиту-launcher, которая с помощью Application Manager будет запускать наше приложение и передавать в параметрах ему все что нужно.

Пишем Launcher

Создадим новый проект и добавим в него сцену.

app/views/main/main-scene.html

<div>
<div class="palm-group">
  <div class="palm-group-title">Application</div>
  <div clas="palm-list">
    <div class="palm-row first">
      <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
        <div class="title">
          <div class="label">Name</div>
          <div id="AppTextBox" x-mojo-element="TextField"></div>
        </div>
      </div>
    </div>
    <div class="palm-row">
      <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
        <div class="title">
          <div class="label">Action</div>
          <div id="ActionTextBox" x-mojo-element="TextField"></div>
        </div>
      </div>
    </div>
    <div class="palm-row last">
      <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
        <div class="title">
          <div class="label">Parameter</div>
          <div id="ParamTextBox" x-mojo-element="TextField"></div>
        </div>
      </div>
    </div>
  </div>
</div>
<div id="LaunchButton" x-mojo-element="Button"></div>
<div id="ExitButton" x-mojo-element="Button"></div>
</div>

app/assistants/main-assistant.js

function MainAssistant() {
}

MainAssistant.prototype.setup = function() {
        this.controller.setupWidget('AppTextBox',
        {
            modelProperty:  'originalValue',
            textCase:       Mojo.Widget.steModeLowerCase,
            focus:          true
        },
        this.appModel =
        {
            originalValue : 'com.mobiledeveloper.appparameters'
        });
        this.controller.setupWidget('ActionTextBox',
        {
            modelProperty:  'originalValue',
            textCase:       Mojo.Widget.steModeLowerCase,
            focus:          false
        },
        this.actionModel =
        {
            originalValue : 'add'
        });
    this.controller.setupWidget('ParamTextBox',
        {
            modelProperty:  'originalValue',
            textCase:       Mojo.Widget.steModeLowerCase,
            focus:          false
        },
        this.paramModel =
        {
            originalValue : 123.45
        });

        this.controller.setupWidget("LaunchButton", {}, {label:"Launch"});
        this.controller.setupWidget("ExitButton", {}, {label:"Exit"});

        Mojo.Event.listen(this.controller.get("LaunchButton"),
            Mojo.Event.tap, this.handleLaunchButton.bind(this));
        Mojo.Event.listen(this.controller.get("ExitButton"),
            Mojo.Event.tap, this.handleExitButton.bind(this));
}

MainAssistant.prototype.cleanup = function(event) {
        Mojo.Event.stopListening(this.controller.get("LaunchButton"),
            Mojo.Event.tap, this.handleLaunchButton.bind(this));
        Mojo.Event.stopListening(this.controller.get("ExitButton"),
            Mojo.Event.tap, this.handleExitButton.bind(this));
}

MainAssistant.prototype.handleLaunchButton = function(event) {
        try
        {
            this.controller.serviceRequest('palm://com.palm.applicationManager',
            {
                method:'launch',
                parameters:
                {
                        id: this.appModel.originalValue,
                        params:
                        {
                            action: this.actionModel.originalValue,
                            param: this.paramModel.originalValue
                        }
                }
            });
        }
        catch(e)
        {
            this.controller.showAlertDialog({
                onChoose: function(value){},
                title: 'Error',
                message: e,
                choices: [{label:'OK'}]
        });
    }
}

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

Сцена содержит три поля ввода:

  • В первом – вводим уникальный идентификатор приложения, которое будем запускать
  • Во втором – параметр action, который будет передан запускаемому приложению
  • В третьем – параметр param, который будет передан запускаемому приложению

При запуске Launcher выглядит так:

WebOS Application Launcher (sample)

Рассмотрим более детально, как же происходит запуск стороннего приложения:

  • Мы вызываем Application Manager с помощью метода serviceRequest() объекта-контроллера
  • Методу serviceRequest мы скармливаем название сервиса и JSON-объект с параметрами вызова сервиса
  • В параметрах вызова сервиса указываем, что вызывается метод launch, а также указывается JSON-объект , который будет передан в качестве параметра методу launch.
  • Объект, передаваемый методу launch содержит поле id, а котором указан идентификатор вызываемого приложения, а также поле params, содержащее JSON-объект, передаваемый в качестве параметра запускаемому приложению.

И вот, c launcher’ом мы закончили. Теперь приступим к примеру, демонстрирующему обработку параметров запуска.

Учимся обрабатывать параметры запуска приложения

Для начала создадим новое приложение и в нем сцены с названием first и add.

Если приложение должно обрабатывать параметры запуска, это значит что нам необходимо создать свой Application Assistant – класс, обеспечивающий логику работы приложения. Если мы создаем свой Application Assistant, то и создание GUI мы тоже должны будем прописывать руками. По умолчанию генератор проектов создает проект, содержащий главное окно. В нашем же случае все окна мы будем создавать руками (в коде). Для того, чтобы создавать окна в коде и избавиться от автоматически создаваемого окна, нам надо править файл appinfo.json. В нем необходимо указать параметр noWindow равным true.

{
"id": "com.mobiledeveloper.appparameters",
"version": "1.0.0",
"vendor": "Mobile-Developer.ru",
"type": "web",
"main": "index.html",
"title": "AppParameters",
"icon": "icon.png",
"noWindow": "true"
}

Указание значения noWindow является очень важным шагом, т.к. без этого свойства в приложении будут создаваться два окна и при запуске это будет выглядеть очень странно, что может в последствии стать причиной отказа в приеме приложения в Palm’овский e-commerce для приложений.

По умолчанию, кодогенератор для проектов создает код для Stage Assistant. Нам он теперь не понадобится и поэтому файл app/assistants/stage-assistant.js можно смело удалять.

Теперь поработаем над созданными ранее сценами:

app/views/first/first-scene.html

<div id="main" class="palm-hasheader">
  <div class="palm-header center" id="main-hdr">Main Scene</div>
</div>
<div x-mojo-element="Button" id="AddSceneButton"></div>
<div x-mojo-element="Button" id="ExitButton"></div>

app/assistants/first-assistant.js

function FirstAssistant() {
}

FirstAssistant.prototype.setup = function() {
    this.controller.setupWidget("AddSceneButton", {}, {label:"Add"});
    this.controller.setupWidget("ExitButton", {}, {label:"Exit"});
    Mojo.Event.listen(this.controller.get("AddSceneButton"),
        Mojo.Event.tap, this.handleAddButton.bind(this));
    Mojo.Event.listen(this.controller.get("ExitButton"),
        Mojo.Event.tap, this.handleExitButton.bind(this));
}

FirstAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening(this.controller.get("AddSceneButton"),
        Mojo.Event.tap, this.handleAddButton.bind(this));
    Mojo.Event.stopListening(this.controller.get("ExitButton"),
        Mojo.Event.tap, this.handleExitButton.bind(this));
}

FirstAssistant.prototype.handleAddButton = function(event) {
    this.controller.stageController.pushScene("add");
}

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

Сцена First содержит две кнопки. Первая кнопка запускает сцену Add, а вторая – завершает работу приложения

app/views/add/add-scene.html

<div class="palm-row">
<div class="palm-hasheader">
  <div class="palm-header">Add Scene</div>
</div>
</div>
<div class="palm-row">
  <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
    <div class="title">
      <div id="ParamTextBox" x-mojo-element="TextField"></div>
    </div>
  </div>
</div>

app/assistants/add-assistants.js

function AddAssistant(param) {
    if(param)
    {
        this.initialValue = param;
    }
    else
    {
        this.initialValue = '';
    }
}

AddAssistant.prototype.setup = function() {
    this.controller.setupWidget('ParamTextBox',
    {
        modelProperty: 'originalValue',
        focus: true
    },
    {
        originalValue: this.initialValue
    });
}

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

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

Для того чтобы обработать параметры запуска, в Application Assistant есть метод handleLaunch, у которого есть параметр launchParams – это объект, содержащий параметры запуска. Если приложение было запущено без параметров, то launchParams будет равен null.

app/assistants/app-assistant.js

var AppParameters = {}
AppParameters.StageName = "AppParamaters";

function AppAssistant() {
}

AppAssistant.prototype.handleLaunch = function(launchParams) {
    if(!launchParams)
    {
        Mojo.Log.info('Applicaion was started without parameters');
        this.startDefault();
    }
    else
    {
        Mojo.Log.info('Applicaion was started with parameters');
        switch(launchParams.action)
        {
        case 'add':
            Mojo.Log.info('ADD action');
            this.addSceneParam = launchParams.param;
            this.handleAddAction();
        break;
        }
    }
}

AppAssistant.prototype.startDefault = function() {
    this.stageController = this.controller.getStageController(AppParameters.StageName);
    if (this.stageController)
    {
        this.stageController.popSceneTo('first');
        this.stageController.activate();
    }
    else
    {
        var stageParams =
        {
            name: AppParameters.StageName,
            lightweight: true
        }
        this.controller.createStageWithCallback(stageParams,
            this.pushFirstScene.bind(this));
    }
}

AppAssistant.prototype.handleAddAction = function() {
    this.stageController = this.controller.getStageController(AppParameters.StageName);
    if (this.stageController)
    {
        this.stageController.popSceneTo('first');
        this.stageController.pushScene('add', this.addSceneParam);
        this.stageController.activate();
    }
    else
    {
        var stageParams =
        {
            name: AppParameters.StageName,
            lightweight: true
        }
        var addStageCallback = function(stageController)
        {
            stageController.pushScene('first');
            stageController.pushScene('add', this.addSceneParam);
        }
        this.controller.createStageWithCallback(stageParams,
        addStageCallback.bind(this));
    }
}

AppAssistant.prototype.pushFirstScene = function(stageController) {
    stageController.pushScene('first');
}

В методе handleLaunch мы проверяем значение launchParams и если оно равно null, то вызываем метод startDefault(). Если launchParams не null, то мы выполняем проверку значения поля action и если оно равно add, то вызываем сцену Add.

Метод handleLaunch может быть вызван в двух случаях – при запуске первого экземпляра приложения и для уже запущенного приложения. Об этом надо помнить, когда мы реализуем логику создания сцен в методах startDefault() и handleAddSAction().

В теле метода startDefault() мы получаем объект Stage Controller с именем “AppParameters”. Если полученное значение равно null, то у нас первый запуск приложения. Мы создаем новое окно (stage) с помощью метода createStageWithCallback() и в callback-функции, которая отрабатывает после успешного создания окна, создаем сцену first.

Если же ссылка на Stage Controller, полученная в методе startDefault(), не равна null, то у нас произошел вызов уже запущенного приложения. Мы закрываем все сцены, которые находятся над сценой first. Делаем мы это с помощью метода popSceneTo().

Метод handleAddAction() работает аналогично. Если у нас происходит вызов уже запущенного приложения, то мы закрываем все сцены, находящиеся над сценой first, а затем открываем сцену add и передаем ей в качестве параметра поле param из launchParameters.

Если же мы вызываем приложение первый раз с параметром action=add, то создаем новое окно, в нем создаем сцену first, а затем сцену add и точно так же, скармливаем ей в качестве параметра поле param из launchParameters.

WebOS Launch Application with Parameters

На этом все.

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

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

Leave a Reply

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

С.

Симуляция аппаратных событий в эмуляторе Palm WebOS

В эмуляторе WebOS есть возможность программно симулировать аппаратные события, например входящий телефонный звонок, входящее SMS или изменение GPS-координат. Такая возможность может быть полезна, например, при отладке приложений, использующих GPS.

Для симуляции аппаратных событий в Palm Mojo SDK используется утилита luna-send, которая отправляет сообщения сервису pmradiosimulator в эмуляторе. Об использовании утилиты luna-send и пойдет речь в этот раз.

Синтаксис вызова luna-send
luna-send -n 1 URL JSON_object

Параметр URL позволяет указать аппаратное событие, которое должно быть симулировано. Параметр JSON_object позволяет указать параметры вызова сервиса pmradiosimulator.

Примеры использования

Симуляция входящего телефонного звонка:

luna-send -n 1 luna://com.palm.pmradiosimulator/set_incomingcall {\"number\":\"14086177431\"}
Симуляция входящего SMS:
luna-send -n 1 luna://com.palm.pmradiosimulator/set_incomingsms {\"number\":\"4086177431\",\"
message\":\"'Hello World! Incoming SMS.'\"}
Изменение GPS-координат
luna-send -n 1 luna://com.palm.pmradiosimulator/set_position {\"lat\":\"37.3\",\"long\":\"-122\"}
Изменение оператора сотовой связи (применяется после перезагрузки)
luna-send -n 1 luna://com.palm.pmradiosimulator/set_operator {\"operator\":\"Sprint\"}

GPS AutoDrive

Фyкция GPS AutoDrive в эмуляторе позволяет использовать CSV-файл с записанным GPS-треком при запросе координат приложениями, использующими GPS. Таким образом можно симулировать передвижение по заданному маршруту.

Запуск функции AutoDrive
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/start {}

Если имя CSV-файла с запиью трека не указано, то будет использоваться файл /var/lib/til/AutoDrive_DefaultRoute.csv.

Остановка режима AutoDrive
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/stop {}

После остановки AutoDrive координаты GPS будут установлены в значения по умолчанию (Palm Sunnyvale).

Установить AutoDrive в реверсный режим
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/reverse {}
Приостановить AutoDrive
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/pause {}
Восстановить режим AutoDrive после паузы
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/resume {}
Ускорить режим AutoDrive
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/speedup {}
Замедлить режим AutoDrive
luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/slowdown {}

CSV-файл трека

По умолчанию для задания GPS-трека используется файл AutoDrive_DefaultRoute.csv. Для того, чтобы указать другой файл трека, необходимо вызвать функцию set_route сервиса pmradiosimulator:

luna-send -n 1 luna://com.palm.pmradiosimulator/autodrive/set_route \{\"route\":\"/var/lib/MyGpsRoute.csv\"}

Формат CSV-файла трека описан здесь.

P.

Project Ares – Web IDE для Palm WebOS

Хм… А все-таки Palm делают странное. Недавно они запустили Web-based среду разработки мобильных приложений для Palm WebOS. Публичная бета доступна уже сейчас и все желающие могут ее поиспользоваться и пообвыкнуть.

Обещают что IDE покрывает все нужды, начиная от разработки и отладки, и заканчивая публикацией приложений в Palm App Catalog.

Из полезных возможностей следует отметит:

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

Работает Ares в Safari, Chrome, Firefox (по крайней мере официально так заявлено).

Попробовать Ares в действии можно здесь.

Ares - Web IDE for Palm WebOS