StupidBeauty
Read times:2342Posted at: - no title specified

Qt 5.4文档翻译:QAndroidJniObject类,QAndroidJniObject Class

提供了一些接口,用于从C++中调用Java 代码。详细说明……

头文件:

#include <QAndroidJniObject>

qmake:

QT += androidextras

自此版本开始引入:

Qt 5.2

详细说明

提供了一些接口,用于从C++中调用Java 代码。

通用注意事项

方法名签名

对于那些不要参数的函数,QAndroidJniObject提供了一些便利函数,用来根据妳所提供的模板类型生成正确的方法名签名。例如:

jint x = QAndroidJniObject ::callMethod<jint>("getSize");

QAndroidJniObject ::callMethod<void>("touch");

在其它情况下,妳需要自己提供方法名签名,并且要注意,妳所提供的签名必须与妳要调用的函数相匹配。签名结构是(A)R,其中,A是指参数的类型,R是指返回类型。签名中的数组类型必须带有[前缀(☯:原文是suffix),并且,完整的类型名字中必须带有L前缀和;后缀。

下面代码展示了如何调用两个不同的静态函数。

// Java

package org.qtproject.qt5;

class TestClass

{

static String fromNumber(int x) { ... }

static String[] stringArray(String s1, String s2) { ... }

}

第一个函数的签名是"(I)Ljava/lang/String;"

// C++代码

QAndroidJniObject stringNumber = QAndroidJniObject :: callStaticObjectMethod ("org/qtproject/qt5/TestClass",

"fromNumber"

"(I)Ljava/lang/String;",

10);

而第二个函数的签名是"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"

// C++代码

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

处理Java异常

当妳调用那种可能会抛出异常的Java函数时,要注意,检查、处理并且清除异常。

注意:在仍然存在未处理的异常的情况下调用JNI 代码是不安全的。

void functionException()

{

QAndroidJniObject myString = QAndroidJniObject ::fromString("Hello");

jchar c = myString.callMethod<jchar>("charAt", "(I)C", 1000);

QAndroidJniEnvironment env;

if (env->ExceptionCheck()) {

// 在此处处理异常。

env->ExceptionClear();

}

}

Java原生方法

Java原生方法可用于从 Java 中调用原生代码,具体做法就是,在Java 中创建一个函数声明,并且加上一个native前缀。在能够从 Java 中调用原生函数之前,妳需要将该Java 原生函数映射到妳自己代码中的某个原生函数。函数的映射,可通过JNI环境指针调用RegisterNatives()函数来实现。

以下代码展示了这一点。

Java实现代码:

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++实现代码:

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

}

一个Java Object的生命周期

从Java 接收到的大部分对象都是本地的引用,因此,只会在妳接收到它们的那个作用域中保持有效。从那之后,该对象就可能会被垃圾回收。如果妳想保持某个Java 对象存活的话,则,妳需要做以下两件事中的一件:创建指向该对象的一个新的全局引用,并在妳做完工作之后释放它;或者,构造一个新的QAndroidJniObject,并让这个东西来管理该Java 对象的生命周期。

注意:QAndroidJniObject只会管理它自己的引用,如果妳从一个全局或本地引用来构造一个QAndroidJniObject的话,则,该引用不会被这个QAndroidJniObject所释放。

JNI类型

对象类型

类型

签名

jobject

L<fully-qualified-name>;

jclass

jstring

jobjectArray

[L<fully-qualified-name>;

jarray

[<type>

jbooleanArray

[Z

jbyteArray

[B

jcharArray

[C

jshortArray

[S

jintArray

[I

jlongArray

[J

jfloatArray

[F

jdoubleArray

[D

基本类型

类型

签名

jboolean

Z

jbyte

B

jchar

C

jshort

S

jint

I

jlong

J

jfloat

F

jdouble

D

其它

类型

签名

void

V

欲了解更多关于JNI 的信息,则访问:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html

参考QAndroidJniEnvironmentobject()。

成员函数文档

QAndroidJniObject::QAndroidJniObject(const char * className)

通过调用className的默认构造函数来构造一个新的QAndroidJniObject

...

QAndroidJniObject myJavaString("java/lang/String");

...

[static] QAndroidJniObject QAndroidJniObject::callStaticObjectMethod(const char *className, const char * methodName, const char * signature, ...)

对于类className,以signature签名来调用它的静态方法methodName。

QAndroidJniObject thread = QAndroidJniObject :: callStaticObjectMethod ("java/lang/Thread", "currentThread", "()Ljava/lang/Thread;");

QAndroidJniObject string = QAndroidJniObject :: callStaticObjectMethod ("java/lang/String", "valueOf", "(I)Ljava/lang/String;", 10);

[static] QAndroidJniObject QAndroidJniObject::fromString(const QString & string)

QString string来创建一个Java 字符串,并且返回一个持有该字符串的QAndroidJniObject

...

QString myQString = "QString";

QAndroidJniObject myJavaString = QAndroidJniObject ::fromString(myQString);

...

参考toString()。

T QAndroidJniObject::getField(const char * fieldName) const

获取名为fieldName的字段的值。

QAndroidJniObject volumeControl = ...;

jint fieldValue = volumeControl.getField<jint>("MAX_VOLUME");

QAndroidJniObject QAndroidJniObject::getObjectField(const char * fieldName) const

获取名为fieldName的字段对应的对象。

QAndroidJniObject field = jniObject.getObjectField<jstring>("FIELD_NAME");

T QAndroidJniObject::object() const

将此QAndroidJniObject所持有的对象以类型T 的形式返回。

QAndroidJniObject string = QAndroidJniObject :: fromString ("Hello, JNI");

jstring jstring = string.object<jstring>();

注意:所返回的那个对象仍然是由该QAndroidJniObject所拥有。如果妳想让该对象保持有效,则,妳应当创建一个新的QAndroidJniObject,或者创建一个新的指向该对象的全局引用,并且在日后自行释放它。

void functionScope()

{

QString helloString("Hello");

jstring myJString = 0;

{

QAndroidJniObject string = QAndroidJniObject ::fromString(helloString);

myJString = string.object<jstring>();

}

// 呃! myJString 到此处已经无效了。

}

注意:自Qt 5.3开始,如果返回的类型是一个jobject的话,则,使用此函数时可不提供模板类型。

jobject object = jniObject.object();

QString QAndroidJniObject::toString() const

返回一个QString,它是该java 对象的字符串表示方式。对于一个Java String 对象,调用这个函数,是一种便利地获取其字符串数据的方法。

QAndroidJniObject string = ...; //  "Hello Java"

QString qstring = string.toString(); // "Hello Java"

参考fromString()。

汤灿

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands