Evgenii Legotckoi
Evgenii Legotckoi30 червня 2016 р. 12:53

QML - Урок 026. Наміри з Qt для Android, частина 1

"Intent" є головною можливістю для міжпроцесорної взаємодії Android. В основному, Intent є об'єктом, який обробляється операційною системою і передається потім одній або більшій кількості встановлених програм, ґрунтуючись на його змісті. Це може бути екземпляр запиту відображення відео, в даному випадку тип intent повинен бути ACTION_VIEW і тип mime повинен бути встановлений відповідний. Програми можуть підписуватись на відповідні Intents у налаштуваннях фільтра intent у своїх маніфест файлах. Вперше користувачеві пристрою буде надано вибір, які типи intent відомі програмі та на які можна передплатити. Якщо вони вибрані, вони будуть встановлені за замовчуванням, або вибрані при питанні від кожного екземпляра програми у разі потреби.

Це перша з кількох статей, як використовувати intents з Qt для Android.

Сам механізм має досить загальний характер. Те, що описано вище є одним із способів використання, але intents також можуть бути використані і для іншого: Одним із таких випадків є запуск сервісів усередині програми. Це зазвичай називається "explicit intent", що означає, що передбачено для запуску повне ім'я сервісу, і не може бути перехоплено іншим додатком.

Іншим способом використання intents є широкомовний варіант (broadcast) для екземплярів, коли змінюється тимчасова зона пристрою. У цей час як дії описані вище дозволяють запускати тільки один певний додаток, обраний користувачем, то при широкомовному варіанті сигнал буде переданий у всі додатки, які були на нього підписані.


Цей варіант націлений на Android пристрої, але схожий механізм, званий app extensions , був введений у iOS 8.

У цій першій статті про intents на Android сфокусуємося на найпростішому варіанті використання: Створення прихованого intent з Qt для запуску невизначеної програми на цільовому пристрої. Наприклад, зроблено простий додаток, який представляє рецепти їжі. Кожен рецепт має час приготування. Натиснувши кнопку, ви можете встановити таймер, використовуючи зворотний відлік на пристрої. (Для більш корисного застосування можна надати кнопку встановлення часу для кожного кроку приготування рецепту, але в цьому простому прикладі використовуватимемо лише один таймер.)

Не будемо вдаватися у подробиці того, як програма була написана, але кому цікаво, то код може бути знайдений тут . Жодних зусиль для покращення зовнішнього вигляду додатка не було, тому не звертайте на це уваги. Програма базується на базі даних SQLite (яка заповнена деяким фейковим контентом при першому запуску) і має дуже простий інтерфейс користувача, написаний на Qt Quick Controls 2, який дозволяє користувачеві вибрати рецепт зі списку, подивитися його опис на окремій сторінці і натиснути кнопку в рецепті для установки таймера до системи.

А тепер сфокусуємось на коді, який фактично вимагає таймер від системи. Це міститься у файлі recipe.cpp , функції Recipe::createTimer() . У прикладі ми використовуємо наступний тип intent - AlarmClock.ACTION_SET_TIMER .

Ми будемо використовувати для цього зручний JNI API із модуля Qt Android Extras . Давайте пройдемо за кодом крок за кроком.

QAndroidJniObject ACTION_SET_TIMER = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock",
                                                                                      "ACTION_SET_TIMER");
QAndroidJniObject intent("android/content/Intent",
                         "(Ljava/lang/String;)V",
                         ACTION_SET_TIMER.object());

Першим кроком створимо intent. Ми приймаємо ідентифікатор ACTION_SET_TIMER intent. Він є статичним учасником у android.provider.AlarmClock класі та має рядковий тип даних (String). Зауважте, що використання слешів замість точок у імені пакета класу. Це співвідноситься з представленням імен пакетів у байткоді (так склалося з історичних причин, дивіться специфікацію . 1) ) і відтак також використовується у підписі JNI.

Оскільки ми використовуємо лише функції з Qt Android Extras і не використовуємо явні виклики до JNI API, ми можемо не турбуватися про еталонному управлінні. Це головна зручність цього API.

Наступним кроком ми створимо об'єкт intent. Ми зробимо це, побудувавши QAndroidJniObject і передавши його в JNI-розбірник підписів Java конструктора, який бажаємо викликати, а також передамо ID дії, яку хочемо отримали з класу AlarmClock.

QAndroidJniObject EXTRA_MESSAGE = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock",
                                                                                   "EXTRA_MESSAGE");
QAndroidJniObject messageObject = QAndroidJniObject::fromString(message);
intent.callObjectMethod("putExtra",
                        "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;",
                        EXTRA_MESSAGE.object(),
                        messageObject.object());

QAndroidJniObject EXTRA_LENGTH = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock",
                                                                                  "EXTRA_LENGTH");
intent.callObjectMethod("putExtra",
                        "(Ljava/lang/String;I)Landroid/content/Intent;",
                        EXTRA_LENGTH.object(),
                        jint(m_time * 60));

QAndroidJniObject EXTRA_SKIP_UI = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock",
                                                                                  "EXTRA_SKIP_UI");
intent.callObjectMethod("putExtra",
                        "(Ljava/lang/String;Z)Landroid/content/Intent;",
                        EXTRA_SKIP_UI.object(),
                        jboolean(true));

Наступним кроком ми встановимо кілька аргументів, які хочемо надіслати в обробник дії Activity. Ми передаємо в описі таймер та кількість секунд для встановлення.

QAndroidJniObject activity = QtAndroid::androidActivity();
QAndroidJniObject packageManager = activity.callObjectMethod("getPackageManager",
                                                             "()Landroid/content/pm/PackageManager;");
QAndroidJniObject componentName = intent.callObjectMethod("resolveActivity",
                                                          "(Landroid/content/pm/PackageManager;)Landroid/content/ComponentName;",
                                                          packageManager.object());

Потім ми дозволяємо цю дію. Вона скаже системі перевірити, чи є програма для обробки дії ACTION_SET_TIMER. І тоді ми спочатку отримаємо поточну діяльність (у нашому поточному контексті) для того, щоб отримати відповідний пакетний менеджер. Потім викличемо resolveActivity() на intent для передачі його в пакетний менеджер.

if (componentName.isValid()) {
    QtAndroid::startActivity(intent, 0);
} else {
    qWarning() << "Unable to resolve activity";
}

Якщо повернене ім'я компонента є ненульовим, ми запускаємо activity використовуючи зручну функцію в Qt Android Extras. Якщо відповідної діяльності не було знайдено, тоді зробимо висновок про помилку в консоль. Правильне застосування має повідомляти про помилку в інтерфейсі користувача, але зауважте, що операційна система також повідомить користувачеві про проблеми в цьому місці.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

S
  • 04 жовтня 2020 р. 17:48
  • (відредаговано)

Есть ли возможность приведения java типа у QAndroidJniObject? Интересует конкретно class to

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 11:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 11:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 22:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi01 листопада 2024 р. 00:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 18:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 17:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 21:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi25 червня 2024 р. 01:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 17:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 13:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 19:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Слідкуйте за нами в соціальних мережах