QJniEnvironment: extend API
This patch adds some convenience methods to QJniEnvironment API: * an overload of registerNativeMethods() that accepts jclass instead of const char *className. * a findMethod() function is added to query a methodID of a static or nonstatic method by its name and signature. Task-number: QTBUG-92952 Change-Id: Ib1bc892decea97e625c4822888b6183af6edd6dc Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This commit is contained in:
parent
96d9cf8de4
commit
34f72ca52e
@ -197,6 +197,54 @@ jclass QJniEnvironment::findClass(const char *className)
|
||||
return QtAndroidPrivate::findClass(className, d->jniEnv);
|
||||
}
|
||||
|
||||
/*!
|
||||
Searches for an instance method of a class \a clazz. The method is specified
|
||||
by its \a methodName and \a signature.
|
||||
|
||||
Returns the method ID or \c nullptr if the method is not found.
|
||||
|
||||
A usecase for this method is searching for class methods and caching their
|
||||
IDs, so that they could later be used for calling the methods.
|
||||
*/
|
||||
jmethodID QJniEnvironment::findMethod(jclass clazz, const char *methodName, const char *signature)
|
||||
{
|
||||
jmethodID id = d->jniEnv->GetMethodID(clazz, methodName, signature);
|
||||
if (checkAndClearExceptions(d->jniEnv))
|
||||
return nullptr;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/*!
|
||||
Searches for a static method of a class \a clazz. The method is specified
|
||||
by its \a methodName and \a signature.
|
||||
|
||||
Returns the method ID or \c nullptr if the method is not found.
|
||||
|
||||
A usecase for this method is searching for class methods and caching their
|
||||
IDs, so that they could later be used for calling the methods.
|
||||
|
||||
\code
|
||||
QJniEnvironment env;
|
||||
jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
|
||||
jmethodID methodId = env.findStaticMethod(javaClass,
|
||||
"staticJavaMethod",
|
||||
"(Ljava/lang/String;)V");
|
||||
QJniObject javaMessage = QJniObject::fromString("findStaticMethod example");
|
||||
QJniObject::callStaticMethod<void>(javaClass,
|
||||
methodId,
|
||||
javaMessage.object<jstring>());
|
||||
\endcode
|
||||
*/
|
||||
jmethodID QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName, const char *signature)
|
||||
{
|
||||
jmethodID id = d->jniEnv->GetStaticMethodID(clazz, methodName, signature);
|
||||
if (checkAndClearExceptions(d->jniEnv))
|
||||
return nullptr;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn JavaVM *QJniEnvironment::javaVM()
|
||||
|
||||
@ -216,7 +264,7 @@ JavaVM *QJniEnvironment::javaVM()
|
||||
which can call native C++ functions from class \a className. These methods
|
||||
must be registered before any attempt to call them.
|
||||
|
||||
Returns True if the registration is successful, otherwise False.
|
||||
Returns \c true if the registration is successful, otherwise \c false.
|
||||
|
||||
Each element in the methods array consists of:
|
||||
\list
|
||||
@ -240,14 +288,31 @@ bool QJniEnvironment::registerNativeMethods(const char *className, JNINativeMeth
|
||||
return false;
|
||||
|
||||
jclass clazz = d->jniEnv->GetObjectClass(classObject.object());
|
||||
if (d->jniEnv->RegisterNatives(clazz, methods, size) < 0) {
|
||||
checkAndClearExceptions();
|
||||
d->jniEnv->DeleteLocalRef(clazz);
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool result = registerNativeMethods(clazz, methods, size);
|
||||
d->jniEnv->DeleteLocalRef(clazz);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
This overload uses a previously cached jclass instance \a clazz.
|
||||
|
||||
\code
|
||||
JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
|
||||
{"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
|
||||
QJniEnvironment env;
|
||||
jclass clazz = env.findClass("org/qtproject/android/TestJavaClass");
|
||||
env.registerNativeMethods(clazz, methods, 2);
|
||||
\endcode
|
||||
*/
|
||||
bool QJniEnvironment::registerNativeMethods(jclass clazz, JNINativeMethod methods[], int size)
|
||||
{
|
||||
if (d->jniEnv->RegisterNatives(clazz, methods, size) < 0) {
|
||||
checkAndClearExceptions();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,11 @@ public:
|
||||
JNIEnv &operator*() const;
|
||||
JNIEnv *jniEnv() const;
|
||||
jclass findClass(const char *className);
|
||||
jmethodID findMethod(jclass clazz, const char *methodName, const char *signature);
|
||||
jmethodID findStaticMethod(jclass clazz, const char *methodName, const char *signature);
|
||||
static JavaVM *javaVM();
|
||||
bool registerNativeMethods(const char *className, JNINativeMethod methods[], int size);
|
||||
bool registerNativeMethods(jclass clazz, JNINativeMethod methods[], int size);
|
||||
|
||||
enum class OutputMode {
|
||||
Silent,
|
||||
|
@ -31,11 +31,16 @@ package org.qtproject.qt.android.testdatapackage;
|
||||
public class QtJniEnvironmentTestClass
|
||||
{
|
||||
private static native void callbackFromJava(String message);
|
||||
private static native void intCallbackFromJava(int value);
|
||||
|
||||
public static void appendJavaToString(String message)
|
||||
{
|
||||
callbackFromJava("From Java: " + message);
|
||||
}
|
||||
|
||||
public static void convertToInt(String message)
|
||||
{
|
||||
intCallbackFromJava(Integer.parseInt(message));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ static const char javaTestClass[] =
|
||||
"org/qtproject/qt/android/testdatapackage/QtJniEnvironmentTestClass";
|
||||
|
||||
static QString registerNativesString = QStringLiteral("Qt");
|
||||
static int registerNativeInteger = 0;
|
||||
|
||||
class tst_QJniEnvironment : public QObject
|
||||
{
|
||||
@ -45,6 +46,9 @@ private slots:
|
||||
void jniEnv();
|
||||
void javaVM();
|
||||
void registerNativeMethods();
|
||||
void registerNativeMethodsByJclass();
|
||||
void findMethod();
|
||||
void findStaticMethod();
|
||||
};
|
||||
|
||||
void tst_QJniEnvironment::jniEnv()
|
||||
@ -134,6 +138,71 @@ void tst_QJniEnvironment::registerNativeMethods()
|
||||
QVERIFY(registerNativesString == QStringLiteral("From Java: Qt"));
|
||||
}
|
||||
|
||||
static void intCallbackFromJava(JNIEnv *env, jobject /*thiz*/, jint value)
|
||||
{
|
||||
Q_UNUSED(env)
|
||||
registerNativeInteger = static_cast<int>(value);
|
||||
}
|
||||
|
||||
void tst_QJniEnvironment::registerNativeMethodsByJclass()
|
||||
{
|
||||
JNINativeMethod methods[] {
|
||||
{ "intCallbackFromJava", "(I)V", reinterpret_cast<void *>(intCallbackFromJava) }
|
||||
};
|
||||
|
||||
QJniEnvironment env;
|
||||
jclass clazz = env.findClass(javaTestClass);
|
||||
QVERIFY(clazz != 0);
|
||||
QVERIFY(env.registerNativeMethods(clazz, methods, 1));
|
||||
|
||||
QCOMPARE(registerNativeInteger, 0);
|
||||
|
||||
QJniObject parameter = QJniObject::fromString(QString("123"));
|
||||
QJniObject::callStaticMethod<void>(clazz, "convertToInt", "(Ljava/lang/String;)V",
|
||||
parameter.object<jstring>());
|
||||
QTest::qWait(200);
|
||||
QCOMPARE(registerNativeInteger, 123);
|
||||
}
|
||||
|
||||
void tst_QJniEnvironment::findMethod()
|
||||
{
|
||||
QJniEnvironment env;
|
||||
jclass clazz = env.findClass("java/lang/Integer");
|
||||
QVERIFY(clazz != nullptr);
|
||||
|
||||
// existing method
|
||||
jmethodID methodId = env.findMethod(clazz, "toString", "()Ljava/lang/String;");
|
||||
QVERIFY(methodId != nullptr);
|
||||
|
||||
// invalid signature
|
||||
jmethodID invalid = env.findMethod(clazz, "unknown", "()I");
|
||||
QVERIFY(invalid == nullptr);
|
||||
// check that all exceptions are already cleared
|
||||
QVERIFY(!env.checkAndClearExceptions());
|
||||
}
|
||||
|
||||
void tst_QJniEnvironment::findStaticMethod()
|
||||
{
|
||||
QJniEnvironment env;
|
||||
jclass clazz = env.findClass("java/lang/Integer");
|
||||
QVERIFY(clazz != nullptr);
|
||||
|
||||
// existing method
|
||||
jmethodID staticMethodId = env.findStaticMethod(clazz, "parseInt", "(Ljava/lang/String;)I");
|
||||
QVERIFY(staticMethodId != nullptr);
|
||||
|
||||
QJniObject parameter = QJniObject::fromString("123");
|
||||
jint result = QJniObject::callStaticMethod<jint>(clazz, staticMethodId,
|
||||
parameter.object<jstring>());
|
||||
QCOMPARE(result, 123);
|
||||
|
||||
// invalid method
|
||||
jmethodID invalid = env.findStaticMethod(clazz, "unknown", "()I");
|
||||
QVERIFY(invalid == nullptr);
|
||||
// check that all exceptions are already cleared
|
||||
QVERIFY(!env.checkAndClearExceptions());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QJniEnvironment)
|
||||
|
||||
#include "tst_qjnienvironment.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user