Опубліковано: 25 Жовтня 2017
Модуль App Control. Запуск сторонніх додатків

У цьому уроці ми розглянемо модуль управління додатками, його основні функції і типи даних, види запуску додатків, а також можливість ділитись функціоналом одного додатку з іншим.

Також у цьому уроку ми подивимось, як закінчити 4-е демо, яке ви почали в 24 уроку, додавши в нього можливість запускати вибраний додаток. А також реалізуємо на мобільному пристрої, прив’язаному до годинника, запуск Samsung Galaxy Apps на сторінці з потрібним додатком.

Короткий опис модулю

Модуль управління додатками (App Control) використовується для запуску одного додатку з іншого.

Керування додатком – це також можливість ділитись функціональністю одного додатку з іншим. Спільне використання ресурсів оптимізує затрати часу на розробку. Наприклад, ви хочете додати можливість робити телефонний виклик певного номеру, для цього необхідно запустити вбудований на пристрої додаток для дзвінків, вказавши, яка функціональність вас цікавить. Додаток, що викликає також може отримати результат виконання запитуваної функціональності від додатку який викликають, якщо така опція була реалізована.

У модулі управління додатком існує два види запуску додатків: явний і неявний. Водночас вид запуску залежить від того, чи відомий ідентифікатор додатку, який ви хочете запустити.

Перед тим як розглянути види запуску додатків, розглянемо функції і типи управління додатком.

Основні функції і типи даних App Control

Для використання функцій і типів даних модуля керування додатками, необхідно включити в проект наступний заголовний файл:

#include <app_control.h>

Також варто відзначити, що даний заголовний файл входить в заголовний файл "app.h".

Для використання в своєму додатку функціональності даного модулю, необхідно додати в маніфест-файл наступний привілей:

"http://tizen.org/privilege/appmanager.launch"

Основним типом модулю, який розглядається є app_control_h.

У першу чергу необхідно створити об’єкт управління додатком, для цього потрібно викликати наступну функцію:

int app_control_create(app_control_h *app_control);

Першим параметром є вказівник на об’єкт управління додатком. У разі успішного виконання функція повертає нуль, а в разі помилки – негативне число.

Аби відправити запит платформі на запуск налаштованого об’єкту додатку, необхідна наступна функція:

int app_control_send_launch_request(app_control_h app_control,
                                    app_control_reply_cb callback,
                                    void *user_data);

Перший параметр – це вказівник на об’єкт управління додатком, другий параметр – вказівник на функцію для отримання результату виконання додатку, що викликається (якщо такий наявний) і третій параметр – це вказівник на дані користувача, що передаються у функцію, яка приходить у другому параметрі. У разі успішного виконання функція повертає нуль, у разі помилки – негативне число.

У кінці необхідно видаляти створений об’єкт керування додатками, використовуючи наступну функцію:

int app_control_destroy(app_control_h app_control);

Функція приймає в якості параметра об’єкт, який потрібно видалити і повертає нуль у разі успішного виконання і ненульове число у разі помилки.

Приклади використання вище перерахованих функцій будуть розглянуті далі в цьому уроку.

Явний запуск додатку

Тепер перейдемо до розгляду видів запуску додатку. Для початку ознайомимось з явним запуском, який передбачає запуск з явним вказанням ідентифікатора того додатку, який ви хочете запустити з вашої програми.

Для того аби вказати, який додаток вас цікавить, розгляньте наступну функцію:

int app_control_set_app_id(app_control_h app_control, const char *app_id);

Перший параметр – це об’єкт управління додатком, а другий – це вказівник на рядок, що містить ідентифікатор додатку. У разі успішного виконання функція повертає нуль, а у разі помилки – ненульове число.

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

Спочатку необхідно додати в маніфест файл привілей на використання функції для запуску додатків.

"http://tizen.org/privilege/appmanager.launch"

Для цього відкрийте у вашому проекті tizen-mainfest.xml файл.

Перейдіть на вкладку: Privileges. nw_027_01_en

Натисніть на кнопку "+".

У діалоговому вікні, що відкрилось, необхідно вибрати потрібний привілей і натиснути OK.

nw_027_02_en

Збережіть файл.

Оскільки, як було сказано вище, заголовний файл "app_control.h" неявно включений до заголовного файлу "app.h", то в даному демо немає необхідності підключати його, аби мати можливість працювати з модулем управління додатками.

Тепер змініть функцію створення rotary selector віджета. У структурі Eext_Object_Item створеного елементу, додайте в поле data вказівник на структуру Application_Info, що містить інформацію про додаток, яку ви будете обробляти при натисканні на елемент rotary selector.

У rotary selector віджеті зареєструйте обробник натискання на елемент, передавши останнім параметром, у якості даних користувача, вказівник на UIData структуру.

static void
_rotary_selector_create(UIData *ui)
{
   ...

   Application_Info *app_info = NULL;
   EINA_LIST_FOREACH(ui->list_package, iterator, app_info)
     {
        Eext_Object_Item *item = eext_rotary_selector_item_append(ui->rotary_selector);
        item->data = app_info;

        ...
     }

   evas_object_smart_callback_add(ui->rotary_selector,
                                  "item,clicked",
                                  _item_clicked_cb,
                                  ui);
   ...
}

Реалізуйте обробник натискання на елемент rotary selector, додавши виклик розглянутих вище функцій для запуску додатків. Тепер обробник виглядає наступним чином:

static void
_item_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
   dlog_print(DLOG_INFO, LOG_TAG, "Елемент натиснутий");

   UIData *ui = (UIData *)data;

   Eext_Object_Item *item = eext_rotary_selector_selected_item_get(ui->rotary_selector);
   Application_Info *application_info = item->data;

   app_control_h a_control;
   app_control_create(&a_control);
   app_control_set_app_id(a_control, application_info->app_id);
   if (app_control_send_launch_request(a_control, NULL, NULL) != APP_CONTROL_ERROR_NONE)
     dlog_print(DLOG_INFO, LOG_TAG, "Помилка запуску додатку");

   app_control_destroy(a_control);

   dlog_print(DLOG_INFO, LOG_TAG, "ID додатку: %s", application_info->app_id);
}

У цій функції ви отримуєте вказівник на виділений елемент rotary selector. Далі через поле data структури елементу отримайте вказівник на структуру, що містить інформацію про вибраний додаток. Тут вас цікавить поле, що містить ідентифікатор додатку. Створіть об’єкт управління додатками, задайте отриманий ідентифікатор додатку і виконайте запит на запуск цього додатку, а потім перевірте статус виконання.

Запустіть додаток і з rotary selector віджету запустіть, наприклад, календар і телефон.

Якщо ви у віджеті rotary selector натиснете на вибраному елементі, то вказаний додаток запуститься через деякий час. Те на скільки буде відтерміновано запуск, залежить від додатку.

Варто відзначити, що тут було розглянуто простий вид запуску додатку, виконати який можна викликавши функцію:

app_manager_open_app(const char *app_id)

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

Неявний запуск додатку (теорія)

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

Аби визначити який додаток буде запущено, на рівні платформи, сервіс порівнює всі додатки на пристрої з запитуваною операцією, URI (уніфікований ідентифікатор ресурсу) і MIME типами на те, чи відповідають вони запитуваним умовам. Якщо тільки один додаток відповідає запитуваним умовам, то він одразу ж буде запущений, якщо ж буде знайдено декілька додатків, то система запропонує користувачу вибрати, що запускати.

Якщо ви пишете додаток і хочете аби частина його функціональності була доступна для інших додатків, то в маніфест файлі додатку необхідно налаштувати такі параметри як: запитувану операцію, URI, MIME тип.

Нижче приведемо перелік функцій, які необхідні для налаштування функціональності запуску додатку. Для встановлення типу виконуваної операції, необхідно викликати функцію:

int app_control_set_operation(app_control_h app_control, const char *operation);

Перший параметр – це об’єкт управління додатком, другий параметр – вказівник на рядок, що містить виконувану операцію. У разі успішного виконання функція повертає нуль, у разі помилки – ненульове число.

У заголовному файлі "app_control.h" вказано перелік виконуваних операцій, нижче перераховані ті з них, що виконуються найчастіше:

APP_CONTROL_OPERATION_DEFAULT – операція за замовчанням
APP_CONTROL_OPERATION_VIEW – для перегляду контенту 
APP_CONTROL_OPERATION_PICK – для  вибору контенту 
APP_CONTROL_OPERATION_CALL – для здійснення викликів, наприклад, телефонного номеру 
APP_CONTROL_OPERATION_SEARCH – для пошуку контенту 
APP_CONTROL_OPERATION_SEND_TEXT – для відправки тексту, наприклад, текстового повідомлення 

Якщо ви вказуєте в якості виконуваної операції APP_CONTROL_OPERATION_DEFAULT, то необхідно явно вказати який додаток вас цікавить, викликавши функцію app_control_set_app_id(), яка була розглянена у попередньому розділі.

Аби встановити URI дані, використовуйте наступну функцію:

int app_control_set_uri(app_control_h app_control, const char *uri);

Перший параметр – це об’єкт управління додатками, другий параметр – це вказівник на рядок, який містить URI дані, наприклад шлях до файлу. У разі успішного виконання функція повертає нуль, а в разі помилки – ненульове число.

Для того аби явно встановити MIME тип даних, необхідно використовувати наступну функцію:

int app_control_set_mime(app_control_h app_control, const char *mime);

Перший параметр - це об’єкт управління додатками, другий параметр – це вказівник на рядок, що містить MIME тип даних. У разі успішного виконання функція повертає нуль, а в разі помилки – ненульове число.

Варто зазначити, що встановлення MIME типу - це своєрідний фільтр, наприклад, ви хочете вибрати картинки з Галереї, але вас цікавлять лише картинки, що мають розширення .jpg.

Як вже було сказано, у більшості додатків, що запускаються, реалізована можливість повертати результат на виконання запитуваної функціональності, наприклад, вибір картинки в додатку Галерея. Розглянемо основні функції, необхідні для обробки отриманого результату. Для початку розглянемо оголошення функції обробника, яка вказується у функції app_control_send_launch_request() другим параметром.

typedef void (*app_control_reply_cb) (app_control_h request,
                                      app_control_h reply,
                                      app_control_result_e result,
                                      void *user_data);

Цей обробник спрацьовує, коли додаток, що викликається має повернути результат роботи запитуваної функціональності, якщо така наявна.

Перший параметр – це об’єкт управління додатку, який був відправлений з вашої програми, другий параметр - це об’єкт управління додатку, який містить відповідь від додатку, що викликається, третій параметр – це код результату запиту, що запускається, четвертий – дані користувача. Приведемо перелік можливих значень коду результату додатку, що викликається.

APP_CONTROL_RESULT_SUCCEEDED – операція виконана успішно
APP_CONTROL_RESULT_FAILED – помилка виконання операції 
APP_CONTROL_RESULT_CANCELED – виконання операції було скасовано 

Після перевірки на успішність виконання операції, необхідно отримати дані від додатку, для цього використовуйте другий параметр reply розглянутого обробника.

Необхідно відзначити, що відповідь завжди містить поняття пари ключ-значення. Можливі два види отримання даних: з відомим і не відомим ключем.

Якщо ви не знаєте назву ключа відповіді, то необхідно викликати приведену нижче функцію для вибірки по всіх повернених ключах з викликаного додатку.

int app_control_foreach_extra_data(app_control_h app_control,
                                   app_control_extra_data_cb callback,
                                   void *user_data);

Перший параметр – це об’єкт управління додатками, який містить в собі відповідь від повідомлення, що викликається, другий параметр – це вказівник на функцію-обробник, що запускається для вибірки кожного ключа, третій параметр – це дані користувача. У разі успішного викання функція повертає нуль, а у разі помилки – ненульове число.

Розглянемо оголошення функції обробника:

typedef bool (*app_control_extra_data_cb)(app_control_h app_control,
                                          const char *key,
                                          void *user_data);

Перший параметр - це об’єкт управління додатками, а другий параметр - це вказівник на рядок, що містить вибраний ключ, і третій параметр - вказівник на дані користувача. Обробник повинен повертати логічний признак по вказаному ключу. Значення завжди передаються у вигляді рядків, як вказівник на символ. Передати можна як одне значення, так і масив значень. Для того аби отримати одне значення по ключу, необхідно викликати наступну функцію:

int app_control_get_extra_data(app_control_h app_control, const char *key, char **value);

Перший параметр – це об’єкт управління додатками, другий параметр – це вказівник на рядок, що містить ключ, третій параметр – це подвійний вказівник, який містить дані, які будуть заповнені всередині функції. У разі успішного виконання функція повертає нуль, а в разі помилки – ненульове число.

Отримані дані необхідно обов’язково видаляти.

Для отримання масиву значень за ключем, необхідно викликати наступну функцію:

int app_control_get_extra_data_array(app_control_h app_control,
                                     const char *key,
                                     char ***value,
                                     int *length);

Перший параметр – це об’єкт управління додатками, другий параметр - це вказівник на рядок, що містить ключ, третій параметр – це адреса масиву рядків, що містить дані, які будуть заповнені всередині функції, четвертий параметр – це вказівник на розмір отриманого масиву. У разі успішного виконання функція повертає нуль, а в разі помилки – ненульове число. Після завершення роботи, отримані дані потрібно видаляти. Якщо ви знаєте ключ, який містить відповідь додатку, що викликається, то можна одразу викликати функції для отримання даних по цьому ключу, без виклику вибірки всіх ключів.

Неявний запуск додатку (Практика)

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

За основу візьміть шаблон, який ви почали в 24 уроку, коли розглядали rotary selector віджет. Додайте декілька елементів у rotary selector. При натисканні на перший елемент буде запускатись додаток для вибору лише .png зображень, і повернення результату у вигляді шляху до вибраного зображення. При натисканні на другий – буде запускатись додаток для перегляду вибраного зображення. Варто відзначити, що назви та ідентифікатори додатків нам невідомі, все виконується на рівні платформи.

Додайте привілей в маніфест.

"http://tizen.org/privilege/appmanager.launch"

Додайте в структуру UIData поле, що містить шлях до вибраного зображення.

typedef struct _UIData {
   ...

   char *image_path;
} UIData;

Створіть дві глобальні цілочисельні статичні константи, які необхідні для того аби ідентифікувати, який елемент був натиснутий в rotary selector.

static const int FIRST_ITEM  = 1;
static const int SECOND_ITEM = 2;

Тепер внесемо зміни у функцію створення rotary selector.

static void
_rotary_selector_create(UIData *ui)
{
   ui->rotary_selector = eext_rotary_selector_add(ui->conform);
   eext_rotary_object_event_activated_set(ui->rotary_selector, EINA_TRUE);

   Eext_Object_Item *item = eext_rotary_selector_item_append(ui->rotary_selector);
   item->data = (void *)&FIRST_ITEM;
   eext_rotary_selector_item_part_text_set(item,
                                           "selector,main_text",
                                           "Вибір");

   item = eext_rotary_selector_item_append(ui->rotary_selector);
   item->data = (void *)&SECOND_ITEM;
   eext_rotary_selector_item_part_text_set(item,
                                           "selector,main_text",
                                           "Перегляд");

   evas_object_smart_callback_add(ui->rotary_selector,
                                  "item,clicked",
                                  _item_clicked_cb,
                                  ui);

   elm_object_content_set(ui->conform, ui->rotary_selector);
   evas_object_show(ui->rotary_selector);
}

