Evgenii Legotckoi
Evgenii Legotckoi30 июня 2016 г. 22:53

QML - Урок 026. Intents с 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). Заметьте, что использование слэшей вместо точек в имени пакета класса. Это соотносится с представление имён пакетов в байткоде (так сложилось по историческим причинам, смотрите спецификацию )  и следовательно также используется в подписи 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());

Затем мы разрешаем данную activity. Она скажет системе проверить, доступно ли приложение для обработки действия ACTION_SET_TIMER. И тогда мы сначала получим текущую activity (в нашем текущем контексте) для того, чтобы получить соответствующий пакетный менеджер. Затем вызовем resolveActivity() на intent для передачи его в пакетный менеджер.

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

Если возвращённое имя компонента является ненулевым, то мы запускаем activity используя удобную функцию в Qt Android Extras. Если соответствующей activity не было найдено, тогда сделаем вывод об ошибке в консоль.  Правильное приложение должно сообщать об ошибке в пользовательском интерфейсе, но заметьте, что операционная система также сообщит пользователю о проблемах в этом месте.

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

Вам это нравится? Поделитесь в социальных сетях!

S
  • 5 октября 2020 г. 3:48
  • (ред.)

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

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Lz

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

  • Результат:70баллов,
  • Очки рейтинга1
РК

Qt - Тест 001. Сигналы и слоты

  • Результат:84баллов,
  • Очки рейтинга4
ВМ

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

  • Результат:80баллов,
  • Очки рейтинга4
Последние комментарии
k
kmssr8 февраля 2024 г. 15:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко4 февраля 2024 г. 22:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 7:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 5:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik18 декабря 2023 г. 18:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
NSProject
NSProject23 июня 2024 г. 10:48
добавить qlineseries в функции А куда собстаенно делся Евгений раз на сайте такой бордак творится?
BlinCT
BlinCT5 мая 2024 г. 2:46
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii Legotckoi2 мая 2024 г. 11:07
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderChe30 апреля 2024 г. 1:22
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…
G
Gar22 апреля 2024 г. 2:46
Clipboard Как скопировать окно целиком в clipb?

Следите за нами в социальных сетях