Fix registerNativeMethods for good

The initial implementation and the commit
c00ab6f8eaa3cdc9a29dd103c91b2eaf212cac9f was wrong:
* env->findClass() in fact returns a global reference, and in any
case we shouldn't be calling that, instead QJniObject would be
enough.
* The size param provided to env->RegisterNatives was wrong.
* A test for registerNativeMethods() is added to ensure such break
is not repeated again.

Task-number: QTBUG-89633
Change-Id: I4d3a6a9270755f465c40add25521fb750dd4de0a
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
(cherry picked from commit deca7cd730a44988d3e15c551d9a82a5c75618e2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Assam Boudjelthia 2021-02-08 14:16:55 +02:00 committed by Qt Cherry-pick Bot
parent 4a3fe46313
commit 0c413c379a
4 changed files with 83 additions and 3 deletions

View File

@ -222,12 +222,13 @@ JavaVM *QJniEnvironment::javaVM()
*/
bool QJniEnvironment::registerNativeMethods(const char *className, JNINativeMethod methods[], int size)
{
jclass clazz = findClass(className);
QJniObject classObject(className);
if (!clazz)
if (!classObject.isValid())
return false;
if (d->jniEnv->RegisterNatives(clazz, methods, size / sizeof(methods[0])) < 0) {
jclass clazz = d->jniEnv->GetObjectClass(classObject.object());
if (d->jniEnv->RegisterNatives(clazz, methods, size) < 0) {
exceptionCheckAndClear();
d->jniEnv->DeleteLocalRef(clazz);
return false;

View File

@ -6,3 +6,11 @@ qt_internal_add_test(tst_qjnienvironment
SOURCES
tst_qjnienvironment.cpp
)
if(ANDROID)
set_property(TARGET tst_qjnienvironment APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/testdata
)
# QTBUG-88840
qt_android_generate_deployment_settings(tst_qjnienvironment)
endif()

View File

@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
package org.qtproject.qt.android.testdatapackage;
public class QtJniEnvironmentTestClass
{
private static native void callbackFromJava(String message);
public static void appendJavaToString(String message)
{
callbackFromJava("From Java: " + message);
}
}

View File

@ -27,8 +27,14 @@
****************************************************************************/
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
#include <QtTest/QtTest>
static const char javaTestClass[] =
"org/qtproject/qt/android/testdatapackage/QtJniEnvironmentTestClass";
static QString registerNativesString = QStringLiteral("Qt");
class tst_QJniEnvironment : public QObject
{
Q_OBJECT
@ -36,6 +42,7 @@ class tst_QJniEnvironment : public QObject
private slots:
void jniEnv();
void javaVM();
void registerNativeMethods();
};
void tst_QJniEnvironment::jniEnv()
@ -101,6 +108,29 @@ void tst_QJniEnvironment::javaVM()
QCOMPARE(env.javaVM(), vm);
}
static void callbackFromJava(JNIEnv *env, jobject /*thiz*/, jstring value)
{
registerNativesString = QJniObject(value).toString();
}
void tst_QJniEnvironment::registerNativeMethods()
{
JNINativeMethod methods[] {
{"callbackFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callbackFromJava)}
};
QJniEnvironment env;
QVERIFY(env.registerNativeMethods(javaTestClass, methods, 1));
QJniObject QtString = QJniObject::fromString(registerNativesString);
QJniObject::callStaticMethod<void>(javaTestClass,
"appendJavaToString",
"(Ljava/lang/String;)V",
QtString.object<jstring>());
QTest::qWait(200);
QVERIFY(registerNativesString == QStringLiteral("From Java: Qt"));
}
QTEST_MAIN(tst_QJniEnvironment)
#include "tst_qjnienvironment.moc"