QtAndroid details (4): JNI calls Android system functions (1), qtandroidjni

Source: Internet
Author: User

QtAndroid details (4): JNI calls Android system functions (1), qtandroidjni

In the previous sections, we have explained the basic usage of the QtAndroid namespace. This time, we will use the methods and class libraries we mentioned earlier to demonstrate some simple small examples. In my book Qt on Android core programming, I mainly call some Android functions by inheriting QtActivity, implementing my own Activity and adding static methods. In this series of articles, we mainly use the methods in the QtAndroid namespace introduced in Qt 5.3 and the QAndroidJniObject class to demonstrate how to call JNI in Qt and rewrite QtActivity only when necessary.

Based on your needs, Qt on Android applications often call some functions provided by the Android system, such as determining network connections, obtaining external storage paths, or caching file directories. These are frequently asked by friends. In this series of articles, I will demonstrate the features frequently used in Qt on Android development. Hope to help you.

Example

The example is simple. It is displayed using Qt Widgets. Result:



As shown in, the interface is very simple. Click the Refresh button to obtain information about the Android system and the current application and put it in the QListWidget. Includes the following content:

  • Android version of the mobile phone
  • Network Status and network information
  • Mobile phone data directory
  • Mobile phone external storage directory
  • Mobile phone photos, music, videos, ringtones, and other directories
  • Application Path
  • Location of the APK retained by the system after installation
  • Application files directory

Source code analysis

The Code has no logic to explain ...... All in the following:

# Include "widget. h "# include <QVBoxLayout> # include <QListWidgetItem> # include <QtAndroid> # include <QAndroidJniEnvironment> # include <QAndroidJniObject> # include <QDebug> using namespace QtAndroid; # define CHECK_EXCEPTION () \ if (env-> ExceptionCheck () \ {\ qDebug () <"exception occured"; \ env-> ExceptionClear (); \} Widget:: Widget (QWidget * parent): QWidget (parent) {QVBoxLayout * layout = new QVBoxLayout (this ); M_refresh = new QPushButton ("Refresh"); connect (m_refresh, SIGNAL (clicked (), this, SLOT (onRefresh ())); layout-> addWidget (m_refresh); m_list = new QListWidget (); layout-> addWidget (m_list, 1);} Widget ::~ Widget () {} void Widget: onRefresh () {m_list-> clear (); QAndroidJniEnvironment env; // get Android SDK version m_list-> addItem (QString ("SDK version: % 1 "). arg (androidSdkVersion (); QAndroidJniObject activity = androidActivity (); // get network state QAndroidJniObject connectivity = QAndroidJniObject: bytes ("android/content/Context", "CONNECTIVITY_SERVICE ", "Ljava/lang/String;"); if (connectivity. isValid () {qDebug () <"connectivity id-" <connectivity. toString (); CHECK_EXCEPTION () QAndroidJniObject connectivityService = activity. callObjectMethod ("getSystemService", "(Ljava/lang/String;) Ljava/lang/Object;", connectivity. object <jstring> (); CHECK_EXCEPTION () qDebug () <"got connectivity service-" <connectivityService. isValid (); if (connectivityService. isValid () {QAndroidJniObject networkInfo = connectivityService. callObjectMethod ("getActiveNetworkInfo", "() Landroid/net/NetworkInfo;"); CHECK_EXCEPTION () qDebug () <"got NetworkInfo-" <networkInfo. isValid (); if (networkInfo. isValid () {m_list-> addItem (QString ("network status: connected (% 1 )"). arg (networkInfo. toString ();} else {m_list-> addItem ("Network Status: Not connected"); }}// get variable directories of Android System QAndroidJniObject externalStorageDir = QAndroidJniObject :: callStaticObjectMethod ("android/OS/Environment", "getExternalStorageDirectory", "() Ljava/io/File;"); CHECK_EXCEPTION () m_list-> addItem (QString ("external storage directory: % 1 "). arg (externalStorageDir. toString (); QAndroidJniObject dataDir = QAndroidJniObject: callStaticObjectMethod ("android/OS/Environment", "getDataDirectory", "() Ljava/io/File ;"); CHECK_EXCEPTION () m_list-> addItem (QString ("Data Directory: % 1 "). arg (dataDir. toString (); QAndroidJniObject dcim = QAndroidJniObject: getStaticObjectField ("android/OS/Environment", "DIRECTORY_DCIM", "Ljava/lang/String;"); CHECK_EXCEPTION () QAndroidJniObject dcimDir = QAndroidJniObject: callStaticObjectMethod ("android/OS/Environment", "plugin", "(Ljava/lang/String;) Ljava/io/File;", dcim. object <jstring> (); CHECK_EXCEPTION () m_list-> addItem (QString ("photo directory: % 1 "). arg (dcimDir. toString (); QAndroidJniObject music = QAndroidJniObject: getStaticObjectField ("android/OS/Environment", "DIRECTORY_MUSIC", "Ljava/lang/String;"); CHECK_EXCEPTION () QAndroidJniObject musicDir = QAndroidJniObject: callStaticObjectMethod ("android/OS/Environment", "plugin", "(Ljava/lang/String;) Ljava/io/File;", music. object <jstring> (); CHECK_EXCEPTION () m_list-> addItem (QString ("Music Directory: % 1 "). arg (musicDir. toString (); QAndroidJniObject movie = QAndroidJniObject: getStaticObjectField ("android/OS/Environment", "DIRECTORY_MOVIES", "Ljava/lang/String;"); CHECK_EXCEPTION () QAndroidJniObject movieDir = QAndroidJniObject: callStaticObjectMethod ("android/OS/Environment", "plugin", "(Ljava/lang/String;) Ljava/io/File;", movie. object <jstring> (); CHECK_EXCEPTION () m_list-> addItem (QString ("video Directory: % 1 "). arg (movieDir. toString (); QAndroidJniObject ringtones = QAndroidJniObject: bytes ("android/OS/Environment", "DIRECTORY_RINGTONES", "Ljava/lang/String;"); CHECK_EXCEPTION () QAndroidJniObject ringtonesDir = QAndroidJniObject: callStaticObjectMethod ("android/OS/Environment", "plugin", "(Ljava/lang/String;) Ljava/io/File;", ringtones. object <jstring> (); CHECK_EXCEPTION () m_list-> addItem (QString ("ringtone Directory: % 1 "). arg (ringtonesDir. toString (); // app's infomation QAndroidJniObject filesDir = activity. callObjectMethod ("getFilesDir", "() Ljava/io/File;"); CHECK_EXCEPTION () m_list-> addItem (QString ("application File directory: % 1 "). arg (filesDir. toString (); QAndroidJniObject packageName = activity. callObjectMethod <jstring> ("getPackageName"); CHECK_EXCEPTION () m_list-> addItem (QString ("application package name: % 1 "). arg (packageName. toString (); QAndroidJniObject appCacheDir = activity. callObjectMethod ("getCacheDir", "() Ljava/io/File;"); CHECK_EXCEPTION () m_list-> addItem (QString ("application cache directory: % 1 "). arg (appCacheDir. toString (); QAndroidJniObject appInfo = activity. callObjectMethod ("getApplicationInfo", "() Landroid/content/pm/ApplicationInfo;"); CHECK_EXCEPTION () QAndroidJniObject appClassName = appInfo. getObjectField <jstring> ("className"); CHECK_EXCEPTION () m_list-> addItem (QString ("application Class Name: % 1 "). arg (appClassName. toString (); QAndroidJniObject appLocation = appInfo. getObjectField ("sourceDir", "Ljava/lang/String;"); CHECK_EXCEPTION () m_list-> addItem (QString ("APK location: % 1 "). arg (appLocation. toString ()));}

The most frightening thing is the onRefresh () slot, which contains nearly one hundred and fifty lines of code. This is not a good programming practice. Do not do this in actual development.

In fact, the key to calling Android functions through JNI in Qt is two points:

The APIS provided by Qt are described in "QtAndroid details (1): QAndroidJniObject", "QtAndroid details (2): startActivity and its partners", and "QtAndroid details (3 ): startActivity practices Android photo taking feature "has been explained in detail in the three articles, and I will not go into details.

In this regard, we may not be familiar with C ++ developers. But it doesn't matter. You can use the Android online SDK for learning. In addition, the Qt JNI code I provide here is all available for actual test. It demonstrates some functional code. If necessary, it can be used directly in the project.

Okay. Let's get started with it.

Obtain the Android version

This is very considerate. The QtAndroid namespace directly provides a method: androidSdkVersion (). It returns an integer indicating the Android SDK version number.

Network Status

In Android, there is a ConnectivityManager class that can query the network status of the system.

The getActiveNetworkInfo () method of the ConnectivityManager class can obtain the currently active network connection information, and it returns an instance of the NetworkInfo class. If the network is not connected, this method returns null.

ConnectivityManager exists as a service in the Android system and needs to be obtained through the getSystemService () method of Context. GetSystemService () accepts a string representing the service name as a parameter. For the network connection management service, the name is CONNECTIVITY_SERVICE, which is a static member variable of the Context class.

The Java code for getting the network connection management service is as follows:

Context.getSystemService(Context.CONNECTIVITY_SERVICE);

These are the background knowledge of Android Java. Now let's look at the Qt JNI code. One row has passed.

    QAndroidJniObject connectivity = QAndroidJniObject::getStaticObjectField(                "android/content/Context",                "CONNECTIVITY_SERVICE",                "Ljava/lang/String;");

This line of code uses CONNECTIVITY_SERVICE, a static member of the Context class, to be stored in a connectivity object. We need it when getting ConnectivityManager.

        QAndroidJniObject connectivityService = activity.callObjectMethod(                    "getSystemService",                    "(Ljava/lang/String;)Ljava/lang/Object;",                    connectivity.object<jstring>());

This line of code calls the getSystemService method of Context to obtain the ConnectivityManager instance. We need a Context instance, and the QtAndroid: androidActivity () method can return one to us.

When you get the ConnectivityManager instance, you should call its getActiveNetworkInfo () method to obtain the current active connection. The following code is used:

    QAndroidJniObject networkInfo = connectivityService.callObjectMethod(                "getActiveNetworkInfo",                "()Landroid/net/NetworkInfo;");

QAndroidJniObject has a method called isValid (). When it returns true, the JNI object in the table is normally available. false indicates that no JNI object is available, this is generally the null value in Java. Therefore, if networkInfo. isValid () is true, the network connection is normal.

The others are helper code. Check the source code at the beginning.

Various directories of the Android System

The various system-level directories in the example are obtained through the android. OS. Enviroment class.

Let's talk about images, videos, and ringtones. They are obtained using the getExternalStoragePublicDirectory (String) method. Android provides a string name for each public storage directory, which is defined as a static member variable of the Enviroment class. Therefore, the steps for obtaining these directories using Qt JNI are as follows:

According to this logic, the code for obtaining the image directory is as follows:

    QAndroidJniObject dcim = QAndroidJniObject::getStaticObjectField(                "android/os/Environment",                "DIRECTORY_DCIM",                "Ljava/lang/String;"                );    QAndroidJniObject dcimDir = QAndroidJniObject::callStaticObjectMethod(                "android/os/Environment",                "getExternalStoragePublicDirectory",                "(Ljava/lang/String;)Ljava/io/File;",                dcim.object<jstring>()                );

We use the QAndroidJniObject: getStaticObjectField () method to obtain the static member variable of the Java class Enviroment, and then use callStaticObjectMethod to call the getExternalStoragePublicDirectory method.

Current Application Information

Some information about the current application can be obtained through the Activity class in Android.

We need an Activity object. In the Qt on Android Application, the corresponding class is QtActivity. In the previous section "QtAndroid details (3 ): we have already introduced startActivity's actual Android photo taking feature. Not much.

The code for getting the files directory of the current application is as follows:

    QAndroidJniObject filesDir = activity.callObjectMethod(                "getFilesDir",                "()Ljava/io/File;");

The returned result is/data/an. qt. SystemInfo/files. In fact, the same result can be obtained using the QDir: currentPath () method of Qt.


--------

Okay, this time. Next time, we will show some more interesting practical functions, such as shaking the mobile phone, keeping the screen bright, and dynamically switching the portrait screen. In the future, we may also introduce how to adjust the volume, adjust the screen brightness, use the push, the notification bar, and select contacts. However, let's look at my time.

Review:

  • Details on QtAndroid (3): startActivity for Android photography
  • QtAndroid (2): startActivity and its friends
  • QtAndroid (1): QAndroidJniObject
  • Qt on Android Column

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.