Для того чтобы сделать телефонный звонок из приложения в Palm WebOS есть только один способ – вызвать приложение Phone (стандартную звонилку) с помощью Application Manager. Пользователь обязательно должен подтвердить выполнение звонка, нажав кнопку дозвона. Выполнить звонок без подтверждения, возможности нет.

В API предусмотрена возможность запуска приложения дозвона с предварительной установкой телефонного номера, а также возможность запуска без установки параметров. Как использовать это API – смотрим ниже:

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

app/views/call/call-scene.html

<div class="palm-group">
  <div class="palm-group-title">Phone number</div>
  <div class="palm-row">
    <div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
      <div class="title">
        <div class="label">Number</div>
        <div id="PhoneNumber" x-mojo-element="TextField"></div>
      </div>
    </div>
  </div>
</div>
<div id="DialerButton" x-mojo-element="Button"></div>
<div id="CallButton" x-mojo-element="Button"></div>
<div id="ExitButton" x-mojo-element="Button"></div>

Наша сцена содержит группу, в которой находится текстовое поле, а также три кнопки:

  • Кнопку запуска приложения дозвона без параметров
  • Кнопку запуска приложения дозвона с предустановленным номером (для завершения звонка необходимо нажать кнопку дозвона)
  • Кнопку для выхода из приложения.

app/assistants/call-assistant.js

function CallAssistant() {
}

CallAssistant.prototype.setup = function() {
    this.controller.setupWidget("PhoneNumber",
    {
        modelProperty: 'originalValue'
    },
    this.phoneNumberTextModel =
    {
        originalValue: ''
    });
    this.controller.setupWidget("DialerButton", {}, {label:"Launch dialer"});
    this.controller.setupWidget("CallButton", {}, {label:"Call"});
    this.controller.setupWidget("ExitButton", {}, {label:"Exit"});
}

После запуска приложение у нас должно получиться что-то подобное:
WebOS Dialer Sample

Теперь посмотрим как можно запустить приложение дозвона без параметров:

CallAssistant.prototype.handleDialerButton = function(event) {
    this.controller.serviceRequest('palm://com.palm.applicationManager',
    {
        method:'launch',
        parameters:
        {
            id:"com.palm.app.phone"
        }
    });
}

Мы вызываем метод launch сервиса Application Manager и указываем ему уникальный идентификатор приложения дозвона.

Теперь посмотрим как при запуске приложения дозвона можно указать телефонный номер:

CallAssistant.prototype.handleCallButton = function(event) {
    if (this.phoneNumberTextModel.originalValue.length < 7) {
        this.controller.showAlertDialog(
        {
            onChoose: function(value){},
            title: 'Error',
            message: 'Phone number should contain at least 7 digits',
            choices: [{label:'OK'}]
        });
        return;
    }
    this.controller.serviceRequest("palm://com.palm.applicationManager",
    {
        method : 'open',
        parameters:
        {
            target: "tel://" + this.phoneNumberTextModel.originalValue
        }
    });
}

Для начала, перед запуском мы проверяем длину значения в текстовом поле. Если она меньше 7ми символов, то выводим уведомление об ошибке.
Для запуска приложения дозвона мы используем метод open сервиса Application Manager и в качестве параметра скармливаем ему объект, свойство target которого содержит телефонный номер и префикс “tel://”.

Не забываем, также, что для всех кнопок нужно регистрировать обработчики в методе setup() и отключать их в методе сleanup().

CallAssistant.prototype.setup = function() {
...
    Mojo.Event.listen(this.controller.get("DialerButton"),
        Mojo.Event.tap, this.handleDialerButton.bind(this));
    Mojo.Event.listen(this.controller.get("CallButton"),
        Mojo.Event.tap, this.handleCallButton.bind(this));
    Mojo.Event.listen(this.controller.get("ExitButton"),
        Mojo.Event.tap, this.handleExitButton.bind(this));
}

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

CallAssistant.prototype.cleanup = function(event) {
    Mojo.Event.stopListening(this.controller.get("DialerButton"),
        Mojo.Event.tap, this.handleDialerButton.bind(this));
    Mojo.Event.stopListening(this.controller.get("CallButton"),
        Mojo.Event.tap, this.handleCallButton.bind(this));
    Mojo.Event.stopListening(this.controller.get("ExitButton"),
        Mojo.Event.tap, this.handleExitButton.bind(this));
}

После всех проделанных действий, после нажатия на кнопку Call, получим что-то вроде этого:

WebOS Phone Application GUI

На этом все.

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

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

Leave a Reply

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

И.

Использование диалогов в приложениях для Palm WebOS

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

И вот в этот раз мы узнаем, как же всем этим добром пользоваться.

В WebOS существует возможность создать три типа диалоговых окон:

  • Диалог с сообщением об ошибке (Error Dialog)
  • Диалог с сообщением/уведомлением (Alert Dialog)
  • Пользовательский диалог (для которого необходимо писать свой собственный шаблог и Assistant)

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

app/views/main/main-scene.html

<br />
&lt;div class=&quot;palm-page-header&quot;&gt;<br />
  &lt;div class=&quot;palm-page-header-wrapper&quot;&gt;<br />
    &lt;div class=&quot;title&quot;&gt;WebOS Dialog Test&lt;/div&gt;<br />
  &lt;/div&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&quot;MainDatePicker&quot; x-mojo-element=&quot;DatePicker&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;AlertButton&quot; x-mojo-element=&quot;Button&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;ErrorButton&quot; x-mojo-element=&quot;Button&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;DialogButton&quot; x-mojo-element=&quot;Button&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;ExitButton&quot; x-mojo-element=&quot;Button&quot;&gt;&lt;/div&gt;<br />
&lt;div id=&quot;info&quot; class=&quot;palm-body-text&quot;&gt;&lt;/div&gt;<br />

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

app/assistants/main-assistant.js

<br />
function MainAssistant() {<br />
}</p>
<p>MainAssistant.prototype.setup = function() {<br />
    this.controller.setupWidget(&quot;MainDatePicker&quot;,<br />
        {<br />
            modelProperty: &quot;date&quot;<br />
        },<br />
        this.mainDateModel =<br />
        {<br />
            date: new Date()<br />
        });<br />
    this.controller.setupWidget(&quot;AlertButton&quot;, {}, {label:&quot;Alert Dialog&quot;});<br />
    this.controller.setupWidget(&quot;ErrorButton&quot;, {}, {label:&quot;Error Dialog&quot;});<br />
    this.controller.setupWidget(&quot;DialogButton&quot;, {}, {label:&quot;Custom Dialog&quot;});<br />
    this.controller.setupWidget(&quot;ExitButton&quot;, {}, {label:&quot;Exit&quot;});</p>
<p>    Mojo.Event.listen($(AlertButton), Mojo.Event.tap, this.onAlert.bind(this));<br />
    Mojo.Event.listen($(ErrorButton), Mojo.Event.tap, this.onError.bind(this));<br />
    Mojo.Event.listen($(DialogButton), Mojo.Event.tap, this.onDialog.bind(this));<br />
    Mojo.Event.listen($(ExitButton), Mojo.Event.tap, this.onExit.bind(this));<br />
}</p>
<p>MainAssistant.prototype.onAlert = function(event) {<br />
}</p>
<p>MainAssistant.prototype.onError = function(event) {<br />
}</p>
<p>MainAssistant.prototype.onDialog = function(event) {<br />
}</p>
<p>MainAssistant.prototype.onExit = function(event) {<br />
    this.controller.stageController.getAppController().closeAllStages();<br />
    window.close();<br />
}</p>
<p>MainAssistant.prototype.cleanup = function(event) {<br />
    Mojo.Event.stopListening($(AlertButton), Mojo.Event.tap, this.onAlert);<br />
    Mojo.Event.stopListening($(ErrorButton), Mojo.Event.tap, this.onError);<br />
    Mojo.Event.stopListening($(DialogButton), Mojo.Event.tap, this.onDialog);<br />
    Mojo.Event.stopListening($(ExitButton), Mojo.Event.tap, this.onExit);<br />
}<br />

