Evgenii Legotckoi
Evgenii Legotckoi30 июня 2016 г. 12: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
  • 4 октября 2020 г. 17:48
  • (ред.)

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

Комментарии

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

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

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

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

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

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

  • Результат:20баллов,
  • Очки рейтинга-10
Последние комментарии
ИМ
Игорь Максимов22 ноября 2024 г. 11:51
Django - Урок 017. Кастомизированная страница авторизации на Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 октября 2024 г. 14:37
Django - Урок 064. Как написать расширение для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 октября 2024 г. 8:19
Читалка fb3-файлов на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5 октября 2024 г. 7:51
Django - Урок 064. Как написать расширение для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55 июля 2024 г. 11:02
QML - Урок 016. База данных SQLite и работа с ней в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Сейчас обсуждают на форуме
m
moogo22 ноября 2024 г. 7:17
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii Legotckoi24 июня 2024 г. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 ноября 2024 г. 6:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject4 июня 2022 г. 3:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

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