Evgenij LegotskojJune 30, 2016, 11:53 a.m.

QML - Lesson 026. Intents with Qt for Android, part 1

The “ intent ” is the main facility for interprocess communication on Android. Basically, an intent is an object that is processed by the operating system and then passed to one or more of the installed applications based on its contents. It could for instance be a request to show a video, in which case the intent type would be ACTION_VIEW and the mime type would be set accordingly. Applications can subscribe to certain intents by setting an intent filter in their manifest files. The first time a type of intent is seen, the user of the device will be presented with a selection of applications known to subscribe to that type of intent. If they choose, they can set a default at this point, or select to be asked for every instance.

This is the first of a few articles showing how to use intents with Qt for Android.

The mechanism itself is quite general. What is described above is one use case, but intents are also used for other things: One such thing is launching services inside the application. This is usually formatted as an “explicit intent”, meaning that the fully qualified name of the service to start is provided, so it cannot be intercepted by any other applications.

Another way intents are used is for broadcasts, for instance when the time zone of the device changes. While the action to view a video described above would only launch the one specific application selected by the user, a broadcast will rather be passed to any application which subscribes to it.

This blog will focus on Android, but a similar mechanism called app extensions was introduced in iOS 8.

In this first article about intents on Android, I will focus on the simplest use case: Creating an implicit intent from Qt to start an unspecified application on the target device. As an example, I have made a simple application which presents food recipes. Each recipe has an estimated time for completion. By clicking a button, you can set a timer using the preferred countdown application on the device. (For a more useful use case, one might imagine a button setting a timer for each of the steps in the recipe’s directions, but for this simple example we will only have a single timer per recipe.)

I won’t go into detail about how the application itself is written, but the code can be found here . No effort has been made to make the UI look nice, so please disregard that. The application is backed by an SQLite database (which is filled with some dummy content the first time the application is started) and has a very simple UI written in Qt Quick Controls 2, allowing the user to select a recipe from a list, see its details on a separate page and click a button on the recipe to set a timer in the system.

The part we will focus on is the code that actually requests the timer from the system. This is in the recipe.cpp file, in the function Recipe::createTimer() . For our example we will be using the AlarmClock.ACTION_SET_TIMER intent type.

We will use the JNI convenience APIs in the Qt Android Extras module for this. I will go through this code step by step.

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());

Since we are only using functions from Qt Android Extras and no explicit calls using the JNI APIs, we don’t have to worry about reference management. This is one primary convenience of the APIs.The first step is to create the intent. We retrieve the identifier of the ACTION_SET_TIMER intent. This is a static member of the android.provider.AlarmClock class and is of type String. Note the use of slashes in place of dots in the package name of the class. This corresponds to the bytecode representation of package names (for historical reasons according to the specification ) and is therefore also used in signatures in JNI.

The next step is to actually create the intent object. We do this by constructing a QAndroidJniObject, passing in the JNI-mangled signature of the Java constructor we want to call and we pass in the ID of the action we just got from the AlarmClock class.

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));

Next up, we set up some arguments we want to send to the activity handling the action. We pass in a description of the timer and the number of seconds to set it for.

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());

Then we have to resolve the activity. This will tell the system to check if there is an application available to handle the ACTION_SET_TIMER action. We first get a reference to the current activity (our current context ) in order to get the appropriate package manager . Then we call resolveActivity() on the intent and pass in the package manager.

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

If the returned component name is non-null, we start the activity using the convenience function in Qt Android Extras. We will look at more features of this function in a later blog. If no appropriate activity is found, then this code only outputs a warning to the console. A proper application might complain in the actual user interface, but note that the operating system has also alerted the user of the problem at this point.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
S

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

Comments

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

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
R
  • Rrrrr
  • Oct. 16, 2020, 5:14 a.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:70points,
  • Rating points1
e

C++ - Test 005. Structures and Classes

  • Result:91points,
  • Rating points8
N

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

  • Result:85points,
  • Rating points6
Last comments
S

QML - Lesson 026. Intents with Qt for Android, part 1

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

Qt/C++ - Lesson 015. QTableWidget – How to create a table with checkboxes?

Кто-нибудь знает, как сделать так, чтобы в QTableWidget состоящей из чекбоксов в строке таблицы можно было выбрать только один checkbox ?

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

QSqlTableModel выполняет ряд стандартных операций для одной таблицы из базы данных. Поэтому там и реализован функционал по удалению и редактированию. QSqlQueryModel позволяет выполнить запр…
VB

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

Добрый день. Хотел спросить вот что. Создал проект на основе QAbstractTableModel. В MainWindow cоответственно создал модель и связал с представлением. Поиск веду по списку элементов модели,…

QCheckBox в качестве делегата QTableView

До тех пор, пока у вас проект содержит только одну таблицу, или несколько то может быть. Когда их будет 1000 и чекбоксы в разных колонках, то без делегатов и переопределения возвращаемых ре…
Now discuss on the forum

Баг в QGraphicsView

решил проблему
CF

Маленький вопрос для знатоков list

Спасибо, я уже понял, в чем было дело) меня запутали квадратные скобки и название простого массива "mylist". Я думал, что [10] это размер листа, а размер листа задается в круглых скобках. Да и …

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

Ну тогда в этом столбце указывайте пути на несколько картинок

Создание иерархии в виде дерева для фронта приложения на Джанго.

1 эндпоинт - элементы дерева, второй - контент. не надо мешать все в кучу. добавился элемент дерева - запрос в первый эндпоинт, вернулся id созданного элемента, и когда создается контент, …

Как вернуться на главное окно проекта в Qt

Разобрался. Задачу решил вот так (может немоного не экономно и топорно, но рабтает): auto widgetList = QApplication::topLevelWidgets(); foreach(auto object, widgetList){ if(ob…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB