Professional Documents
Culture Documents
The latest revisions Qt framework allow to port application developed in C++ code to run
in Android OS also. For standard app the Qt framework provide all the required features
but in some case is necessary to interact with the system using native java code. For
make such task Qt provide some specific objects able to allow a more easy work.
m_MainActivity = MainActivity;
}
Please note, although not necessary in this example we'll pass as class constructor
param the pointer to the main activity object created by the Qt app. This because this
object will be necessary in case you need to make calls to some native views. Indeed if
you want to interact with native views it's usually require to call view function from UI
thread. This class and all call made from Qt are not part of UI thread than many of then
will dont' work. The common workaround is to use the following "wrapper" code:
m_MainActivity.runOnUiThread(new Runnable()
@Override
});
As you can note we use the main activity object just saved to run a code in a UI thread
for allow operation with native views. For allow Qt Creator to compile and include this
java class inside final apk you have to insert into your .pro project file as follow:
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
DISTFILES += android/AndroidManifest.xml
OTHER_FILES +=
android/src/com/mycompanyname/myappname/MyJavaClass.java
An important point you must to know is if you want Qt Creator to correctly compile your
java file you have to put the file in the subfolder
path /src/com/mycompanyname/myappname/ starting from the point where you place
the AndroidManifest.xml file (the android folder in our example). Once created your java
class file you can load it from C++ Qt side as follow:
QAndroidJniObject MyJavaClass;
MyJavaClass =
QAndroidJniObject("com/mycompanyname/myappname/MyJavaClass",
"(Landroid/app/Activity;)V",
QtAndroid::androidActivity().object<jobject>()
);
Now we have a Qt object to use for communicate with our java class just loaded. Note
the param to pass the main activity pointer to the class as explained above.
{
private final Activity m_MainActivity;
m_MainActivity = MainActivity;
// Do something here
As you can see a new function called TestCallMe has been added with two example
params, one integer and one string. Using Qt class is possible to call this method from
C++ side as follow:
int Param1;
QString Param2;
MyJavaClass.callMethod<void>("TestCallMe",
"(ILjava/lang/String;)V",
Param1,
QAndroidJniObject::fromString(Param2).object<jstring>()
);
Basically here we have to specify, in add of method name, the params accepted using
the JNI format specification. You can read more about the syntax here. Native variable
like integer doesn't need specific conversion but some more complex element, like
QString as in example, require a conversion to the JNI native format jstring. Anyway
reading the JNI types map it will be possible to exchange the majority of common format
available.
class MainQtApp
This can be used for invoke function connection from java code in the form:
MainQtApp.nativeQtTestFuction(1234);
This is all from java side since all the job is made from C++ side. Basically we have to
include in our C++ code a special function called from JNI engine at startup where is
registered inside the same JNI engine a "connection" between the java functions and
the C++ function. The following code will explain better:
};
jclass javaClass;
JNIEnv* env;
if(vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) !=
JNI_OK)
return JNI_ERR;
javaClass = env-
>FindClass("com/mycompanyname/myappname/MainQtApp");
if(!javaClass)
return JNI_ERR;
if(env->RegisterNatives(javaClass, methodsArray,
sizeof(methodsArray) / sizeof(methodsArray[0])) < 0)
return JNI_ERR;
return JNI_VERSION_1_6;
As you can see the function JNI_OnLoad() is called automatically at app startup. Inside,
after some validity check, the code look for the "container" class MainQtApp with inside
the java native methods. Once found register the connection between java and C++ code
using the special array JNINativeMethod containing the string name of java method with
the corresponding params in JNI format, as explained above, and the C++ function code
to call. Please note the function is in C format since is more easy to pass a static function
pointer through the array and also because JNI manage only C format (this is a very
important point to remember). From inside the C function you can call directly your Qt
object class using different methods. It's all, not very difficult but a bit annoying to
develop.