Евгений Легоцкой30 июня 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 хостинг.
Поддержать автора Donate
S
  • #
  • 4 октября 2020 г. 17:48
  • (ред.)

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

Комментарии

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

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
ГИ

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

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

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

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

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

  • Результат:57баллов,
  • Очки рейтинга-2
Последние комментарии
ВР

QML - Урок 016. База данных SQLite и работа с ней в QML Qt

Помогите, пожалуйста. У меня похожая задача, но я в qml слой долен передать не чистый запрос, а со сложной обработкой, поэтому у меня в С++ слое есть иерархия классов, которая имитирует бд и зап…
e
  • eviza
  • 16 ноября 2020 г. 4:32

Qt/C++ - Урок 083. Создание динамической библиотеки и подключение её в другой проект

здравствуйте! при компиляции библиотеки выскакивает окно особая программа( не удалось найти программу, укажите путь к ней), и в папке debug создается файл .dll, а .lib нет. подскажите…
ИБ

Шифрование данных в Qt алгоритмом RSA c открытым и закрытым ключами без привязки к OpenSSL

Библиотека подключилась нормально, только на выводе из первого примера выходит пустое сообщение, вместо "test message" просто "". Никаких ошибок не выдает.
VS

Qt WinAPI - Урок 002. Как сделать win инсталлятор для Qt-приложения?

Можно ли как-то однозначно (не проверяя) выяснить, запустится ли программа в windows 7? И как быть с разрядностью уже и просто в w10 (32\64)?
ДТ

Django - Урок 036. Как добавить аутентификацию через социальные сети. ВКонтакте

Возможно, автор прочитает. Делал авторизацию с помощью ВК по книге Дронова. Выдает ошибку "Backend not found". Стал гуглить, нашел вашу статью, вроде почти то же самое (оно и понятно, документа…
Сейчас обсуждают на форуме

Разный масштаб в формах и при запуске

Сврестайте все в один лэйаут (Выбирите окно и нажмити сверху на голубой квадратик из 9 голубфх квадратиков)

Обращение к ячейке таблицы

Вам нужно наследоваться от QAbstractTableModel, выбрать в каких контейнерах и как будите хранить данные и уже у них по индексу будите получать данные. Вот под рукой пример был на питоне, на…

Отправка JSON

postData.addQueryItem("data", doc.toJson(QJsonDocument::Compact).toStdString().c_str()); а почему так? попробуйте эту строку убрать, а эту запись: { "Array": [ t…
ДК

QTableView не становится в редактирование

балин, вот я, конечно, "молодец". минус 5 часов, из-за того, что не поставил в модели флаги. Qt::ItemFlags UserModel::flags(const QModelIndex &index) const{ Qt::ItemFlags flags = Tre…

QSqlTableModel - Как добавить картинки в таблицу, чтобы они отражались в диалоговом окне, но не были частью модели

Ну тогда в этом столбце указывайте пути на несколько картинок
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB