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. Записанный вариант вебкаста обещали выложить (не знаю пока, в публичном доступе или только для участников) и прислать адрес в почту. Если пришлют, обязательно выложу информацию здесь на сайте.

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

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

Leave a Reply

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

О.

Обработка параметров запуска приложения в Palm WebOS

В прошлый раз я рассказывал о том, как выполнить телефонный звонок из приложения в 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

На этом все.

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

М.

Мой путь в Palm App Catalog

Введение

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

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

Начало

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

После анонса Palm Mojo SDK Early Access Program я сразу же подал заявку на участие, но при регистрации товарищи из Palm открыто заявляли что да, регистрация доступна для всех, но фактически доступ получат только те, кого Palm посчитает достойным. Какими там критериями они руководствовались, непонятно, но официальный доступ к SDK мне удалось получить только через 4 месяца. Все эти 4 месяца (а на самом деле еще меньше, т.к. SDK долгое время было недоступно для свободной загрузки) приходилось довольствоваться пиратскими/неофициальными версиями, которые иногда, с задержкой, появлялись на торрентах.

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

И вот нконец-то чудо произошло и Palm прислали мне инвайт, как раз где-то в это же время вышли первые главы книги (здесь и здесь) о разработке для WebOS и уже можно было как-то понять, что же с этим чудом делать.

Оно даже работает

Да, именно так, “оно даже работает” – это как раз та мысль, которая пришла мне в голову после того, как я впервые установил себе WebOS SDK. Да, на Vista были проблемы с тем, что ранние версии что-то пытались писать в Program Files, а этого делать нельзя, но при наличии прямых рук, растущих из нужного места, все эти проблемы решались довольно просто. И таки-да, SDK заработало почти с первого раза.

Язык разработки – JavaScript. Я его никогда не знал, да и желания учить как-то до этого не было (всю жизнь писал под десктоп на C++ и под всякое тоже на C++, до интерпретируемых языков все руки не доходили). Но ведь новые горизонты, возможность хорошо заработать, слава, мировое господство…. Эх… Чего только не сделаешь ради мирового господства… И я сделал. Я сел учить JavaScript.

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

После седьмого дня подготовки туториалов, почувствовал в себе силы делать что-то полезное. Нашел человека, который хотел мобильное приложение для WebOS и написал первое коммерческое приложение – клиент для обмена файлами посредством SMS для сервиса SMSMyFile. На разработку первой версии первого приложения для WebOS  у меня ушло 15 часов. Сейчас это приложение доступно в Palm App Catalog, распространяется бесплатно, хотя разработка стоила денег.

Я ненавижу тебя, Palm… и люблю

Дальше были попытки запостить приложение в Palm App Catalog. Для площадки по продаже мобильных приложений у Palm была такая же политика, как и с SDK. Вы пишете им письмо, в письме посылаете скомпилированный пакет с приложением, они рассматривают возможность публикации и затем публикуют. Называлось это все eCommerce Beta Program. Сейчас страница с описанием этой программы на официальном сайте выдает 404ю ошибку, поэтому ссылку не даю.

На вид все просто и я очень рассчитывал, что это будет еще и быстро. Palm ведь маленькая компания, где-то слышал, что в в ней работали на то время всего 300 человек (может это и не соответствует действительности, но все равно, компания явно меньше чем MS), к тому же доля на рынке мобильных устройств у них не такая большая, поэтому мне казалось что за каждого довольного клиента или разработчика они должны (могут, должны, как-то так…) держаться обеими руками.

И вот, я пишу письмо, прикладываю к нему описание приложения и дистрибутив и… ничего. Тишина. Ради спортивного интереса отослал письмо с уведомлении о прочтении. Через две недели получил уведомление что таки-да, мое письмо прочитали. И снова тишина. Уже думал что все, потеряли мое приложение или забыли, и через !(внимание) полтора месяца получаю еще одно уведомление что… письмо у кого-то из Palm было удалено без прочтения. После этого я обиделся. К слову сказать, я не один такой был, который обиделся. Многие люди тоже ненавидят Palm из-за их политики общения с разработчиками. Затем было долгое затишье, когда, разработав свое приолжение, я не могу хотя бы как-то отдать его пользователям. Пытаться распространять приложение для Palm WebOS собственными силами – относительно глупая затея. Ну, разве что, если у вас есть сервис, который уже приносит миллионные прибыли и какую-то часть из этих денег вы можете потратить на раскрутку своей программы (но тогда напрашивается вопрос, а почему вы еще не в App Catalog’e :)).