Наша сцена после всего этого у нас сцена должна выглядеть так:
WebOS Dialogs

Теперь можно писать логику приложения.

Error Dialog

Для отображения диалога с сообщением об ошибке есть функция Mojo.Controller.errorDialog(). В качестве параметра в эту функцию передается строка, которая будет отображаться в диалоге.

<br />
MainAssistant.prototype.onError = function(event) {<br />
    Mojo.Controller.errorDialog(&quot;Simple Error Dialog&quot;);<br />
}<br />

Выглядит такой диалог вот как:

WebOS Error Dialog

Alert Dialog

Для отображения всякого рода сообщений/уведомлений используется Alert Dialog. Для вызова подобного диалога есть метод Mojo.Controller.showAlertDialog():

<br />
MainAssistant.prototype.handleAlertDialog = function(event) {<br />
    $(info).update(&quot;Alert dialog result: &quot; + event);<br />
}</p>
<p>MainAssistant.prototype.onAlert = function(event) {<br />
    this.controller.showAlertDialog({<br />
        onChoose: this.handleAlertDialog.bind(this),<br />
        title: $L(&quot;Alert Title&quot;),<br />
        message: $L(&quot;Sample Alert Message&quot;),<br />
        choices:<br />
        [<br />
            {label:$L(&quot;Normal&quot;), value:&quot;med&quot;},<br />
            {label:$L(&quot;Affirmative&quot;), value:&quot;aff&quot;, type:'affirmative'},<br />
            {label:$L(&quot;Negative&quot;), value:&quot;neg&quot;, type:'negative'},<br />
            {label:$L(&quot;Cancel&quot;), value:&quot;cancel&quot;, type:'dismiss'}<br />
        ]<br />
    });<br />
}<br />

Параметры у этого метода такие:

  • onChoose – функция, которая будет вызвана при завершении работы диалога. Параметр этой функции будет содержать код нажатой кнопки
  • title – заголовок диалога
  • message – текстовое сообщение
  • choices – массив объектов, описывающих параметры кнопок, которые будут отображены в диалоге

Каждый объект из массива choices содержит такие поля:

  • label – текст кнопки
  • value – код кнопки. При закрытии диалога этот код будет передан в функцию-обработчик, указанную в параметре onChoose.
  • type – тип кнопки. Соответствует CSS-классам для кнопок (например primary, affirmative, negative, dismiss).

WebOS Alert Dialog

Пользовательские диалоги

Существуеть возможность создавать свои собственные диалоги, которые могут содержать любые виджеты. Для создания диалога необходимо создать html-файл шаблона и Assistant-класс, который будет обрабатывать события от виджетов в диалоге, аналогично Assistant-классу сцены.

Вызвать такой диалог можно с помощью метода Mojo.Controller.showDialog():

<br />
MainAssistant.prototype.onDialog = function(event) {<br />
    this.controller.showDialog({<br />
            template: &quot;main/custom-dialog&quot;,<br />
            assistant: new CustomDialogAssistant(this)<br />
        });<br />
}</p>
<p>var CustomDialogAssistant = Class.create({<br />
    initialize: function(sceneAssistant) {<br />
        this.sceneAssistant = sceneAssistant;<br />
        this.controller = sceneAssistant.controller;<br />
    },<br />
    setup : function(widget) {<br />
        this.widget = widget;<br />
        var today = new Date();<br />
        this.controller.setupWidget(&quot;SampleDatePicker&quot;,<br />
            {<br />
                modelProperty: 'date'<br />
            },<br />
            this.dateModel =<br />
            {<br />
                date: today<br />
            });<br />
        this.controller.get('primary_button').addEventListener(Mojo.Event.tap,<br />
            this.handleButton.bind(this));<br />
        this.controller.get('secondary_button').addEventListener(Mojo.Event.tap,<br />
            this.handleButton.bind(this));<br />
        this.controller.get('negative_button').addEventListener(Mojo.Event.tap,<br />
            this.handleButton.bind(this));<br />
    },</p>
<p>    handleButton: function() {<br />
        this.sceneAssistant.mainDateModel.date = this.dateModel.date;<br />
        this.sceneAssistant.controller.modelChanged(this.sceneAssistant.mainDateModel);<br />
        this.widget.mojo.close();<br />
    }<br />
});<br />

В качестве параметра функции showDialog() передается объект с такими полями:

  • template – шаблон диалога
  • assistant – Assistant-объект диалога

В качестве параметра Assistant-классу диалога можно передать Assistant-объект сцены. В этом случае диалоговое окно может влиять на поведение сцены, например установить значения в некоторых контролах, как сделано у нас в примере.

WebOS Custom Dialog

На этом все.

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

Л.

Локализация приложений для Palm WebOS

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

В Palm WebOS локализация происходит достаточно прозрачно. Никаких сверхъестественных знаний не требуется.

Локализируем имя приложения, отображаемое в Launcher

Для того, чтобы в Launcher’е ваше приложение меняло название при смене системных настроек локализации, необходимо скопировать файл appinfo.json в папку с локализированными ресурсами.

Путь для размещения локализированных ресурсов формируется таким образом:

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

Например мы создали приложение следующим образом:

palm-generate -p "id=com.mobiledeveloper.localizableapp" -p "title=Localizable Application" LocalizableApplication
palm-generate -t new_scene -p "name=Main" LocalizaleApplication

Получаем appinfo.json такого вида:

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

Теперь нам необходимо сделать локализацию. Для этого файл appinfo.json мы копируем в /resources/es_us/appinfo.json и текст файла заменяем на следующий:

{
 "id": "com.mobiledeveloper.localizableapplication",
 "version": "1.0.0",
 "vendor": "Mobile-Developer.ru",
 "type": "web",
 "main": "../../index.html",
 "title": "Translated Application",
 "icon": "../../icon.png"
}

В результате, при смене языка на испанский, получим такое в Launcher’е:
WebOS Localized Application in Launcher

Локализируем HTML-текст сцен

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

Допустим, у нас был файл /views/main/main-scene.html

<div class="row" style="padding-left: 5px;">
    My<br />text <b>here</b>!
</div>

Для создания испанской локализации нам надо скопировать его в /resources/es_us/views/main/main-scene.html и заменить текст:

<div class="row" style="padding-left: 5px;">
    Your<br />image <b>there</b>!
</div>

После смены языковых настроек в системе, мы увидим измененный текст.

Локализация строк в JavaScript

Все строки, для которых необходима локализация, должны быть помещены в функцию $L():

$L("My text here");

Если по каким-то причинам вы не можете использовать исходную строку в качестве ключа, то значение ключа в словаре с переводом можно указать вручную.

$L("value":"Done", "key": "done_key");

Файл со словарем должен находиться непосредственно в каталоге с локализированніми ресурсами и называться strings.json

{
"My text here": "Mi texto aquí",
"done_key": "Listo",
}

Файл со словарем должен иметь кодировку UTF-8 (без BOM). Если работаете в Eclipse, то, если не указать кодировку для файла и попытаться ввести неанглийские символы и сохранить файл, должно появиться сообщение об ошибке.

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

Например английская версия строки может выглядеть так:

"Not enough memory to #{action} the file #{fname}."

…а финская так:

"Liian vähän muistia tiedoston #{fname} #{action}."

Чтобы правильно сделать локализацию подобных строк, нужно использовать метод interpolate():

var data={num:10};
var localizedText = $L("You have #{num} messages").interpolate(data);

или класс Template

var template = new Template($L("You have #{num} messages"));
var localizedText = template.evaluate({num: 10});

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