diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp index 07acd11db6..19e4cc4e40 100644 --- a/src/corelib/kernel/qjniobject.cpp +++ b/src/corelib/kernel/qjniobject.cpp @@ -970,7 +970,7 @@ QByteArray QJniObject::className() const \since 6.4 Calls the static method \a methodName on \a clazz and returns the value of type \c Ret - (unless c Ret is \c void). If \c Ret if a jobject type, then the returned value will + (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value will be a QJniObject. \code @@ -982,6 +982,18 @@ QByteArray QJniObject::className() const The method signature is deduced at compile time from \c Ret and the types of \a args. */ +/*! + \fn template auto QJniObject::callStaticMethod(const char *methodName, Args &&...args) + \since 6.7 + + Calls the static method \a methodName on the class \c Klass and returns the value of type + \c Ret (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value will + be a QJniObject. + + The method signature is deduced at compile time from \c Ret and the types of \a args. + \c Klass needs to be a C++ type with a registered type mapping to a Java type. +*/ + /*! \fn QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h index ff5d81e1a3..e5212d36ff 100644 --- a/src/corelib/kernel/qjniobject.h +++ b/src/corelib/kernel/qjniobject.h @@ -127,7 +127,8 @@ public: static auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args) { QJniEnvironment env; - jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true); + jmethodID id = clazz ? getMethodID(env.jniEnv(), clazz, methodName, signature, true) + : 0; return callStaticMethod(clazz, id, std::forward(args)...); } @@ -181,6 +182,21 @@ public: constexpr auto signature = QtJniTypes::methodSignature(); return callStaticMethod(clazz, methodName, signature.data(), std::forward(args)...); } + template = true +#endif + > + static auto callStaticMethod(const char *methodName, Args &&...args) + { + QJniEnvironment env; + const jclass clazz = QJniObject::loadClass(QtJniTypes::className().data(), + env.jniEnv()); + const jmethodID id = clazz ? getMethodID(env.jniEnv(), clazz, methodName, + QtJniTypes::methodSignature().data(), true) + : 0; + return callStaticMethod(clazz, id, std::forward(args)...); + } static QJniObject callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...); @@ -547,6 +563,8 @@ private: static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz, jmethodID id, ...) { + if (!clazz || !id) + return; va_list args = {}; va_start(args, id); if constexpr (std::is_same_v) @@ -572,6 +590,8 @@ private: static void callStaticMethodForVoid(JNIEnv *env, jclass clazz, jmethodID id, ...) { + if (!clazz || !id) + return; va_list args; va_start(args, id); env->CallStaticVoidMethodV(clazz, id, args); diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 7ea6b1e121..b524997961 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -8,6 +8,8 @@ #include #include +using namespace Qt::StringLiterals; + static const char testClassName[] = "org/qtproject/qt/android/testdatapackage/QtJniObjectTestClass"; Q_DECLARE_JNI_CLASS(QtJniObjectTestClass, testClassName) @@ -310,7 +312,8 @@ void tst_QJniObject::callStaticObjectMethod() jclass cls = env->FindClass("java/lang/String"); QVERIFY(cls != 0); - QJniObject formatString = QJniObject::fromString(QLatin1String("test format")); + const QString string = u"test format"_s; + QJniObject formatString = QJniObject::fromString(string); QVERIFY(formatString.isValid()); QJniObject returnValue = QJniObject::callStaticObjectMethod(cls, @@ -319,20 +322,14 @@ void tst_QJniObject::callStaticObjectMethod() formatString.object(), jobjectArray(0)); QVERIFY(returnValue.isValid()); - - QString returnedString = returnValue.toString(); - - QCOMPARE(returnedString, QString::fromLatin1("test format")); + QCOMPARE(returnValue.toString(), string); returnValue = QJniObject::callStaticObjectMethod(cls, "format", formatString.object(), jobjectArray(0)); QVERIFY(returnValue.isValid()); - - returnedString = returnValue.toString(); - - QCOMPARE(returnedString, QString::fromLatin1("test format")); + QCOMPARE(returnValue.toString(), string); // from 6.4 on we can use callStaticMethod returnValue = QJniObject::callStaticMethod(cls, @@ -340,10 +337,15 @@ void tst_QJniObject::callStaticObjectMethod() formatString.object(), jobjectArray(0)); QVERIFY(returnValue.isValid()); + QCOMPARE(returnValue.toString(), string); - returnedString = returnValue.toString(); + // from 6.7 we can use callStaticMethod without specifying the class string + returnValue = QJniObject::callStaticMethod("format", + formatString.object(), + jobjectArray(0)); + QVERIFY(returnValue.isValid()); + QCOMPARE(returnValue.toString(), string); - QCOMPARE(returnedString, QString::fromLatin1("test format")); } void tst_QJniObject::callStaticObjectMethodById()