За это время я успел почитать всякой полезной документации, например UI Design Guidelines, Application Submission Checklist, знание которых потом неоднократно помогло мне в будущем.

А потом… Регистрация в Palm App Catalog стала публичной. Это не могло не радовать, но вместе с радостью пришли и другие проблемы.

Основной проблемой, как ни странно, стали… деньги. Много денег. Почему-то Palm помимо неповоротливости оказались еще и жадными. Участие в Palm Developer Program стало возможным в трех вариантах:

  • Вы регистрируетесь как open-source разработчик и постите все приложения как бесплатные и с открытими исходниками. За это не платите ничего
  • Вы регистрируетесь, платите $99  в год, а затем !(внимание), получаете ссылку на загрузку своего приложения и распространяете его сами как хотите. Palm всего лишь упоминает ваше приложение в RSS фидах и, собственно, хостит ваш бинарник у себя. Остальное все за вами.
  • Вы регистрируетесь, платите $99 за регистрацию и $50 за каждое приложение, которое попадает в Palm App Catalog. Итого, $150 вы отдаете сразу и неизвестно, будут ли ваше приложение вобще скачивать. В общем, на вид очень опасно, так мне показалось тогда и так же кажется сейчас.

А еще Palm отбирает у вас 30%  с каждой продажи 😉

На самом деле, зарегистрироваться на сайте и скачать SDK (скачать можно официально только после регистрации), можно и бесплатно, но если вы решили распространять свои приложения, то надо проапгрейдить свой аккаунт до статуса разработчика и, все же, выбрать один из трех вариантов. Я решился в конце декабря. К тому времени у меня уже была готова Android-версия SMSMyFile, которая начала продаваться в Android Market и первую прибыль с продаж я решил потратить на регистрацию в Palm App Catalog.

Дело близилось к новому году и когда я решил зарегистрироваться, то с меня взяли не $99 а всего $5 за первый год участия в программе и с последующим продлением за $99. Не знаю, доступна ли эта скидка до сих пор, пробовать второй раз не буду 🙂

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

С PayPal аккаунтом у меня как-то сразу не сложилось. Украины в списке стран в настройках аккаунта не было. Пришлось писать в службу поддержки, от которой ждал ответа две недели. Посоветовали вписать американский адрес и поиспользовать американский PayPal (вобще забавно, представители солидной компании советуют такие не совсем честные махинации). Ну, опыт у меня с этим есть. Вбиваем в качестве адреса адрес банка, выдавшего карту Payoneer, затем указываем американский PayPal.

А дальше? PROFIT? Да щаз! Это только начало…. до профита еще очень и очень долго.

Но тем не менее, этого было достаточно чтобы запостить бесплатное приложение.

Для того чтобы постить платные приложения, надо обязательно указывать американский код налогоплательщика (адрес-то в учетке американский) – ITIN (Individual Taxpayer Identification Number) или EIN (Employer Identification Number), которого у меня, по понятным причинам, отродясь не было.

Но, в Internet есть все. И я нашел компанию, которая предлагала зарегистрировать ITIN/EIN за 100 зеленых американских президентов. Денег заплатил, циферку выслали через 4 дня. Циферка вроде рабочая, указал ее в Google Checkout, Palm App Catalog, Intel AppUp. Документы, подтверждающие действительность этой циферки, обещали прислать в течении 4 недель с момента получения. На данный момент прошло больше 4х недель, а документов еще нет, поэтому ссылку на сайт, предлагающий эту услугу давать не буду до выяснения обстоятельств.

Пока регистрировали EIN, нашел на Хабре информацию о системе AdMob, которая позволяет размещать рекламу в мобильных приложениях. Решил вставить AdMob в SMSMyFile. Для этих целей есть нормальное рабочее SDK для WebOS, заводится с пол-пинка. Подробнее о процессе интегрирования, думаю, расскажу отдельным постом.

Но, судя по статистике за месяц, денег там нет, по крайней мере на WebOS. На данный момент у SMSMyFile около 10000 загрузок, а приносит пользы это несколько десятков центов в день. В приложениях для iPhone от AdMob намного больше толку, но об этом как-то потом расскажу.

Процесс сабмита приложения в Palm App Catalog довольно муторный, требуют кучу разной информации. Если вы указали, что хотите распространять приложение, например, в Германии, то будьте добры, укажите все тексты на немецком, всю локализацию сделайте на немецком. Английский вариант не прокатывает. После того, как вы указали всю информацию, будет еще ревью в Palm перед публикацией.

Но есть несколько моментов, которые я бы назвал положительными:

  • У вас есть уверенность в результате. Если вы постите приложение, то вы можете быть уверены что ревью все-таки будет, а также есть вероятность, стремящаяся к единице, того, что ревью будет выполнено в заявленный срок
  • Если в процессе ревью будут обнаружены несоответствия с UI Guidelines, то вы получите список несоответствий (говорят что в Windows Marketplace for Mobile каждая попытка сабмита стоит $100 и говорят только одну причину отказа, даже если их было несколько. На самом деле, статья со сравнением маркетов меня очень тронула. От Marketplace for Mobile я просто в шоке и уже боюсь туда постить).

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

В качестве платного приложения решил сделать программку, которая сохраняет Web-странички в виде PDF файлов. Работы на это ушло 14 часов. Программка дергает один довольно популярный сервис, который отдает PDF  по GET-запросу, так что, по сути, работа сводилась только к UI.

На этом месте, думаю, стоит заметить вот какую штуку:

  • У меня платный аккаунт в Palm App Catalog
  • У меня в Palm App Catalog уже есть бесплатное приложение
  • Если я пробую запостить еще одно бесплатное приложение, то с меня требуют $50 как за платное. Ну и спрашивается, где здесь PROFIT?
  • Есть возможность запостить бесплатную beta-версию платного приложения. Такой сабмит проходит без ревью и является бесплатным.
  • Кажется, что для бесплатных приложений лучше заводить отдельный аккаунт с Community Membership.

Изначально на сайте Palm Developer Program я регистрировался с e-mail’ом, к которому у меня прикручен украинский PayPal. При попытке оплатить сабмит с американского PayPal’а мне сказали что это какой-то чужой аккаунт, не совпадает с e-mail’ом на сайте и надо его привязать к учетке. Привязать PayPal  стоит $10. В этом месте я отчаянно борюсь с жабой, которая меня уже почти задушила, когда я решил вспомнить, сколько денег я угробил, в общей сложности, на все это 🙂

Дальше был сабмит beta-версии. За 3 дня, пока пользователи тешились бесплатной бетой, я получил около 2000 загрузок и 4 письма в службу поддержки с предложениями новых фич. За эти 3 дня приложение получило рейтинг 5 из 5ти, что очень классно.

Затем был сабмит платной версии, в которой были учтены пожелания пользователей, отписавших на e-mail с предложениями новых фич. Выглядело это все как-то так:

После сабмита за 8 дней приложение скачали (надеюсь что купили) около 400 пользователей. За эти 8 дней рейтинг скатился с 5 до 4.1. То ли при покупке платных приложений пользователи становятся более злыми, то ли “кругом одни враги” 😉

Почему я пишу “надеюсь что купили”? У Palm  какая-то глупая система учета статистики:

  • Вы не можете видеть отдельно количество загрузок каждой версии приложения
  • Вы не можете видеть статистику загрузок за текущий день/неделю/месяц
  • Доступен только общий отчет за прошлый месяц и за все предыдущие, тоесть мониторить статистику в реальном времени нельзя.
  • Статистика загрузок обновляется не сразу, а несколько раз в день. Кажется, раз в 2-4 часа.

Еще более странная у Palm система оплаты. Свои деньги за проданное ПО вы получите “в течении 60ти дней после окончания текущего месяца” дабы не быть голословным, вот ссылка по теме (см. раздел Payment).

Ну вот как-то так. Система работает, будем ждать оплаты.

Немного статистики

  • Потрачено времени – 1 год
  • Потрачено денег – $100 + $5 + $10 + $50
  • Получено прибыли – $9 за AdMob + (unknown) за продажи
  • Всего загрузок бесплатного приложения – 10000 (за 1.5 месяца) + 2200 (за 3 дня)
  • Всего загрузок платного приложения – ~500
  • Левелап получен – да, как всегда

Надеюсь, мои многобукаф кому-то принесут пользу.