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
e
  • ehot
  • 31 березня 2024 р. 21:29

C++ - Тест 003. Условия и циклы

  • Результат:78бали,
  • Рейтинг балів2
B
  • Bogdannn
  • 28 березня 2024 р. 02:21

C++ - Тест 002. Константы

  • Результат:16бали,
  • Рейтинг балів-10
B
  • Bogdannn
  • 28 березня 2024 р. 02:15

C++ - Тест 001. Первая программа и типы данных

  • Результат:46бали,
  • Рейтинг балів-6
Останні коментарі
k
kmssr09 лютого 2024 р. 02:43
Qt Linux - Урок 001. Автозапуск програми Qt під Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко05 лютого 2024 р. 09:50
Qt WinAPI - Урок 007. Робота з ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 грудня 2023 р. 18:30
Boost - статичне зв&#39;язування в проекті CMake під Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 грудня 2023 р. 16:38
Boost - статичне зв&#39;язування в проекті CMake під Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 грудня 2023 р. 05:01
Qt/C++ - Урок 056. Підключення бібліотеки Boost в Qt для компіляторів MinGW і MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Тепер обговоріть на форумі
DA
Dr Gangil Academics20 квітня 2024 р. 14:45
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasov14 квітня 2024 р. 13:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 квітня 2024 р. 09:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex04 квітня 2024 р. 11:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…
P
Pisych27 лютого 2023 р. 12:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))

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