QAndroidJniObject Class
Provides APIs to call Java code from C++. More...
| Header: | #include <QAndroidJniObject> |
| qmake: | QT += androidextras |
| Since: | Qt 5.2 |
This class was introduced in Qt 5.2.
Public Functions
Detailed Description
General Notes
- Class names needs to contain the fully-qualified class name, for example: "java/lang/String".
- Method signatures are written as "(Arguments)ReturnType"
- All object types are returned as a QAndroidJniObject.
Method Signatures
For functions that take no arguments, QAndroidJniObject provides convenience functions that will use the correct signature based on the provided template type. For example:
jint x = QAndroidJniObject::callMethod<jint>("getSize"); QAndroidJniObject::callMethod<void>("touch");
In other cases you will need to supply the signature yourself, and it is important that the signature matches the function you want to call. The signature structure is (A)R, where A is the type of the argument(s) and R is the return type. Array types in the signature must have the [ suffix and the fully-qualified type names must have the L prefix and ; suffix.
The example below demonstrates how to call two different static functions.
// Java class package org.qtproject.qt5; class TestClass { static String fromNumber(int x) { ... } static String[] stringArray(String s1, String s2) { ... } }
The signature for the first function is "(I)Ljava/lang/String;"
// C++ code QAndroidJniObject stringNumber = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/TestClass", "fromNumber" "(I)Ljava/lang/String;", 10);
and the signature for the second function is "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"
// C++ code QAndroidJniObject string1 = QAndroidJniObject::fromString("String1"); QAndroidJniObject string2 = QAndroidJniObject::fromString("String2"); QAndroidJniObject stringArray = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/TestClass", "stringArray" "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;" string1.object<jstring>(), string2.object<jstring>());
Handling Java Exception
When calling Java functions that might throw an exception, it is important that you check, handle and clear out the exception before continuing.
Note: It is unsafe to make a JNI call when there are exceptions pending.
void functionException() { QAndroidJniObject myString = QAndroidJniObject::fromString("Hello"); jchar c = myString.callMethod<jchar>("charAt", "(I)C", 1000); QAndroidJniEnvironment env; if (env->ExceptionCheck()) { // Handle exception here. env->ExceptionClear(); } }
Java Native Methods
Java native methods makes it possible to call native code from Java, this is done by creating a function declaration in Java and prefixing it with the native keyword. Before a native function can be called from Java, you need to map the Java native function to a native function in your code. Mapping functions can be done by calling the RegisterNatives() function through the JNI environment pointer.
The example below demonstrates how this could be done.
Java implementation:
class FooJavaClass { public static void foo(int x) { if (x < 100) callNativeOne(x); else callNativeTwo(x); } private static native void callNativeOne(int x); private static native void callNativeTwo(int x); }
C++ Implementation:
static void fromJavaOne(JNIEnv *env, jobject thiz, jint x) { Q_UNUSED(env) Q_UNUSED(thiz) qDebug() << x << "< 100"; } static void fromJavaTwo(JNIEnv *env, jobject thiz, jint x) { Q_UNUSED(env) Q_UNUSED(thiz) qDebug() << x << ">= 100"; } void registerNativeMethods() { JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)}, {"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}}; QAndroidJniObject javaClass("my/java/project/FooJavaClass"); QAndroidJniEnvironment env; jclass objectClass = env->GetObjectClass(javaClass.object<jobject>()); env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0])); env->DeleteLocalRef(objectClass); } void foo() { QAndroidJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 10); // Output: 10 < 100 QAndroidJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 100); // Output: 100 >= 100 }
The Lifetime of a Java Object
Most objects received from Java will be local references and will only stay valid in the scope you received them. After that, the object becomes eligible for garbage collection. If you want to keep a Java object alive you need to either create a new global reference to the object and release it when you are done, or construct a new QAndroidJniObject and let it manage the lifetime of the Java object.
Note: The QAndroidJniObject does only manage its own references, if you construct a QAndroidJniObject from a global or local reference that reference will not be released by the QAndroidJniObject.
JNI Types
Object Types
| Type | Signature |
|---|---|
| jobject | Ljava/lang/Object; |
| jclass | Ljava/lang/Class; |
| jstring | Ljava/lang/String; |
| jthrowable | Ljava/lang/Throwable; |
| jobjectArray | [Ljava/lang/Object; |
| jarray | [<type> |
| jbooleanArray | [Z |
| jbyteArray | [B |
| jcharArray | [C |
| jshortArray | [S |
| jintArray | [I |
| jlongArray | [J |
| jfloatArray | [F |
| jdoubleArray | [D |
Primitive Types
| Type | Signature |
|---|---|
| jboolean | Z |
| jbyte | B |
| jchar | C |
| jshort | S |
| jint | I |
| jlong | J |
| jfloat | F |
| jdouble | D |
Other
| Type | Signature |
|---|---|
| void | V |
| Custom type | L<fully-qualified-name>; |
For more information about JNI see: http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
See also QAndroidJniEnvironment and object().
Member Function Documentation
QAndroidJniObject::~QAndroidJniObject()
Destroys the QAndroidJniObject and releases any references held by the QAndroidJniObject.