Аби мати змогу ідентифікувати елементи - у цій функції створюється два елементи і полю data присвоюється значення.

Змініть обробник натискання на елемент віджету.

static void
_item_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
   dlog_print(DLOG_INFO, "lesson27", "Елемент натиснутий");
  
   app_control_h a_control;

   UIData *ui  = (UIData *)data;
   Eext_Object_Item *item = eext_rotary_selector_selected_item_get(ui->rotary_selector);

   int *item_data   = item->data;
   bool is_first_item  = (*item_data == FIRST_ITEM);
   const char *type_operation    = is_first_item ? APP_CONTROL_OPERATION_PICK :   APP_CONTROL_OPERATION_VIEW;
    
   app_control_reply_cb reply_cb = is_first_item ? _pick_image_cb : NULL;
   app_control_create(&a_control);
   app_control_set_operation(a_control, type_operation);
   if (!is_first_item)
     app_control_set_uri(a_control, ui->image_path);

   app_control_set_mime(a_control, "image/png");
   if (app_control_send_launch_request(a_control, reply_cb, data) != APP_CONTROL_ERROR_NONE)
     dlog_print(DLOG_INFO, "lesson27", "Помилка запуску додатку ");

   app_control_destroy(a_control);
}

Одразу ж видаліть обробник _item_selected_cb().

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

Якщо ви обрали другий елемент, то вас цікавить додаток, який відобразить вибрану раніше картинку, для цього ви вказуєте, що вас цікавить додаток, який вміє відображати для перегляду зображення без можливості редагувати в форматі.png.

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

static void
_pick_image_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
{
   app_control_foreach_extra_data(reply, _app_control_extra_foreach_data_cb, user_data);
}

Тепер напишіть функцію-обробник вибірки ключів. У ній ви ітеруєте дані по першому ключу, який містить абсолютний шлях до обраного зображення. Далі збережіть отримані дані в змінній image_path структури UIData. Також виведіть в логування абсолютний шлях для вибраного зображення. І поверніть результат, аби зупинити вибірку.

static bool
_app_control_extra_foreach_data_cb(app_control_h app_control,
                                   const char *key,
                                   void *user_data)
{
   UIData *ui   = (UIData *)user_data;
   char **value = NULL;
   int length   = 0;

   app_control_get_extra_data_array(app_control, key, &value, &length);
   if (length > 0)
     {
        if (ui->image_path)
          free(ui->image_path);

        ui->image_path = strdup(value[0]);
        dlog_print(DLOG_INFO, LOG_TAG, "Шлях до зображення: %s", ui->image_path);
        for (int i = 0; i < length; ++i)
          {
             free(value[i]);
          }

        free(value);
     }

   return false;
}

Запустіть додаток.

На екрані ви маєте побачити два елементи. При натисканні на перший елемент – запуститься додаток, який пропонує вибрати одне зображення із списку (тут варто зазначити, аби побачити список зображень, необхідно щоб, на годиннику, додаток Галерея містив хоча б одне зображення). Якщо ви виберете зображення і натиснете на другий елемент, запуститься додаток, який на весь екран відобразить ваше зображення. Запустіть логування. Якщо ви вибирете картинку в додатку, що запускається, то в логування буде виводитись абсолютний шлях цієї картинки.

Шлях до зображення: /opt/usr/media/Images/12.png 
Шлях до зображення: /opt/usr/media/Images/18.png

Ви можете скачати повний код даного прикладу тут WearLesson027.

Запуск Samsung Galaxy Apps на телефоні

Далі ми продовжимо розповідати, як писати демо-додаток, на якому ми зупинились в 3-му розділі цього уроку, додавши в нього цікаву можливість – запуск з годинника Samsung Galaxy Apps на телефоні із посиланням на сторінку додатку в маркеті. Навіщо це може знадобитись? Уявімо таку картину: у вас є додаток, який залежить від іншого додатку, але другий додаток не встановлено на годиннику. У цьому разі ви можете запропонувати завантажити його, відкривши магазин із посиланням на потрібний додаток. Або ви можете запропонувати користувачу оцінити ваш додаток в магазині, відразу відкривши йому необхідну сторінку.

Але перед тим як перейти до написання функціональності для вашого демо-додатку, необхідно розглянути декілька функції.

Для того аби передати додатку, що викликаються параметри у вигляді пар ключ-значення - необхідно викликати наступну функцію:

int app_control_add_extra_data(app_control_h app_control,
                               const char *key,
                               const char *value);

Перший параметр - це об’єкт управління додатками, другий параметр – це вказівник на структуру, що містить ключ, третій параметр – це вказівник на рядок, що містить значення. У разі успішного виконання функція повертає нуль, а в разі помилки – негативне число.

Ну і в доповнення до функції передачі одного значення, розглянемо, як передати масив значень по одному ключу.

int app_control_add_extra_data_array(app_control_h app_control,
                                     const char *key,
                                     const char* value[],
                                     int length);

Вона схожа на функцію передавання одного параметру, за вийнятком того, що замість вказівника на рядок передається масив вказівників на рядки, що містять значення. Також необхідно вказати розмір масиву, що передається.

Розглянувши необхідні функції, переходьте до практики і закінчіть цей демо-додаток.

Додайте в нього наступну функціональність: уявімо, що у вас у списку є додаток Калькулятор, але він не встановлений на годиннику. Потрібно зробити так, аби при натисканні на елемент rotary selector віджету перевіряти чи встановлено додаток, і якщо він встановлений, то запускати на телефоні магазин з посиланням на додаток Калькулятор.

Змініть трохи структуру Application_Info, додавши в неї поле, що містить ідентифікатор пакету.

typedef struct _Application_Info {
   ...

   char *pkg_id;
} Application_Info;

Додайте дві глобальні статичні константи, які містять ідентифікатор додатку і ідентифікатор пакету Калькулятора.

static const char *calculator_pkg_id = "com.samsung.d-calculator-wc1";
static const char *calculator_app_id = "com.samsung.d-calculator-wc1";

Вони необхідні для перевірки чи встановлено додаток Калькулятор. Тут варто відзначити, що ви можете вибрати будь-який додаток, що вас цікавить, але для цього вам необхідно знати його ідентифікатор та ідентифікатор пакету.

Ідентифікатори для Калькулятора були визначені в ході виконання функції, яка проітерувала всі встановлені пакети.

Змініть функцію обробника вибірки встановлених додатків, додавши збережені ідентифікатори пакету.

static bool
_app_manager_app_info_cb(app_info_h app_info, void *user_data)
{
   ...

   app_info_get_package(app_info, &(application_info->pkg_id));
   dlog_print(DLOG_INFO, LOG_TAG, "ID пакета: %s", application_info->pkg_id);

   ...

   return true;
}

Тепер у завершальному обробнику необхідно очистити пам'ять.

static void
_app_terminate_cb(void *data)
{
   ...

   EINA_LIST_FREE(ui->list_package, app_info)
     {
        FREE_RESOURCE(app_info->label);
        FREE_RESOURCE(app_info->path_icon);
        FREE_RESOURCE(app_info->app_id);
        FREE_RESOURCE(app_info->pkg_id);
        FREE_RESOURCE(app_info);
     }
}

Трохи перепишіть функцію додавання rotary selector віджета. У ній додайте перевірку чи встановлено на годиннику додаток Калькулятор і якщо ні – додайте пустий елемент в rotary selector.

static void
_rotary_selector_create(UIData *ui)
{
   bool is_find_calculator_app = false;

   ...
   EINA_LIST_FOREACH(ui->list_package, iterator, app_info)
     {
        if (!strcmp(calculator_app_id, app_info->app_id))
          is_find_calculator_app = true;

        ...
     }

   if (!is_find_calculator_app)
     {
        Application_Info *calculator_info = calloc(1, sizeof(Application_Info));
        if (calculator_info)
          {
             memset(calculator_info, 0x0, sizeof(Application_Info));

             calculator_info->app_id = strdup(calculator_app_id);
             calculator_info->pkg_id = strdup(calculator_pkg_id);
             calculator_info->label = strdup("Калькулятор");

             ui->list_package = eina_list_append(ui->list_package, calculator_info);
             Eext_Object_Item *item = eext_rotary_selector_item_append(ui->rotary_selector);
             item->data = calculator_info;
             eext_rotary_selector_item_part_text_set(item,
                                                     "selector,main_text",
                                                     calculator_info->label);
          }
     }

   ...
}

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

static void
_item_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
   ...

   if (app_control_send_launch_request(a_control, NULL, NULL) == APP_CONTROL_ERROR_APP_NOT_FOUND)
     {
        _gear_samsung_app_launch(application_info->app_id);
     }

   ...
}

Напишіть реалізацію функції, яка буде запускати магазин з вказаним додатком.

static void
_gear_samsung_app_launch(const char *pkg_id)
{
   app_control_h a_control;
   char appl_url_link[PATH_MAX] = {'\0'};
   const char *samsung_url      = "samsungapps://ProductDetail/";
   snprintf(appl_url_link,
            strlen(samsung_url) + strlen(pkg_id) + 1,
            "%s%s",
            samsung_url,
            pkg_id);

   app_control_create(&a_control);

   app_control_set_operation(a_control, APP_CONTROL_OPERATION_DEFAULT);
   app_control_set_app_id(a_control, "com.samsung.w-manager-service");
   app_control_add_extra_data(a_control, "type", "gear");
   app_control_add_extra_data(a_control, "deeplink", appl_url_link);
   app_control_send_launch_request(a_control, NULL, NULL);

   app_control_destroy(a_control);
}

У цій функції варто звернути увагу на ідентифікатор додатку, який встановлений на годиннику. Саме він і запускає маркет на телефоні. Не забутьте вказати, що вас цікавлять тільки gear додатки. Крім того, надзвичайно важливо вказати url посилання на ваш додаток у маркеті. У наслідок склеювання двох рядків, для Калькулятора у вас має вийти наступне посилання: "samsungapps://ProductDetail/com.samsung.d-calculator-wc1".

Відредагуйте обробник апаратної кнопки Назад.

static void
_win_back_cb(void *data, Evas_Object *obj, void *event_info)
{
   ui_app_exit();
}

Запустіть додаток.

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

На цьому робота над демо-додатком номер 4 – завершена.

Повний початковий код ви можете скачати тут WearLesson027.

Обробник події App Control життєвого циклу

Варто також згадати ще один дуже важливий системний обробник. У нього передається інформація у вигляді об’єкту керування додатками. Якщо цей об’єкт пустий, значить додаток запустив користувач з системного лаунчера, якщо він не пустий - ваш додаток був запущений іншим додатком. Його сигнатура наступна:

app_control_cb app_control;

Оголошення обробника:

typedef void (*app_control_cb) (app_control_h app_control, void *user_data);

Як бачимо, цей обробник відрізняється від інших одним параметром, а саме - об’єктом управління додатками, в якому міститься додаткова інформація (за умови, що додаток був запущений іншим додатком).

Цей обробник встановлюється в структурі ui_app_lifecycle_callback_s, у якій вказуються обробник на створення і на видалення додатку і т.д.

Необхідно описати життєвий цикл цього обробника. Якщо додаток запускається вперше, то спочатку викликається обробник створення додатку, а потім обробник управління додатком. Якщо додаток запущено і ви його відкриваєте іншим додатком, то викликається обробник на відновлення роботи додатку (resume), а потім обробник на керування додатками. Це дуже важливо, якщо додаток має мати різний вигляд у залежності від того хто і з якими умовами його запускає, наприклад, як відкривається додаток Галерея: з можливістю вибирати із багатьох чи відобразити одне зображення.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *