Make QJniObject and QJniEnvironment public API

As part of Qt 6 restructring for the extras modules, this change exposes
the Jni APIs which are very important for Android platform. This patch
adds the APIs QJniObject, QJniEnvironment, QJniExceptionCleaner based
from private QtCore and QtAndroidExtras.

The Jni interface is cross-platform which justifies the name, but
currently, this API is used mainly for Android, and the naming comes
generic without Android keyword to avoid any future limitation on
supporting other platforms.

[ChangeLog][QtCore] Add new QJniObject, QJniEnvironment and
QJniExceptionCleaner APIs.

Task-number: QTBUG-89482
Fixes: QTBUG-89633
Change-Id: I4382dd53a225375759b9d042f6035a4a9810572b
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
This commit is contained in:
Assam Boudjelthia 2021-01-14 12:38:04 +02:00
parent 407ce5c0af
commit 4e60681c87
48 changed files with 4386 additions and 413 deletions

View File

@ -979,6 +979,8 @@ qt_internal_extend_target(Core CONDITION ANDROID AND NOT ANDROID_EMBEDDED
io/qstandardpaths_android.cpp io/qstandardpaths_android.cpp
io/qstorageinfo_unix.cpp io/qstorageinfo_unix.cpp
kernel/qjni.cpp kernel/qjni_p.h kernel/qjni.cpp kernel/qjni_p.h
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
kernel/qjniobject.cpp kernel/qjniobject.h
kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
kernel/qjnionload.cpp kernel/qjnionload.cpp
) )

View File

@ -0,0 +1,133 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
//! [Working with lists]
QStringList getTrackTitles(const QJniObject &album) {
QStringList stringList;
QJniObject list = album.callObjectMethod("getTitles",
"()Ljava/util/List;");
if (list.isValid()) {
const int size = list.callMethod<jint>("size");
for (int i = 0; i < size; ++i) {
QJniObject title = list.callObjectMethod("get", "(I)Ljava/lang/Object;", i);
stringList.append(title.toString());
}
}
return stringList;
}
//! [Working with lists]
//! [QJniObject scope]
void functionScope()
{
QString helloString("Hello");
jstring myJString = 0;
{
QJniObject string = QJniObject::fromString(helloString);
myJString = string.object<jstring>();
}
// Ops! myJString is no longer valid.
}
//! [QJniObject scope]
//! [Registering native methods]
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)}};
QJniObject javaClass("my/java/project/FooJavaClass");
QJniEnvironment env;
jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
env->RegisterNatives(objectClass,
methods,
sizeof(methods) / sizeof(methods[0]));
env->DeleteLocalRef(objectClass);
}
void foo()
{
QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 10); // Output: 10 < 100
QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 100); // Output: 100 >= 100
}
//! [Registering native methods]
//! [Java native methods]
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);
}
//! [Java native methods]

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2017 Intel Corporation. ** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -78,7 +78,7 @@
#endif #endif
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <private/qjni_p.h> #include <qjniobject.h>
#endif #endif
#if defined(Q_OS_SOLARIS) #if defined(Q_OS_SOLARIS)
@ -2296,7 +2296,7 @@ Oreo
// https://source.android.com/source/build-numbers.html // https://source.android.com/source/build-numbers.html
// https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
const int sdk_int = QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT"); const int sdk_int = QJniObject::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]]; return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]];
} }
#endif #endif

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.
@ -50,7 +50,7 @@
#include <qdebug.h> #include <qdebug.h>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <private/qjni_p.h> #include <QJniObject>
#endif #endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -157,7 +157,7 @@ QOperatingSystemVersion QOperatingSystemVersion::current()
version.m_os = currentType(); version.m_os = currentType();
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#ifndef QT_BOOTSTRAPPED #ifndef QT_BOOTSTRAPPED
const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField( const QVersionNumber v = QVersionNumber::fromString(QJniObject::getStaticObjectField(
"android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString()); "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString());
if (!v.isNull()) { if (!v.isNull()) {
version.m_major = v.majorVersion(); version.m_major = v.majorVersion();
@ -207,7 +207,7 @@ QOperatingSystemVersion QOperatingSystemVersion::current()
}; };
// This will give us at least the first 2 version components // This will give us at least the first 2 version components
const size_t versionIdx = size_t(QJNIObjectPrivate::getStaticField<jint>( const size_t versionIdx = size_t(QJniObject::getStaticField<jint>(
"android/os/Build$VERSION", "SDK_INT")) - 1; "android/os/Build$VERSION", "SDK_INT")) - 1;
if (versionIdx < sizeof(versions) / sizeof(versions[0])) { if (versionIdx < sizeof(versions) / sizeof(versions[0])) {
version.m_major = versions[versionIdx].major; version.m_major = versions[versionIdx].major;

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 Intel Corporation. ** Copyright (C) 2020 Intel Corporation.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.
@ -72,10 +73,6 @@ DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG Rando
} }
#endif #endif
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
# include <private/qjni_p.h>
#endif
// This file is too low-level for regular Q_ASSERT (the logging framework may // This file is too low-level for regular Q_ASSERT (the logging framework may
// recurse back), so use regular assert() // recurse back), so use regular assert()
#undef NDEBUG #undef NDEBUG

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.
@ -41,7 +41,7 @@
#ifndef QT_NO_STANDARDPATHS #ifndef QT_NO_STANDARDPATHS
#include <QtCore/private/qjni_p.h> #include <QJniObject>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/qmap.h> #include <QtCore/qmap.h>
#include <QDir> #include <QDir>
@ -57,13 +57,13 @@ static QString testDir()
: QLatin1String(""); : QLatin1String("");
} }
static QJNIObjectPrivate applicationContext() static QJniObject applicationContext()
{ {
static QJNIObjectPrivate appCtx; static QJniObject appCtx;
if (appCtx.isValid()) if (appCtx.isValid())
return appCtx; return appCtx;
QJNIObjectPrivate context(QtAndroidPrivate::activity()); QJniObject context(QtAndroidPrivate::activity());
if (!context.isValid()) { if (!context.isValid()) {
context = QtAndroidPrivate::service(); context = QtAndroidPrivate::service();
if (!context.isValid()) if (!context.isValid())
@ -75,9 +75,9 @@ static QJNIObjectPrivate applicationContext()
return appCtx; return appCtx;
} }
static inline QString getAbsolutePath(const QJNIObjectPrivate &file) static inline QString getAbsolutePath(const QJniObject &file)
{ {
QJNIObjectPrivate path = file.callObjectMethod("getAbsolutePath", QJniObject path = file.callObjectMethod("getAbsolutePath",
"()Ljava/lang/String;"); "()Ljava/lang/String;");
if (!path.isValid()) if (!path.isValid())
return QString(); return QString();
@ -95,20 +95,20 @@ static QString getExternalFilesDir(const char *directoryField = nullptr)
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
QJNIObjectPrivate appCtx = applicationContext(); QJniObject appCtx = applicationContext();
if (!appCtx.isValid()) if (!appCtx.isValid())
return QString(); return QString();
QJNIObjectPrivate dirField = QJNIObjectPrivate::fromString(QLatin1String("")); QJniObject dirField = QJniObject::fromString(QLatin1String(""));
if (directoryField && strlen(directoryField) > 0) { if (directoryField && strlen(directoryField) > 0) {
dirField = QJNIObjectPrivate::getStaticObjectField("android/os/Environment", dirField = QJniObject::getStaticObjectField("android/os/Environment",
directoryField, directoryField,
"Ljava/lang/String;"); "Ljava/lang/String;");
if (!dirField.isValid()) if (!dirField.isValid())
return QString(); return QString();
} }
QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalFilesDir", QJniObject file = appCtx.callObjectMethod("getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;", "(Ljava/lang/String;)Ljava/io/File;",
dirField.object()); dirField.object());
@ -128,11 +128,11 @@ static QString getExternalCacheDir()
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
QJNIObjectPrivate appCtx = applicationContext(); QJniObject appCtx = applicationContext();
if (!appCtx.isValid()) if (!appCtx.isValid())
return QString(); return QString();
QJNIObjectPrivate file = appCtx.callObjectMethod("getExternalCacheDir", QJniObject file = appCtx.callObjectMethod("getExternalCacheDir",
"()Ljava/io/File;"); "()Ljava/io/File;");
if (!file.isValid()) if (!file.isValid())
@ -150,11 +150,11 @@ static QString getCacheDir()
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
QJNIObjectPrivate appCtx = applicationContext(); QJniObject appCtx = applicationContext();
if (!appCtx.isValid()) if (!appCtx.isValid())
return QString(); return QString();
QJNIObjectPrivate file = appCtx.callObjectMethod("getCacheDir", QJniObject file = appCtx.callObjectMethod("getCacheDir",
"()Ljava/io/File;"); "()Ljava/io/File;");
if (!file.isValid()) if (!file.isValid())
return QString(); return QString();
@ -172,11 +172,11 @@ static QString getFilesDir()
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
QJNIObjectPrivate appCtx = applicationContext(); QJniObject appCtx = applicationContext();
if (!appCtx.isValid()) if (!appCtx.isValid())
return QString(); return QString();
QJNIObjectPrivate file = appCtx.callObjectMethod("getFilesDir", QJniObject file = appCtx.callObjectMethod("getFilesDir",
"()Ljava/io/File;"); "()Ljava/io/File;");
if (!file.isValid()) if (!file.isValid())
return QString(); return QString();

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation. ** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -91,8 +91,8 @@
#endif // QT_NO_QOBJECT #endif // QT_NO_QOBJECT
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
# include <private/qjni_p.h> #include <QJniObject>
# include <private/qjnihelpers_p.h> #include <private/qjnihelpers_p.h>
#endif #endif
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -170,17 +170,17 @@ QString QCoreApplicationPrivate::appVersion() const
# ifdef Q_OS_DARWIN # ifdef Q_OS_DARWIN
applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion")); applicationVersion = infoDictionaryStringProperty(QStringLiteral("CFBundleVersion"));
# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) # elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
QJNIObjectPrivate context(QtAndroidPrivate::context()); QJniObject context(QtAndroidPrivate::context());
if (context.isValid()) { if (context.isValid()) {
QJNIObjectPrivate pm = context.callObjectMethod( QJniObject pm = context.callObjectMethod(
"getPackageManager", "()Landroid/content/pm/PackageManager;"); "getPackageManager", "()Landroid/content/pm/PackageManager;");
QJNIObjectPrivate pn = context.callObjectMethod<jstring>("getPackageName"); QJniObject pn = context.callObjectMethod<jstring>("getPackageName");
if (pm.isValid() && pn.isValid()) { if (pm.isValid() && pn.isValid()) {
QJNIObjectPrivate packageInfo = pm.callObjectMethod( QJniObject packageInfo = pm.callObjectMethod(
"getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;", "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
pn.object(), 0); pn.object(), 0);
if (packageInfo.isValid()) { if (packageInfo.isValid()) {
QJNIObjectPrivate versionName = packageInfo.getObjectField( QJniObject versionName = packageInfo.getObjectField(
"versionName", "Ljava/lang/String;"); "versionName", "Ljava/lang/String;");
if (versionName.isValid()) if (versionName.isValid())
return versionName.toString(); return versionName.toString();

View File

@ -47,6 +47,7 @@
// //
// We mean it. // We mean it.
// //
// FIXME: Remove this once the JNI API is used by other modules.
#ifndef QJNI_P_H #ifndef QJNI_P_H
#define QJNI_P_H #define QJNI_P_H

View File

@ -0,0 +1,283 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** 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-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qjnienvironment.h"
#include "qjniobject.h"
#include "qjnihelpers_p.h"
#include <QtCore/QThread>
#include <QtCore/QThreadStorage>
QT_BEGIN_NAMESPACE
/*!
\class QJniEnvironment
\inmodule QtCore
\brief The QJniEnvironment provides access to the JNI Environment.
\since 6.1
\note This API has been tested and meant to be mainly used for Android and it hasn't been tested
for other platforms.
*/
static const char qJniThreadName[] = "QtThread";
class QJniEnvironmentPrivate
{
public:
JNIEnv *jniEnv = nullptr;
};
class QJniEnvironmentPrivateTLS
{
public:
inline ~QJniEnvironmentPrivateTLS()
{
QtAndroidPrivate::javaVM()->DetachCurrentThread();
}
};
struct QJniLocalRefDeleterPrivate
{
static void cleanup(jobject obj)
{
if (!obj)
return;
QJniEnvironment env;
env->DeleteLocalRef(obj);
}
};
// To simplify this we only define it for jobjects.
typedef QScopedPointer<_jobject, QJniLocalRefDeleterPrivate> QJniScopedLocalRefPrivate;
Q_GLOBAL_STATIC(QThreadStorage<QJniEnvironmentPrivateTLS *>, jniEnvTLS)
/*!
\fn QJniEnvironment::QJniEnvironment()
Constructs a new QJniEnvironment object and attaches the current thread to the Java VM.
*/
QJniEnvironment::QJniEnvironment()
: d(new QJniEnvironmentPrivate{})
{
JavaVM *vm = QtAndroidPrivate::javaVM();
const jint ret = vm->GetEnv((void**)&d->jniEnv, JNI_VERSION_1_6);
if (ret == JNI_OK) // Already attached
return;
if (ret == JNI_EDETACHED) { // We need to (re-)attach
JavaVMAttachArgs args = { JNI_VERSION_1_6, qJniThreadName, nullptr };
if (vm->AttachCurrentThread(&d->jniEnv, &args) != JNI_OK)
return;
if (!jniEnvTLS->hasLocalData()) // If we attached the thread we own it.
jniEnvTLS->setLocalData(new QJniEnvironmentPrivateTLS);
}
}
/*!
\fn QJniEnvironment::~QJniEnvironment()
Detaches the current thread from the Java VM and destroys the QJniEnvironment object.
*/
QJniEnvironment::~QJniEnvironment()
{
exceptionCheckAndClear();
}
/*!
\fn JNIEnv *QJniEnvironment::operator->()
Provides access to the QJniEnvironment's JNIEnv pointer.
*/
JNIEnv *QJniEnvironment::operator->()
{
return d->jniEnv;
}
/*!
\fn QJniEnvironment::operator JNIEnv *() const
Returns the JNI Environment pointer.
*/
QJniEnvironment::operator JNIEnv* () const
{
return d->jniEnv;
}
/*!
\fn jclass QJniEnvironment::findClass(const char *className)
Searches for \a className using all available class loaders. Qt on Android
uses a custom class loader to load all the .jar files and it must be used
to find any classes that are created by that class loader because these
classes are not visible in the default class loader.
Returns the class pointer or null if is not found.
A use case for this function is searching for a custom class then calling
its memeber method. The following code snippet create an instance of the
class \c CustomClass and then calls \c printFromJava() method:
\code
QJniEnvironment env;
jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
QJniObject classObject(javaClass);
QJniObject javaMessage = QJniObject::fromString("findClass example");
classObject.callMethod<void>("printFromJava",
"(Ljava/lang/String;)V",
javaMessage.object<jstring>());
\endcode
\since Qt 6.1
*/
jclass QJniEnvironment::findClass(const char *className)
{
return QtAndroidPrivate::findClass(className, d->jniEnv);
}
/*!
\fn JavaVM *QJniEnvironment::javaVM()
Returns the Java VM interface.
\since Qt 6.1
*/
JavaVM *QJniEnvironment::javaVM()
{
return QtAndroidPrivate::javaVM();
}
/*!
\fn bool QJniEnvironment::registerNativeMethods(const char *className, JNINativeMethod methods[])
Registers the Java methods \a methods that 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.
Each element in the methods array consists of:
\list
\li The Java method name
\li Method signature
\li The C++ functions that will be executed
\endlist
\code
JNINativeMethod methods[] {{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
{"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
QJniEnvironment env;
env.registerNativeMethods("org/qtproject/android/TestJavaClass", methods);
\endcode
\since Qt 6.1
*/
bool QJniEnvironment::registerNativeMethods(const char *className, JNINativeMethod methods[], int size)
{
jclass clazz = findClass(className);
if (!clazz)
return false;
jclass gClazz = static_cast<jclass>(d->jniEnv->NewGlobalRef(clazz));
if (d->jniEnv->RegisterNatives(gClazz, methods, size / sizeof(methods[0])) < 0) {
exceptionCheckAndClear();
return false;
}
d->jniEnv->DeleteLocalRef(gClazz);
return true;
}
/*!
\enum QJniExceptionCleaner::OutputMode
\value Silent the exceptions are cleaned silently
\value Verbose describes the exceptions before cleaning them
*/
/*!
\fn QJniEnvironment::exceptionCheckAndClear(OutputMode outputMode = OutputMode::Silent)
Cleans any pending exceptions either silently or with descriptions, depending on the \a outputMode.
\since 6.1
*/
bool QJniEnvironment::exceptionCheckAndClear(QJniEnvironment::OutputMode outputMode)
{
if (Q_UNLIKELY(d->jniEnv->ExceptionCheck())) {
if (outputMode != OutputMode::Silent)
d->jniEnv->ExceptionDescribe();
d->jniEnv->ExceptionClear();
return true;
}
return false;
}
/*!
\fn QJniEnvironment::exceptionCheckAndClear(JNIEnv *env, OutputMode outputMode = OutputMode::Silent)
Cleans any pending exceptions for \a env, either silently or with descriptions, depending on the \a outputMode.
\since 6.1
*/
bool QJniEnvironment::exceptionCheckAndClear(JNIEnv *env, QJniEnvironment::OutputMode outputMode)
{
if (Q_UNLIKELY(env->ExceptionCheck())) {
if (outputMode != OutputMode::Silent)
env->ExceptionDescribe();
env->ExceptionClear();
return true;
}
return false;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** 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-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QJNI_ENVIRONMENT_H
#define QJNI_ENVIRONMENT_H
#include <QScopedPointer>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <jni.h>
#else
class JNIEnv;
class JNINativeMethod;
class JavaVM;
class jclass;
#endif
QT_BEGIN_NAMESPACE
class QJniEnvironmentPrivate;
class Q_CORE_EXPORT QJniEnvironment
{
public:
QJniEnvironment();
~QJniEnvironment();
JNIEnv *operator->();
operator JNIEnv *() const;
jclass findClass(const char *className);
static JavaVM *javaVM();
bool registerNativeMethods(const char *className, JNINativeMethod methods[], int size);
enum class OutputMode {
Silent,
Verbose
};
bool exceptionCheckAndClear(OutputMode outputMode = OutputMode::Verbose);
static bool exceptionCheckAndClear(JNIEnv *env, OutputMode outputMode = OutputMode::Verbose);
private:
Q_DISABLE_COPY_MOVE(QJniEnvironment)
QScopedPointer<QJniEnvironmentPrivate> d;
};
QT_END_NAMESPACE
#endif // QJNI_ENVIRONMENT_H

View File

@ -37,14 +37,16 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qcoreapplication.h"
#include "qjnienvironment.h"
#include "qjnihelpers_p.h" #include "qjnihelpers_p.h"
#include "qjni_p.h" #include "qjniobject.h"
#include "qmutex.h"
#include "qlist.h" #include "qlist.h"
#include "qmutex.h"
#include "qsemaphore.h" #include "qsemaphore.h"
#include "qsharedpointer.h" #include "qsharedpointer.h"
#include "qthread.h" #include "qthread.h"
#include "qcoreapplication.h"
#include <QtCore/qrunnable.h> #include <QtCore/qrunnable.h>
#include <deque> #include <deque>
@ -146,7 +148,7 @@ static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requ
std::unique_ptr<jint[]> results(new jint[size]); std::unique_ptr<jint[]> results(new jint[size]);
env->GetIntArrayRegion(grantResults, 0, size, results.get()); env->GetIntArrayRegion(grantResults, 0, size, results.get());
for (int i = 0 ; i < size; ++i) { for (int i = 0 ; i < size; ++i) {
const auto &permission = QJNIObjectPrivate(env->GetObjectArrayElement(permissions, i)).toString(); const auto &permission = QJniObject(env->GetObjectArrayElement(permissions, i)).toString();
auto value = results[i] == PERMISSION_GRANTED ? auto value = results[i] == PERMISSION_GRANTED ?
QtAndroidPrivate::PermissionsResult::Granted : QtAndroidPrivate::PermissionsResult::Granted :
QtAndroidPrivate::PermissionsResult::Denied; QtAndroidPrivate::PermissionsResult::Denied;
@ -286,27 +288,14 @@ void QtAndroidPrivate::handleResume()
listeners.at(i)->handleResume(); listeners.at(i)->handleResume();
} }
static inline bool exceptionCheck(JNIEnv *env)
{
if (env->ExceptionCheck()) {
#ifdef QT_DEBUG
env->ExceptionDescribe();
#endif // QT_DEBUG
env->ExceptionClear();
return true;
}
return false;
}
static void setAndroidSdkVersion(JNIEnv *env) static void setAndroidSdkVersion(JNIEnv *env)
{ {
jclass androidVersionClass = env->FindClass("android/os/Build$VERSION"); jclass androidVersionClass = env->FindClass("android/os/Build$VERSION");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return; return;
jfieldID androidSDKFieldID = env->GetStaticFieldID(androidVersionClass, "SDK_INT", "I"); jfieldID androidSDKFieldID = env->GetStaticFieldID(androidVersionClass, "SDK_INT", "I");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return; return;
g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID); g_androidSdkVersion = env->GetStaticIntField(androidVersionClass, androidSDKFieldID);
@ -342,42 +331,42 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
{ {
jclass jQtNative = env->FindClass("org/qtproject/qt/android/QtNative"); jclass jQtNative = env->FindClass("org/qtproject/qt/android/QtNative");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jmethodID activityMethodID = env->GetStaticMethodID(jQtNative, jmethodID activityMethodID = env->GetStaticMethodID(jQtNative,
"activity", "activity",
"()Landroid/app/Activity;"); "()Landroid/app/Activity;");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jobject activity = env->CallStaticObjectMethod(jQtNative, activityMethodID); jobject activity = env->CallStaticObjectMethod(jQtNative, activityMethodID);
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jmethodID serviceMethodID = env->GetStaticMethodID(jQtNative, jmethodID serviceMethodID = env->GetStaticMethodID(jQtNative,
"service", "service",
"()Landroid/app/Service;"); "()Landroid/app/Service;");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jobject service = env->CallStaticObjectMethod(jQtNative, serviceMethodID); jobject service = env->CallStaticObjectMethod(jQtNative, serviceMethodID);
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jmethodID classLoaderMethodID = env->GetStaticMethodID(jQtNative, jmethodID classLoaderMethodID = env->GetStaticMethodID(jQtNative,
"classLoader", "classLoader",
"()Ljava/lang/ClassLoader;"); "()Ljava/lang/ClassLoader;");
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
jobject classLoader = env->CallStaticObjectMethod(jQtNative, classLoaderMethodID); jobject classLoader = env->CallStaticObjectMethod(jQtNative, classLoaderMethodID);
if (exceptionCheck(env)) if (QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
setAndroidSdkVersion(env); setAndroidSdkVersion(env);
@ -405,7 +394,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK); const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK);
if (!regOk && exceptionCheck(env)) if (!regOk && QJniEnvironment::exceptionCheckAndClear(env))
return JNI_ERR; return JNI_ERR;
g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative, g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative,
@ -495,7 +484,10 @@ void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &
waitForSemaphore(timeoutMs, sem); waitForSemaphore(timeoutMs, sem);
} }
void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall) void QtAndroidPrivate::requestPermissions(JNIEnv *env,
const QStringList &permissions,
const QtAndroidPrivate::PermissionsResultFunc &callbackFunc,
bool directCall)
{ {
if (androidSdkVersion() < 23 || !activity()) { if (androidSdkVersion() < 23 || !activity()) {
QHash<QString, QtAndroidPrivate::PermissionsResult> res; QHash<QString, QtAndroidPrivate::PermissionsResult> res;
@ -517,12 +509,17 @@ void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permis
(*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc); (*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
} }
QJNIEnvironmentPrivate env; QJniEnvironment env;
auto array = env->NewObjectArray(permissions.size(), env->FindClass("java/lang/String"), nullptr); jclass clazz = env->FindClass("java/lang/String");
if (env.exceptionCheckAndClear())
return;
auto array = env->NewObjectArray(permissions.size(), clazz, nullptr);
int index = 0; int index = 0;
for (const auto &perm : permissions) for (const auto &perm : permissions)
env->SetObjectArrayElement(array, index++, QJNIObjectPrivate::fromString(perm).object()); env->SetObjectArrayElement(array, index++, QJniObject::fromString(perm).object());
QJNIObjectPrivate(activity()).callMethod<void>("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode); QJniObject(activity()).callMethod<void>("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode);
env->DeleteLocalRef(array); env->DeleteLocalRef(array);
}, env); }, env);
} }
@ -543,10 +540,10 @@ QtAndroidPrivate::PermissionsHash QtAndroidPrivate::requestPermissionsSync(JNIEn
QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission) QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission)
{ {
const auto res = QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt/android/QtNative", const auto res = QJniObject::callStaticMethod<jint>("org/qtproject/qt/android/QtNative",
"checkSelfPermission", "checkSelfPermission",
"(Ljava/lang/String;)I", "(Ljava/lang/String;)I",
QJNIObjectPrivate::fromString(permission).object()); QJniObject::fromString(permission).object());
return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied; return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied;
} }
@ -555,8 +552,9 @@ bool QtAndroidPrivate::shouldShowRequestPermissionRationale(const QString &permi
if (androidSdkVersion() < 23 || !activity()) if (androidSdkVersion() < 23 || !activity())
return false; return false;
return QJNIObjectPrivate(activity()).callMethod<jboolean>("shouldShowRequestPermissionRationale", "(Ljava/lang/String;)Z", return QJniObject(activity()).callMethod<jboolean>("shouldShowRequestPermissionRationale",
QJNIObjectPrivate::fromString(permission).object()); "(Ljava/lang/String;)Z",
QJniObject::fromString(permission).object());
} }
void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener) void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener)

View File

@ -119,6 +119,7 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT jobject context(); Q_CORE_EXPORT jobject context();
Q_CORE_EXPORT JavaVM *javaVM(); Q_CORE_EXPORT JavaVM *javaVM();
Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env); Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env);
Q_CORE_EXPORT jclass findClass(const char *className, JNIEnv *env);
jobject classLoader(); jobject classLoader();
Q_CORE_EXPORT jint androidSdkVersion(); Q_CORE_EXPORT jint androidSdkVersion();
Q_CORE_EXPORT void runOnAndroidThread(const Runnable &runnable, JNIEnv *env); Q_CORE_EXPORT void runOnAndroidThread(const Runnable &runnable, JNIEnv *env);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,207 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** 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-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QJNIOBJECT_H
#define QJNIOBJECT_H
#include <QtCore/QSharedPointer>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <jni.h>
#else
class jclass;
class jobject;
#endif
QT_BEGIN_NAMESPACE
class QJniObjectPrivate;
class Q_CORE_EXPORT QJniObject
{
public:
QJniObject();
explicit QJniObject(const char *className);
explicit QJniObject(const char *className, const char *sig, ...);
explicit QJniObject(jclass clazz);
explicit QJniObject(jclass clazz, const char *sig, ...);
QJniObject(jobject globalRef);
~QJniObject();
template <typename T>
T object() const;
jobject object() const;
template <typename T>
T callMethod(const char *methodName, const char *sig, ...) const;
template <typename T>
T callMethod(const char *methodName) const;
template <typename T>
QJniObject callObjectMethod(const char *methodName) const;
QJniObject callObjectMethod(const char *methodName, const char *sig, ...) const;
template <typename T>
static T callStaticMethod(const char *className, const char *methodName, const char *sig, ...);
template <typename T>
static T callStaticMethod(const char *className, const char *methodName);
template <typename T>
static T callStaticMethod(jclass clazz, const char *methodName, const char *sig, ...);
template <typename T>
static T callStaticMethod(jclass clazz, const char *methodName);
template <typename T>
static QJniObject callStaticObjectMethod(const char *className, const char *methodName);
static QJniObject callStaticObjectMethod(const char *className,
const char *methodName,
const char *sig, ...);
template <typename T>
static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName);
static QJniObject callStaticObjectMethod(jclass clazz,
const char *methodName,
const char *sig, ...);
template <typename T>
T getField(const char *fieldName) const;
template <typename T>
static T getStaticField(const char *className, const char *fieldName);
template <typename T>
static T getStaticField(jclass clazz, const char *fieldName);
template <typename T>
QJniObject getObjectField(const char *fieldName) const;
QJniObject getObjectField(const char *fieldName, const char *sig) const;
template <typename T>
static QJniObject getStaticObjectField(const char *className, const char *fieldName);
static QJniObject getStaticObjectField(const char *className,
const char *fieldName,
const char *sig);
template <typename T>
static QJniObject getStaticObjectField(const char *className,
const char *fieldName,
const char *sig);
template <typename T>
static QJniObject getStaticObjectField(jclass clazz, const char *fieldName);
static QJniObject getStaticObjectField(jclass clazz, const char *fieldName, const char *sig);
template <typename T>
static QJniObject getStaticObjectField(jclass clazz, const char *fieldName, const char *sig);
template <typename T>
void setField(const char *fieldName, T value);
template <typename T>
void setField(const char *fieldName, const char *sig, T value);
template <typename T>
static void setStaticField(const char *className, const char *fieldName, T value);
template <typename T>
static void setStaticField(const char *className, const char *fieldName,
const char *sig, T value);
template <typename T>
static void setStaticField(jclass clazz, const char *fieldName, const char *sig, T value);
template <typename T>
static void setStaticField(jclass clazz, const char *fieldName, T value);
static QJniObject fromString(const QString &string);
QString toString() const;
static bool isClassAvailable(const char *className);
bool isValid() const;
// This function takes ownership of the jobject and releases the local ref. before returning.
static QJniObject fromLocalRef(jobject lref);
template <typename T> QJniObject &operator=(T obj);
private:
struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; };
QJniObject(const char *className, const char *sig, const QVaListPrivate &args);
QJniObject(jclass clazz, const char *sig, const QVaListPrivate &args);
template <typename T>
T callMethodV(const char *methodName, const char *sig, va_list args) const;
QJniObject callObjectMethodV(const char *methodName, const char *sig, va_list args) const;
template <typename T>
static T callStaticMethodV(const char *className,
const char *methodName,
const char *sig,
va_list args);
template <typename T>
static T callStaticMethodV(jclass clazz,
const char *methodName,
const char *sig,
va_list args);
static QJniObject callStaticObjectMethodV(const char *className,
const char *methodName,
const char *sig,
va_list args);
static QJniObject callStaticObjectMethodV(jclass clazz,
const char *methodName,
const char *sig,
va_list args);
bool isSameObject(jobject obj) const;
bool isSameObject(const QJniObject &other) const;
void assign(jobject obj);
jobject javaObject() const;
friend bool operator==(const QJniObject &, const QJniObject &);
friend bool operator!=(const QJniObject&, const QJniObject&);
QSharedPointer<QJniObjectPrivate> d;
};
inline bool operator==(const QJniObject &obj1, const QJniObject &obj2)
{
return obj1.isSameObject(obj2);
}
inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
{
return !obj1.isSameObject(obj2);
}
QT_END_NAMESPACE
#endif // QJNIOBJECT_H

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtCore module of the Qt Toolkit. ** This file is part of the QtCore module of the Qt Toolkit.
@ -37,8 +37,9 @@
** **
****************************************************************************/ ****************************************************************************/
#include <jni.h>
#include "qjnihelpers_p.h" #include "qjnihelpers_p.h"
#include <jni.h>
#include <android/log.h> #include <android/log.h>
static const char logTag[] = "QtCore"; static const char logTag[] = "QtCore";

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com> ** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -38,10 +38,12 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtCore/QSet>
#include "qtimezone.h" #include "qtimezone.h"
#include "qtimezoneprivate_p.h" #include "qtimezoneprivate_p.h"
#include <QtCore/QJniEnvironment>
#include <QtCore/QSet>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/* /*
@ -49,7 +51,7 @@ QT_BEGIN_NAMESPACE
Android implementation Android implementation
Note that a QJNIObjectPrivate manages a global reference, so it serves as an Note that a QJniObject manages a global reference, so it serves as an
owning smart-pointer, ensuring an object doesn't get garbage-collected owning smart-pointer, ensuring an object doesn't get garbage-collected
before we're done with it. before we're done with it.
*/ */
@ -59,9 +61,9 @@ QAndroidTimeZonePrivate::QAndroidTimeZonePrivate()
: QTimeZonePrivate() : QTimeZonePrivate()
{ {
// Keep in sync with systemTimeZoneId(): // Keep in sync with systemTimeZoneId():
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( androidTimeZone = QJniObject::callStaticObjectMethod(
"java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
const QJNIObjectPrivate id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"); const QJniObject id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;");
m_id = id.toString().toUtf8(); m_id = id.toString().toUtf8();
} }
@ -83,16 +85,16 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{ {
} }
static QJNIObjectPrivate getDisplayName(QJNIObjectPrivate zone, jint style, jboolean dst, static QJniObject getDisplayName(QJniObject zone, jint style, jboolean dst,
const QLocale &locale) const QLocale &locale)
{ {
QJNIObjectPrivate jlanguage QJniObject jlanguage
= QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language())); = QJniObject::fromString(QLocale::languageToString(locale.language()));
QJNIObjectPrivate jcountry QJniObject jcountry
= QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country())); = QJniObject::fromString(QLocale::countryToString(locale.country()));
QJNIObjectPrivate QJniObject
jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script())); jvariant = QJniObject::fromString(QLocale::scriptToString(locale.script()));
QJNIObjectPrivate jlocale("java.util.Locale", QJniObject jlocale("java.util.Locale",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
static_cast<jstring>(jlanguage.object()), static_cast<jstring>(jlanguage.object()),
static_cast<jstring>(jcountry.object()), static_cast<jstring>(jcountry.object()),
@ -106,12 +108,12 @@ static QJNIObjectPrivate getDisplayName(QJNIObjectPrivate zone, jint style, jboo
void QAndroidTimeZonePrivate::init(const QByteArray &ianaId) void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{ {
const QString iana = QString::fromUtf8(ianaId); const QString iana = QString::fromUtf8(ianaId);
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( androidTimeZone = QJniObject::callStaticObjectMethod(
"java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",
static_cast<jstring>(QJNIObjectPrivate::fromString(iana).object())); static_cast<jstring>(QJniObject::fromString(iana).object()));
// The ID or display name of the zone we've got, if it looks like what we asked for: // The ID or display name of the zone we've got, if it looks like what we asked for:
const auto match = [iana](const QJNIObjectPrivate &jname) -> QByteArray { const auto match = [iana](const QJniObject &jname) -> QByteArray {
const QString name = jname.toString(); const QString name = jname.toString();
if (iana.compare(name, Qt::CaseInsensitive) == 0) if (iana.compare(name, Qt::CaseInsensitive) == 0)
return name.toUtf8(); return name.toUtf8();
@ -205,7 +207,7 @@ bool QAndroidTimeZonePrivate::hasDaylightTime() const
bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const bool QAndroidTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch) const
{ {
if ( androidTimeZone.isValid() ) { if ( androidTimeZone.isValid() ) {
QJNIObjectPrivate jDate( "java/util/Date", "(J)V", static_cast<jlong>(atMSecsSinceEpoch) ); QJniObject jDate( "java/util/Date", "(J)V", static_cast<jlong>(atMSecsSinceEpoch) );
return androidTimeZone.callMethod<jboolean>("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() ); return androidTimeZone.callMethod<jboolean>("inDaylightTime", "(Ljava/util/Date;)Z", jDate.object() );
} }
else else
@ -250,24 +252,24 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before
QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
{ {
// Keep in sync with default constructor: // Keep in sync with default constructor:
QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod( QJniObject androidSystemTimeZone = QJniObject::callStaticObjectMethod(
"java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
const QJNIObjectPrivate id = androidSystemTimeZone.callObjectMethod<jstring>("getID"); const QJniObject id = androidSystemTimeZone.callObjectMethod<jstring>("getID");
return id.toString().toUtf8(); return id.toString().toUtf8();
} }
QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const
{ {
QList<QByteArray> availableTimeZoneIdList; QList<QByteArray> availableTimeZoneIdList;
QJNIObjectPrivate androidAvailableIdList = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;"); QJniObject androidAvailableIdList = QJniObject::callStaticObjectMethod("java.util.TimeZone", "getAvailableIDs", "()[Ljava/lang/String;");
QJNIEnvironmentPrivate jniEnv; QJniEnvironment jniEnv;
int androidTZcount = jniEnv->GetArrayLength( static_cast<jarray>(androidAvailableIdList.object()) ); int androidTZcount = jniEnv->GetArrayLength( static_cast<jarray>(androidAvailableIdList.object()) );
// need separate jobject and QAndroidJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject // need separate jobject and QJniObject here so that we can delete (DeleteLocalRef) the reference to the jobject
// (or else the JNI reference table fills after 512 entries from GetObjectArrayElement) // (or else the JNI reference table fills after 512 entries from GetObjectArrayElement)
jobject androidTZobject; jobject androidTZobject;
QJNIObjectPrivate androidTZ; QJniObject androidTZ;
for (int i=0; i<androidTZcount; i++ ) { for (int i=0; i<androidTZcount; i++ ) {
androidTZobject = jniEnv->GetObjectArrayElement( static_cast<jobjectArray>( androidAvailableIdList.object() ), i ); androidTZobject = jniEnv->GetObjectArrayElement( static_cast<jobjectArray>( androidAvailableIdList.object() ), i );
androidTZ = androidTZobject; androidTZ = androidTZobject;

View File

@ -70,7 +70,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
#endif // Q_OS_WIN #endif // Q_OS_WIN
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <QtCore/private/qjni_p.h> #include <QJniObject>
#endif #endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -496,7 +496,7 @@ public:
private: private:
void init(const QByteArray &zoneId); void init(const QByteArray &zoneId);
QJNIObjectPrivate androidTimeZone; QJniObject androidTimeZone;
}; };
#endif // Q_OS_ANDROID #endif // Q_OS_ANDROID

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtNetwork module of the Qt Toolkit. ** This file is part of the QtNetwork module of the Qt Toolkit.
@ -38,7 +38,9 @@
****************************************************************************/ ****************************************************************************/
#include "qnetworkproxy.h" #include "qnetworkproxy.h"
#include <QtCore/private/qjni_p.h>
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#ifndef QT_NO_NETWORKPROXY #ifndef QT_NO_NETWORKPROXY
@ -58,7 +60,7 @@ static const char networkClass[] = "org/qtproject/qt/android/network/QtNetwork";
ProxyInfoObject::ProxyInfoObject() ProxyInfoObject::ProxyInfoObject()
{ {
QJNIObjectPrivate::callStaticMethod<void>(networkClass, QJniObject::callStaticMethod<void>(networkClass,
"registerReceiver", "registerReceiver",
"(Landroid/content/Context;)V", "(Landroid/content/Context;)V",
QtAndroidPrivate::context()); QtAndroidPrivate::context());
@ -66,7 +68,7 @@ ProxyInfoObject::ProxyInfoObject()
ProxyInfoObject::~ProxyInfoObject() ProxyInfoObject::~ProxyInfoObject()
{ {
QJNIObjectPrivate::callStaticMethod<void>(networkClass, QJniObject::callStaticMethod<void>(networkClass,
"unregisterReceiver", "unregisterReceiver",
"(Landroid/content/Context;)V", "(Landroid/content/Context;)V",
QtAndroidPrivate::context()); QtAndroidPrivate::context());
@ -78,18 +80,18 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
if (!proxyInfoInstance) if (!proxyInfoInstance)
return proxyList; return proxyList;
QJNIObjectPrivate proxyInfo = QJNIObjectPrivate::callStaticObjectMethod(networkClass, QJniObject proxyInfo = QJniObject::callStaticObjectMethod(networkClass,
"getProxyInfo", "getProxyInfo",
"(Landroid/content/Context;)Landroid/net/ProxyInfo;", "(Landroid/content/Context;)Landroid/net/ProxyInfo;",
QtAndroidPrivate::context()); QtAndroidPrivate::context());
if (proxyInfo.isValid()) { if (proxyInfo.isValid()) {
QJNIObjectPrivate exclusionList = proxyInfo.callObjectMethod("getExclusionList", QJniObject exclusionList = proxyInfo.callObjectMethod("getExclusionList",
"()[Ljava/lang/String;"); "()[Ljava/lang/String;");
bool exclude = false; bool exclude = false;
if (exclusionList.isValid()) { if (exclusionList.isValid()) {
jobjectArray listObject = static_cast<jobjectArray>(exclusionList.object()); jobjectArray listObject = static_cast<jobjectArray>(exclusionList.object());
QJNIEnvironmentPrivate env; QJniEnvironment env;
QJNIObjectPrivate entry; QJniObject entry;
const int size = env->GetArrayLength(listObject); const int size = env->GetArrayLength(listObject);
QUrl host = QUrl(query.url().host()); QUrl host = QUrl(query.url().host());
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
@ -101,7 +103,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
} }
} }
if (!exclude) { if (!exclude) {
QJNIObjectPrivate hostName = proxyInfo.callObjectMethod<jstring>("getHost"); QJniObject hostName = proxyInfo.callObjectMethod<jstring>("getHost");
const int port = proxyInfo.callMethod<jint>("getPort"); const int port = proxyInfo.callMethod<jint>("getPort");
QNetworkProxy proxy(QNetworkProxy::HttpProxy, hostName.toString(), port); QNetworkProxy proxy(QNetworkProxy::HttpProxy, hostName.toString(), port);
proxyList << proxy; proxyList << proxy;

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the QtNetwork module of the Qt Toolkit. ** This file is part of the QtNetwork module of the Qt Toolkit.
@ -53,7 +53,8 @@
****************************************************************************/ ****************************************************************************/
#include "qsslsocket_openssl_p.h" #include "qsslsocket_openssl_p.h"
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -61,13 +62,13 @@ QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData()
{ {
QList<QByteArray> certificateData; QList<QByteArray> certificateData;
QJNIObjectPrivate certificates = QJNIObjectPrivate::callStaticObjectMethod("org/qtproject/qt/android/QtNative", QJniObject certificates = QJniObject::callStaticObjectMethod("org/qtproject/qt/android/QtNative",
"getSSLCertificates", "getSSLCertificates",
"()[[B"); "()[[B");
if (!certificates.isValid()) if (!certificates.isValid())
return certificateData; return certificateData;
QJNIEnvironmentPrivate env; QJniEnvironment env;
jobjectArray jcertificates = static_cast<jobjectArray>(certificates.object()); jobjectArray jcertificates = static_cast<jobjectArray>(certificates.object());
const jint nCertificates = env->GetArrayLength(jcertificates); const jint nCertificates = env->GetArrayLength(jcertificates);
certificateData.reserve(static_cast<int>(nCertificates)); certificateData.reserve(static_cast<int>(nCertificates));

View File

@ -39,7 +39,8 @@
#include "androidcontentfileengine.h" #include "androidcontentfileengine.h"
#include <private/qjni_p.h> #include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
#include <private/qjnihelpers_p.h> #include <private/qjnihelpers_p.h>
#include <QDebug> #include <QDebug>
@ -65,12 +66,12 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode)
openModeStr += QLatin1Char('a'); openModeStr += QLatin1Char('a');
} }
const auto fd = QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt/android/QtNative", const auto fd = QJniObject::callStaticMethod<jint>("org/qtproject/qt/android/QtNative",
"openFdForContentUrl", "openFdForContentUrl",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I", "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I",
QtAndroidPrivate::context(), QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(fileName(DefaultName)).object(), QJniObject::fromString(fileName(DefaultName)).object(),
QJNIObjectPrivate::fromString(openModeStr).object()); QJniObject::fromString(openModeStr).object());
if (fd < 0) { if (fd < 0) {
return false; return false;
@ -81,10 +82,10 @@ bool AndroidContentFileEngine::open(QIODevice::OpenMode openMode)
qint64 AndroidContentFileEngine::size() const qint64 AndroidContentFileEngine::size() const
{ {
const jlong size = QJNIObjectPrivate::callStaticMethod<jlong>( const jlong size = QJniObject::callStaticMethod<jlong>(
"org/qtproject/qt/android/QtNative", "getSize", "org/qtproject/qt/android/QtNative", "getSize",
"(Landroid/content/Context;Ljava/lang/String;)J", QtAndroidPrivate::context(), "(Landroid/content/Context;Ljava/lang/String;)J", QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); QJniObject::fromString(fileName(DefaultName)).object());
return (qint64)size; return (qint64)size;
} }
@ -92,25 +93,25 @@ AndroidContentFileEngine::FileFlags AndroidContentFileEngine::fileFlags(FileFlag
{ {
FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag); FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag);
FileFlags flags; FileFlags flags;
const bool isDir = QJNIObjectPrivate::callStaticMethod<jboolean>( const bool isDir = QJniObject::callStaticMethod<jboolean>(
"org/qtproject/qt/android/QtNative", "checkIfDir", "org/qtproject/qt/android/QtNative", "checkIfDir",
"(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(), "(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); QJniObject::fromString(fileName(DefaultName)).object());
// If it is a directory then we know it exists so there is no reason to explicitly check // If it is a directory then we know it exists so there is no reason to explicitly check
const bool exists = isDir ? true : QJNIObjectPrivate::callStaticMethod<jboolean>( const bool exists = isDir ? true : QJniObject::callStaticMethod<jboolean>(
"org/qtproject/qt/android/QtNative", "checkFileExists", "org/qtproject/qt/android/QtNative", "checkFileExists",
"(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(), "(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); QJniObject::fromString(fileName(DefaultName)).object());
if (!exists && !isDir) if (!exists && !isDir)
return flags; return flags;
if (isDir) { if (isDir) {
flags = DirectoryType | commonFlags; flags = DirectoryType | commonFlags;
} else { } else {
flags = FileType | commonFlags; flags = FileType | commonFlags;
const bool writable = QJNIObjectPrivate::callStaticMethod<jboolean>( const bool writable = QJniObject::callStaticMethod<jboolean>(
"org/qtproject/qt/android/QtNative", "checkIfWritable", "org/qtproject/qt/android/QtNative", "checkIfWritable",
"(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(), "(Landroid/content/Context;Ljava/lang/String;)Z", QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(fileName(DefaultName)).object()); QJniObject::fromString(fileName(DefaultName)).object());
if (writable) if (writable)
flags |= WriteOwnerPerm|WriteUserPerm|WriteGroupPerm|WriteOtherPerm; flags |= WriteOwnerPerm|WriteUserPerm|WriteGroupPerm|WriteOtherPerm;
} }
@ -182,22 +183,22 @@ bool AndroidContentFileEngineIterator::hasNext() const
if (m_index == -1) { if (m_index == -1) {
if (path().isEmpty()) if (path().isEmpty())
return false; return false;
const bool isDir = QJNIObjectPrivate::callStaticMethod<jboolean>( const bool isDir = QJniObject::callStaticMethod<jboolean>(
"org/qtproject/qt/android/QtNative", "checkIfDir", "org/qtproject/qt/android/QtNative", "checkIfDir",
"(Landroid/content/Context;Ljava/lang/String;)Z", "(Landroid/content/Context;Ljava/lang/String;)Z",
QtAndroidPrivate::context(), QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(path()).object()); QJniObject::fromString(path()).object());
if (isDir) { if (isDir) {
QJNIObjectPrivate objArray = QJNIObjectPrivate::callStaticObjectMethod("org/qtproject/qt/android/QtNative", QJniObject objArray = QJniObject::callStaticObjectMethod("org/qtproject/qt/android/QtNative",
"listContentsFromTreeUri", "listContentsFromTreeUri",
"(Landroid/content/Context;Ljava/lang/String;)[Ljava/lang/String;", "(Landroid/content/Context;Ljava/lang/String;)[Ljava/lang/String;",
QtAndroidPrivate::context(), QtAndroidPrivate::context(),
QJNIObjectPrivate::fromString(path()).object()); QJniObject::fromString(path()).object());
if (objArray.isValid()) { if (objArray.isValid()) {
QJNIEnvironmentPrivate env; QJniEnvironment env;
const jsize length = env->GetArrayLength(static_cast<jarray>(objArray.object())); const jsize length = env->GetArrayLength(static_cast<jarray>(objArray.object()));
for (int i = 0; i != length; ++i) { for (int i = 0; i != length; ++i) {
m_entries << QJNIObjectPrivate(env->GetObjectArrayElement( m_entries << QJniObject(env->GetObjectArrayElement(
static_cast<jobjectArray>(objArray.object()), i)).toString(); static_cast<jobjectArray>(objArray.object()), i)).toString();
} }
} }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -48,11 +48,9 @@
#include "QtGui/qaccessible.h" #include "QtGui/qaccessible.h"
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniObject>
#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/private/qhighdpiscaling_p.h>
#include "qdebug.h"
static const char m_qtTag[] = "Qt A11Y"; static const char m_qtTag[] = "Qt A11Y";
static const char m_classErrorMsg[] = "Can't find class \"%s\""; static const char m_classErrorMsg[] = "Can't find class \"%s\"";
@ -77,7 +75,7 @@ namespace QtAndroidAccessibility
void initialize() void initialize()
{ {
QJNIObjectPrivate::callStaticMethod<void>(QtAndroid::applicationClass(), QJniObject::callStaticMethod<void>(QtAndroid::applicationClass(),
"initializeAccessibility"); "initializeAccessibility");
} }

View File

@ -39,7 +39,8 @@
#include "androidjniclipboard.h" #include "androidjniclipboard.h"
#include <QtCore/QUrl> #include <QtCore/QUrl>
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniObject>
#include <QtCore/QJniEnvironment>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -55,9 +56,9 @@ namespace QtAndroidClipboard
void setClipboardManager(QAndroidPlatformClipboard *manager) void setClipboardManager(QAndroidPlatformClipboard *manager)
{ {
m_manager = manager; m_manager = manager;
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "registerClipboardManager"); QJniObject::callStaticMethod<void>(applicationClass(), "registerClipboardManager");
jclass appClass = QtAndroid::applicationClass(); jclass appClass = QtAndroid::applicationClass();
QJNIEnvironmentPrivate env; QJniEnvironment env;
if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
__android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
return; return;
@ -65,29 +66,30 @@ namespace QtAndroidClipboard
} }
void clearClipboardData() void clearClipboardData()
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "clearClipData"); QJniObject::callStaticMethod<void>(applicationClass(), "clearClipData");
} }
void setClipboardMimeData(QMimeData *data) void setClipboardMimeData(QMimeData *data)
{ {
clearClipboardData(); clearClipboardData();
if (data->hasText()) { if (data->hasText()) {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), QJniObject::callStaticMethod<void>(applicationClass(),
"setClipboardText", "(Ljava/lang/String;)V", "setClipboardText", "(Ljava/lang/String;)V",
QJNIObjectPrivate::fromString(data->text()).object()); QJniObject::fromString(data->text()).object());
} }
if (data->hasHtml()) { if (data->hasHtml()) {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), QJniObject::callStaticMethod<void>(applicationClass(),
"setClipboardHtml", "setClipboardHtml",
"(Ljava/lang/String;Ljava/lang/String;)V", "(Ljava/lang/String;Ljava/lang/String;)V",
QJNIObjectPrivate::fromString(data->text()).object(), QJniObject::fromString(data->text()).object(),
QJNIObjectPrivate::fromString(data->html()).object()); QJniObject::fromString(data->html()).object());
} }
if (data->hasUrls()) { if (data->hasUrls()) {
QList<QUrl> urls = data->urls(); QList<QUrl> urls = data->urls();
for (const auto &u : qAsConst(urls)) { for (const auto &u : qAsConst(urls)) {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "setClipboardUri", QJniObject::callStaticMethod<void>(applicationClass(),
"setClipboardUri",
"(Ljava/lang/String;)V", "(Ljava/lang/String;)V",
QJNIObjectPrivate::fromString(u.toEncoded()).object()); QJniObject::fromString(u.toEncoded()).object());
} }
} }
} }
@ -95,28 +97,28 @@ namespace QtAndroidClipboard
QMimeData *getClipboardMimeData() QMimeData *getClipboardMimeData()
{ {
QMimeData *data = new QMimeData; QMimeData *data = new QMimeData;
if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardText")) { if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardText")) {
data->setText(QJNIObjectPrivate::callStaticObjectMethod(applicationClass(), data->setText(QJniObject::callStaticObjectMethod(applicationClass(),
"getClipboardText", "getClipboardText",
"()Ljava/lang/String;").toString()); "()Ljava/lang/String;").toString());
} }
if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardHtml")) { if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardHtml")) {
data->setHtml(QJNIObjectPrivate::callStaticObjectMethod(applicationClass(), data->setHtml(QJniObject::callStaticObjectMethod(applicationClass(),
"getClipboardHtml", "getClipboardHtml",
"()Ljava/lang/String;").toString()); "()Ljava/lang/String;").toString());
} }
if (QJNIObjectPrivate::callStaticMethod<jboolean>(applicationClass(), "hasClipboardUri")) { if (QJniObject::callStaticMethod<jboolean>(applicationClass(), "hasClipboardUri")) {
QJNIObjectPrivate uris = QJNIObjectPrivate::callStaticObjectMethod(applicationClass(), QJniObject uris = QJniObject::callStaticObjectMethod(applicationClass(),
"getClipboardUris", "getClipboardUris",
"()[Ljava/lang/String;"); "()[Ljava/lang/String;");
if (uris.isValid()) { if (uris.isValid()) {
QList<QUrl> urls; QList<QUrl> urls;
QJNIEnvironmentPrivate env; QJniEnvironment env;
jobjectArray juris = static_cast<jobjectArray>(uris.object()); jobjectArray juris = static_cast<jobjectArray>(uris.object());
const jint nUris = env->GetArrayLength(juris); const jint nUris = env->GetArrayLength(juris);
urls.reserve(static_cast<int>(nUris)); urls.reserve(static_cast<int>(nUris));
for (int i = 0; i < nUris; ++i) for (int i = 0; i < nUris; ++i)
urls << QUrl(QJNIObjectPrivate(env->GetObjectArrayElement(juris, i)).toString()); urls << QUrl(QJniObject(env->GetObjectArrayElement(juris, i)).toString());
data->setUrls(urls); data->setUrls(urls);
} }
} }

View File

@ -49,7 +49,6 @@
#include <QPointer> #include <QPointer>
#include <QGuiApplication> #include <QGuiApplication>
#include <QDebug>
#include <QtMath> #include <QtMath>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -71,7 +70,7 @@ namespace QtAndroidInput
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd; qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd;
#endif #endif
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), QJniObject::callStaticMethod<void>(applicationClass(),
"updateSelection", "updateSelection",
"(IIII)V", "(IIII)V",
selStart, selStart,
@ -82,7 +81,7 @@ namespace QtAndroidInput
void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType) void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), QJniObject::callStaticMethod<void>(applicationClass(),
"showSoftwareKeyboard", "showSoftwareKeyboard",
"(IIIIII)V", "(IIIIII)V",
left, left,
@ -90,8 +89,7 @@ namespace QtAndroidInput
width, width,
height, height,
inputHints, inputHints,
enterKeyType enterKeyType);
);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType; qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
#endif #endif
@ -99,7 +97,7 @@ namespace QtAndroidInput
void resetSoftwareKeyboard() void resetSoftwareKeyboard()
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "resetSoftwareKeyboard"); QJniObject::callStaticMethod<void>(applicationClass(), "resetSoftwareKeyboard");
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ RESETSOFTWAREKEYBOARD"); qDebug("@@@ RESETSOFTWAREKEYBOARD");
#endif #endif
@ -107,7 +105,7 @@ namespace QtAndroidInput
void hideSoftwareKeyboard() void hideSoftwareKeyboard()
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "hideSoftwareKeyboard"); QJniObject::callStaticMethod<void>(applicationClass(), "hideSoftwareKeyboard");
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ HIDESOFTWAREKEYBOARD"); qDebug("@@@ HIDESOFTWAREKEYBOARD");
#endif #endif
@ -125,7 +123,7 @@ namespace QtAndroidInput
void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl) void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIIIIZ)V", QJniObject::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIIIIZ)V",
mode, editMenuPos.x(), editMenuPos.y(), editButtons, mode, editMenuPos.x(), editMenuPos.y(), editButtons,
cursor.x(), cursor.y(), cursor.x(), cursor.y(),
anchor.x(), anchor.y(), rtl); anchor.x(), anchor.y(), rtl);

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> ** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -40,30 +40,30 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
#include <qplugin.h> #include <qplugin.h>
#include <qdebug.h> #include <semaphore.h>
#include "androidjnimain.h"
#include "androidjniaccessibility.h"
#include "androidjniinput.h"
#include "androidjniclipboard.h"
#include "androidjnimenu.h"
#include "androidcontentfileengine.h" #include "androidcontentfileengine.h"
#include "androiddeadlockprotector.h" #include "androiddeadlockprotector.h"
#include "androidjniaccessibility.h"
#include "androidjniclipboard.h"
#include "androidjniinput.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
#include "qandroidassetsfileenginehandler.h"
#include "qandroideventdispatcher.h"
#include "qandroidplatformdialoghelpers.h" #include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h" #include "qandroidplatformintegration.h"
#include "qandroidassetsfileenginehandler.h"
#include <android/bitmap.h>
#include <android/asset_manager_jni.h>
#include "qandroideventdispatcher.h"
#include <android/api-level.h> #include <android/api-level.h>
#include <android/asset_manager_jni.h>
#include <android/bitmap.h>
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/qjnienvironment.h>
#include <QtCore/qjniobject.h>
#include <QtCore/qresource.h> #include <QtCore/qresource.h>
#include <QtCore/qthread.h> #include <QtCore/qthread.h>
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/private/qjni_p.h>
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/private/qhighdpiscaling_p.h>
@ -205,22 +205,22 @@ namespace QtAndroid
void setSystemUiVisibility(SystemUiVisibility uiVisibility) void setSystemUiVisibility(SystemUiVisibility uiVisibility)
{ {
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility)); QJniObject::callStaticMethod<void>(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility));
} }
void notifyAccessibilityLocationChange() void notifyAccessibilityLocationChange()
{ {
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyAccessibilityLocationChange"); QJniObject::callStaticMethod<void>(m_applicationClass, "notifyAccessibilityLocationChange");
} }
void notifyObjectHide(uint accessibilityObjectId) void notifyObjectHide(uint accessibilityObjectId)
{ {
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyObjectHide","(I)V", accessibilityObjectId); QJniObject::callStaticMethod<void>(m_applicationClass, "notifyObjectHide","(I)V", accessibilityObjectId);
} }
void notifyObjectFocus(uint accessibilityObjectId) void notifyObjectFocus(uint accessibilityObjectId)
{ {
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "notifyObjectFocus","(I)V", accessibilityObjectId); QJniObject::callStaticMethod<void>(m_applicationClass, "notifyObjectFocus","(I)V", accessibilityObjectId);
} }
jobject createBitmap(QImage img, JNIEnv *env) jobject createBitmap(QImage img, JNIEnv *env)
@ -311,15 +311,15 @@ namespace QtAndroid
QString deviceName() QString deviceName()
{ {
QString manufacturer = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString(); QString manufacturer = QJniObject::getStaticObjectField("android/os/Build", "MANUFACTURER", "Ljava/lang/String;").toString();
QString model = QJNIObjectPrivate::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString(); QString model = QJniObject::getStaticObjectField("android/os/Build", "MODEL", "Ljava/lang/String;").toString();
return manufacturer + QLatin1Char(' ') + model; return manufacturer + QLatin1Char(' ') + model;
} }
int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth) int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth)
{ {
QJNIEnvironmentPrivate env; QJniEnvironment env;
if (!env) if (!env)
return -1; return -1;
@ -355,7 +355,7 @@ namespace QtAndroid
if (!geometry.isNull()) if (!geometry.isNull())
geometry.getRect(&x, &y, &w, &h); geometry.getRect(&x, &y, &w, &h);
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, QJniObject::callStaticMethod<void>(m_applicationClass,
"insertNativeView", "insertNativeView",
"(ILandroid/view/View;IIII)V", "(ILandroid/view/View;IIII)V",
surfaceId, surfaceId,
@ -370,7 +370,7 @@ namespace QtAndroid
void setViewVisibility(jobject view, bool visible) void setViewVisibility(jobject view, bool visible)
{ {
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, QJniObject::callStaticMethod<void>(m_applicationClass,
"setViewVisibility", "setViewVisibility",
"(Landroid/view/View;Z)V", "(Landroid/view/View;Z)V",
view, view,
@ -382,7 +382,7 @@ namespace QtAndroid
if (surfaceId == -1) if (surfaceId == -1)
return; return;
QJNIEnvironmentPrivate env; QJniEnvironment env;
if (!env) if (!env)
return; return;
jint x = 0, y = 0, w = -1, h = -1; jint x = 0, y = 0, w = -1, h = -1;
@ -411,7 +411,7 @@ namespace QtAndroid
m_surfaces.erase(it); m_surfaces.erase(it);
} }
QJNIEnvironmentPrivate env; QJniEnvironment env;
if (env) if (env)
env->CallStaticVoidMethod(m_applicationClass, env->CallStaticVoidMethod(m_applicationClass,
m_destroySurfaceMethodID, m_destroySurfaceMethodID,
@ -423,7 +423,7 @@ namespace QtAndroid
if (surfaceId == -1) if (surfaceId == -1)
return; return;
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, QJniObject::callStaticMethod<void>(m_applicationClass,
"bringChildToFront", "bringChildToFront",
"(I)V", "(I)V",
surfaceId); surfaceId);
@ -434,7 +434,7 @@ namespace QtAndroid
if (surfaceId == -1) if (surfaceId == -1)
return; return;
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, QJniObject::callStaticMethod<void>(m_applicationClass,
"bringChildToBack", "bringChildToBack",
"(I)V", "(I)V",
surfaceId); surfaceId);
@ -550,7 +550,7 @@ static jboolean startQtApplication(JNIEnv */*env*/, jclass /*clazz*/)
if (m_applicationClass) { if (m_applicationClass) {
qWarning("exit app 0"); qWarning("exit app 0");
QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "quitApp", "()V"); QJniObject::callStaticMethod<void>(m_applicationClass, "quitApp", "()V");
} }
sem_post(&m_terminateSemaphore); sem_post(&m_terminateSemaphore);

View File

@ -37,10 +37,10 @@
** **
****************************************************************************/ ****************************************************************************/
#include "androidjnimenu.h"
#include "androidjnimain.h" #include "androidjnimain.h"
#include "qandroidplatformmenubar.h" #include "androidjnimenu.h"
#include "qandroidplatformmenu.h" #include "qandroidplatformmenu.h"
#include "qandroidplatformmenubar.h"
#include "qandroidplatformmenuitem.h" #include "qandroidplatformmenuitem.h"
#include <QMutex> #include <QMutex>
@ -50,7 +50,7 @@
#include <QSet> #include <QSet>
#include <QWindow> #include <QWindow>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -82,12 +82,12 @@ namespace QtAndroidMenu
void resetMenuBar() void resetMenuBar()
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "resetOptionsMenu"); QJniObject::callStaticMethod<void>(applicationClass(), "resetOptionsMenu");
} }
void openOptionsMenu() void openOptionsMenu()
{ {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "openOptionsMenu"); QJniObject::callStaticMethod<void>(applicationClass(), "openOptionsMenu");
} }
void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env) void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env)
@ -104,13 +104,14 @@ namespace QtAndroidMenu
{ {
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (visibleMenu == menu) { if (visibleMenu == menu) {
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "closeContextMenu"); QJniObject::callStaticMethod<void>(applicationClass(), "closeContextMenu");
pendingContextMenus.clear(); pendingContextMenus.clear();
} else { } else {
pendingContextMenus.removeOne(menu); pendingContextMenus.removeOne(menu);
} }
} }
// FIXME
void syncMenu(QAndroidPlatformMenu */*menu*/) void syncMenu(QAndroidPlatformMenu */*menu*/)
{ {
// QMutexLocker lock(&visibleMenuMutex); // QMutexLocker lock(&visibleMenuMutex);

View File

@ -39,10 +39,12 @@
#include <jni.h> #include <QtCore/QJniEnvironment>
#include <alloca.h>
#include <android/log.h> #include <android/log.h>
#include <extract.h> #include <extract.h>
#include <alloca.h> #include <jni.h>
#include <stdlib.h> #include <stdlib.h>
#define LOG_TAG "extractSyleInfo" #define LOG_TAG "extractSyleInfo"
@ -133,12 +135,15 @@ Java_org_qtproject_qt_android_ExtractStyle_extractChunkInfo20(JNIEnv *env, jobje
env->GetByteArrayRegion(chunkObj, 0, chunkSize, env->GetByteArrayRegion(chunkObj, 0, chunkSize,
reinterpret_cast<jbyte*>(storage)); reinterpret_cast<jbyte*>(storage));
if (!env->ExceptionCheck()) if (QJniEnvironment::exceptionCheckAndClear(env))
return Java_org_qtproject_qt_android_ExtractStyle_extractNativeChunkInfo20(env, obj,
long(storage));
else
env->ExceptionClear();
return 0; return 0;
jintArray res = Java_org_qtproject_qt_android_ExtractStyle_extractNativeChunkInfo20(env, obj,
long(storage));
if (QJniEnvironment::exceptionCheckAndClear(env))
res = nullptr;
return res;
} }
static inline void fill9patchOffsets(Res_png_9patch20* patch) { static inline void fill9patchOffsets(Res_png_9patch20* patch) {

View File

@ -37,13 +37,15 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qandroidassetsfileenginehandler.h"
#include "androidjnimain.h" #include "androidjnimain.h"
#include "qandroidassetsfileenginehandler.h"
#include <optional> #include <optional>
#include <QCoreApplication> #include <QCoreApplication>
#include <QList> #include <QList>
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -139,16 +141,16 @@ public:
FolderIterator(const QString &path) FolderIterator(const QString &path)
: m_path(path) : m_path(path)
{ {
QJNIObjectPrivate files = QJNIObjectPrivate::callStaticObjectMethod(QtAndroid::applicationClass(), QJniObject files = QJniObject::callStaticObjectMethod(QtAndroid::applicationClass(),
"listAssetContent", "listAssetContent",
"(Landroid/content/res/AssetManager;Ljava/lang/String;)[Ljava/lang/String;", "(Landroid/content/res/AssetManager;Ljava/lang/String;)[Ljava/lang/String;",
QtAndroid::assets(), QJNIObjectPrivate::fromString(path).object()); QtAndroid::assets(), QJniObject::fromString(path).object());
if (files.isValid()) { if (files.isValid()) {
QJNIEnvironmentPrivate env; QJniEnvironment env;
jobjectArray jFiles = static_cast<jobjectArray>(files.object()); jobjectArray jFiles = static_cast<jobjectArray>(files.object());
const jint nFiles = env->GetArrayLength(jFiles); const jint nFiles = env->GetArrayLength(jFiles);
for (int i = 0; i < nFiles; ++i) { for (int i = 0; i < nFiles; ++i) {
AssetItem item{QJNIObjectPrivate::fromLocalRef(env->GetObjectArrayElement(jFiles, i)).toString()}; AssetItem item{QJniObject::fromLocalRef(env->GetObjectArrayElement(jFiles, i)).toString()};
insert(std::upper_bound(begin(), end(), item, [](const auto &a, const auto &b){ insert(std::upper_bound(begin(), end(), item, [](const auto &a, const auto &b){
return a.name < b.name; return a.name < b.name;
}), item); }), item);

View File

@ -41,26 +41,24 @@
#include <android/log.h> #include <android/log.h>
#include "qandroidinputcontext.h"
#include "androidjnimain.h"
#include "androidjniinput.h"
#include "qandroideventdispatcher.h"
#include "androiddeadlockprotector.h" #include "androiddeadlockprotector.h"
#include "androidjniinput.h"
#include "androidjnimain.h"
#include "qandroideventdispatcher.h"
#include "qandroidinputcontext.h"
#include "qandroidplatformintegration.h" #include "qandroidplatformintegration.h"
#include <QDebug>
#include <QTextBoundaryFinder>
#include <QTextCharFormat>
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
#include <private/qhighdpiscaling_p.h>
#include <qevent.h> #include <qevent.h>
#include <qguiapplication.h> #include <qguiapplication.h>
#include <qinputmethod.h>
#include <qsharedpointer.h> #include <qsharedpointer.h>
#include <qthread.h> #include <qthread.h>
#include <qinputmethod.h>
#include <qwindow.h> #include <qwindow.h>
#include <QtCore/private/qjni_p.h>
#include <private/qhighdpiscaling_p.h>
#include <QTextCharFormat>
#include <QTextBoundaryFinder>
#include <QDebug>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -434,7 +432,8 @@ QAndroidInputContext::QAndroidInputContext()
, m_batchEditNestingLevel(0) , m_batchEditNestingLevel(0)
, m_focusObject(0) , m_focusObject(0)
{ {
jclass clazz = QJNIEnvironmentPrivate::findClass(QtNativeInputConnectionClassName); QJniEnvironment env;
jclass clazz = env.findClass(QtNativeInputConnectionClassName);
if (Q_UNLIKELY(!clazz)) { if (Q_UNLIKELY(!clazz)) {
qCritical() << "Native registration unable to find class '" qCritical() << "Native registration unable to find class '"
<< QtNativeInputConnectionClassName << QtNativeInputConnectionClassName
@ -442,7 +441,6 @@ QAndroidInputContext::QAndroidInputContext()
return; return;
} }
QJNIEnvironmentPrivate env;
if (Q_UNLIKELY(env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0)) { if (Q_UNLIKELY(env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0)) {
qCritical() << "RegisterNatives failed for '" qCritical() << "RegisterNatives failed for '"
<< QtNativeInputConnectionClassName << QtNativeInputConnectionClassName
@ -450,7 +448,7 @@ QAndroidInputContext::QAndroidInputContext()
return; return;
} }
clazz = QJNIEnvironmentPrivate::findClass(QtExtractedTextClassName); clazz = env.findClass(QtExtractedTextClassName);
if (Q_UNLIKELY(!clazz)) { if (Q_UNLIKELY(!clazz)) {
qCritical() << "Native registration unable to find class '" qCritical() << "Native registration unable to find class '"
<< QtExtractedTextClassName << QtExtractedTextClassName

View File

@ -90,19 +90,19 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
QString str = htmlText(opt->windowTitle()); QString str = htmlText(opt->windowTitle());
if (!str.isEmpty()) if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setTile", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); m_javaMessageDialog.callMethod<void>("setTile", "(Ljava/lang/String;)V", QJniObject::fromString(str).object());
str = htmlText(opt->text()); str = htmlText(opt->text());
if (!str.isEmpty()) if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); m_javaMessageDialog.callMethod<void>("setText", "(Ljava/lang/String;)V", QJniObject::fromString(str).object());
str = htmlText(opt->informativeText()); str = htmlText(opt->informativeText());
if (!str.isEmpty()) if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setInformativeText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); m_javaMessageDialog.callMethod<void>("setInformativeText", "(Ljava/lang/String;)V", QJniObject::fromString(str).object());
str = htmlText(opt->detailedText()); str = htmlText(opt->detailedText());
if (!str.isEmpty()) if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJniObject::fromString(str).object());
const int * currentLayout = buttonLayout(Qt::Horizontal, AndroidLayout); const int * currentLayout = buttonLayout(Qt::Horizontal, AndroidLayout);
while (*currentLayout != QPlatformDialogHelper::EOL) { while (*currentLayout != QPlatformDialogHelper::EOL) {
@ -123,7 +123,7 @@ void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDial
QString label = b.label; QString label = b.label;
label.remove(QChar('&')); label.remove(QChar('&'));
m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", b.id, m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", b.id,
QJNIObjectPrivate::fromString(label).object()); QJniObject::fromString(label).object());
} }
} }
@ -131,7 +131,7 @@ void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDial
StandardButton b = static_cast<StandardButton>(i); StandardButton b = static_cast<StandardButton>(i);
if (buttonRole(b) == role && (opt->standardButtons() & i)) { if (buttonRole(b) == role && (opt->standardButtons() & i)) {
const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b); const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b);
m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object()); m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJniObject::fromString(text).object());
} }
} }
} }
@ -183,7 +183,8 @@ static JNINativeMethod methods[] = {
bool registerNatives(JNIEnv *env) bool registerNatives(JNIEnv *env)
{ {
jclass clazz = QJNIEnvironmentPrivate::findClass(QtMessageHandlerHelperClassName, env); QJniEnvironment qenv;
jclass clazz = qenv.findClass(QtMessageHandlerHelperClassName);
if (!clazz) { if (!clazz) {
__android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt() __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt()
, QtMessageHandlerHelperClassName); , QtMessageHandlerHelperClassName);

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org> ** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -39,10 +40,13 @@
#ifndef QANDROIDPLATFORMDIALOGHELPERS_H #ifndef QANDROIDPLATFORMDIALOGHELPERS_H
#define QANDROIDPLATFORMDIALOGHELPERS_H #define QANDROIDPLATFORMDIALOGHELPERS_H
#include <jni.h> #include <jni.h>
#include <qpa/qplatformdialoghelper.h>
#include <QEventLoop> #include <QEventLoop>
#include <private/qjni_p.h> #include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
#include <qpa/qplatformdialoghelper.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -68,7 +72,7 @@ private:
private: private:
int m_buttonId; int m_buttonId;
QEventLoop m_loop; QEventLoop m_loop;
QJNIObjectPrivate m_javaMessageDialog; QJniObject m_javaMessageDialog;
bool m_shown; bool m_shown;
}; };

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB) ** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB)
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -40,10 +41,10 @@
#include "qandroidplatformfiledialoghelper.h" #include "qandroidplatformfiledialoghelper.h"
#include <androidjnimain.h> #include <androidjnimain.h>
#include <jni.h> #include <QtCore/QJniObject>
#include <QMimeType>
#include <QMimeDatabase> #include <QMimeDatabase>
#include <QMimeType>
#include <QRegularExpression> #include <QRegularExpression>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -71,9 +72,9 @@ bool QAndroidPlatformFileDialogHelper::handleActivityResult(jint requestCode, ji
return true; return true;
} }
const QJNIObjectPrivate intent = QJNIObjectPrivate::fromLocalRef(data); const QJniObject intent = QJniObject::fromLocalRef(data);
const QJNIObjectPrivate uri = intent.callObjectMethod("getData", "()Landroid/net/Uri;"); const QJniObject uri = intent.callObjectMethod("getData", "()Landroid/net/Uri;");
if (uri.isValid()) { if (uri.isValid()) {
takePersistableUriPermission(uri); takePersistableUriPermission(uri);
m_selectedFile.append(QUrl(uri.toString())); m_selectedFile.append(QUrl(uri.toString()));
@ -83,15 +84,15 @@ bool QAndroidPlatformFileDialogHelper::handleActivityResult(jint requestCode, ji
return true; return true;
} }
const QJNIObjectPrivate uriClipData = const QJniObject uriClipData =
intent.callObjectMethod("getClipData", "()Landroid/content/ClipData;"); intent.callObjectMethod("getClipData", "()Landroid/content/ClipData;");
if (uriClipData.isValid()) { if (uriClipData.isValid()) {
const int size = uriClipData.callMethod<jint>("getItemCount"); const int size = uriClipData.callMethod<jint>("getItemCount");
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
QJNIObjectPrivate item = uriClipData.callObjectMethod( QJniObject item = uriClipData.callObjectMethod(
"getItemAt", "(I)Landroid/content/ClipData$Item;", i); "getItemAt", "(I)Landroid/content/ClipData$Item;", i);
QJNIObjectPrivate itemUri = item.callObjectMethod("getUri", "()Landroid/net/Uri;"); QJniObject itemUri = item.callObjectMethod("getUri", "()Landroid/net/Uri;");
takePersistableUriPermission(itemUri); takePersistableUriPermission(itemUri);
m_selectedFile.append(itemUri.toString()); m_selectedFile.append(itemUri.toString());
} }
@ -102,17 +103,17 @@ bool QAndroidPlatformFileDialogHelper::handleActivityResult(jint requestCode, ji
return true; return true;
} }
void QAndroidPlatformFileDialogHelper::takePersistableUriPermission(const QJNIObjectPrivate &uri) void QAndroidPlatformFileDialogHelper::takePersistableUriPermission(const QJniObject &uri)
{ {
int modeFlags = QJNIObjectPrivate::getStaticField<jint>( int modeFlags = QJniObject::getStaticField<jint>(
JniIntentClass, "FLAG_GRANT_READ_URI_PERMISSION"); JniIntentClass, "FLAG_GRANT_READ_URI_PERMISSION");
if (options()->acceptMode() == QFileDialogOptions::AcceptSave) { if (options()->acceptMode() == QFileDialogOptions::AcceptSave) {
modeFlags |= QJNIObjectPrivate::getStaticField<jint>( modeFlags |= QJniObject::getStaticField<jint>(
JniIntentClass, "FLAG_GRANT_WRITE_URI_PERMISSION"); JniIntentClass, "FLAG_GRANT_WRITE_URI_PERMISSION");
} }
QJNIObjectPrivate contentResolver = m_activity.callObjectMethod( QJniObject contentResolver = m_activity.callObjectMethod(
"getContentResolver", "()Landroid/content/ContentResolver;"); "getContentResolver", "()Landroid/content/ContentResolver;");
contentResolver.callMethod<void>("takePersistableUriPermission", "(Landroid/net/Uri;I)V", contentResolver.callMethod<void>("takePersistableUriPermission", "(Landroid/net/Uri;I)V",
uri.object(), modeFlags); uri.object(), modeFlags);
@ -120,16 +121,16 @@ void QAndroidPlatformFileDialogHelper::takePersistableUriPermission(const QJNIOb
void QAndroidPlatformFileDialogHelper::setIntentTitle(const QString &title) void QAndroidPlatformFileDialogHelper::setIntentTitle(const QString &title)
{ {
const QJNIObjectPrivate extraTitle = QJNIObjectPrivate::getStaticObjectField( const QJniObject extraTitle = QJniObject::getStaticObjectField(
JniIntentClass, "EXTRA_TITLE", "Ljava/lang/String;"); JniIntentClass, "EXTRA_TITLE", "Ljava/lang/String;");
m_intent.callObjectMethod("putExtra", m_intent.callObjectMethod("putExtra",
"(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;",
extraTitle.object(), QJNIObjectPrivate::fromString(title).object()); extraTitle.object(), QJniObject::fromString(title).object());
} }
void QAndroidPlatformFileDialogHelper::setOpenableCategory() void QAndroidPlatformFileDialogHelper::setOpenableCategory()
{ {
const QJNIObjectPrivate CATEGORY_OPENABLE = QJNIObjectPrivate::getStaticObjectField( const QJniObject CATEGORY_OPENABLE = QJniObject::getStaticObjectField(
JniIntentClass, "CATEGORY_OPENABLE", "Ljava/lang/String;"); JniIntentClass, "CATEGORY_OPENABLE", "Ljava/lang/String;");
m_intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;", m_intent.callObjectMethod("addCategory", "(Ljava/lang/String;)Landroid/content/Intent;",
CATEGORY_OPENABLE.object()); CATEGORY_OPENABLE.object());
@ -137,7 +138,7 @@ void QAndroidPlatformFileDialogHelper::setOpenableCategory()
void QAndroidPlatformFileDialogHelper::setAllowMultipleSelections(bool allowMultiple) void QAndroidPlatformFileDialogHelper::setAllowMultipleSelections(bool allowMultiple)
{ {
const QJNIObjectPrivate allowMultipleSelections = QJNIObjectPrivate::getStaticObjectField( const QJniObject allowMultipleSelections = QJniObject::getStaticObjectField(
JniIntentClass, "EXTRA_ALLOW_MULTIPLE", "Ljava/lang/String;"); JniIntentClass, "EXTRA_ALLOW_MULTIPLE", "Ljava/lang/String;");
m_intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", m_intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;",
allowMultipleSelections.object(), allowMultiple); allowMultipleSelections.object(), allowMultiple);
@ -169,17 +170,17 @@ void QAndroidPlatformFileDialogHelper::setMimeTypes()
QString type = !mimeTypes.isEmpty() ? mimeTypes.at(0) : QLatin1String("*/*"); QString type = !mimeTypes.isEmpty() ? mimeTypes.at(0) : QLatin1String("*/*");
m_intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", m_intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;",
QJNIObjectPrivate::fromString(type).object()); QJniObject::fromString(type).object());
if (!mimeTypes.isEmpty()) { if (!mimeTypes.isEmpty()) {
const QJNIObjectPrivate extraMimeType = QJNIObjectPrivate::getStaticObjectField( const QJniObject extraMimeType = QJniObject::getStaticObjectField(
JniIntentClass, "EXTRA_MIME_TYPES", "Ljava/lang/String;"); JniIntentClass, "EXTRA_MIME_TYPES", "Ljava/lang/String;");
QJNIObjectPrivate mimeTypesArray = QJNIObjectPrivate::callStaticObjectMethod( QJniObject mimeTypesArray = QJniObject::callStaticObjectMethod(
"org/qtproject/qt/android/QtNative", "org/qtproject/qt/android/QtNative",
"getStringArray", "getStringArray",
"(Ljava/lang/String;)[Ljava/lang/String;", "(Ljava/lang/String;)[Ljava/lang/String;",
QJNIObjectPrivate::fromString(mimeTypes.join(",")).object()); QJniObject::fromString(mimeTypes.join(",")).object());
m_intent.callObjectMethod( m_intent.callObjectMethod(
"putExtra", "(Ljava/lang/String;[Ljava/lang/String;)Landroid/content/Intent;", "putExtra", "(Ljava/lang/String;[Ljava/lang/String;)Landroid/content/Intent;",
@ -187,11 +188,11 @@ void QAndroidPlatformFileDialogHelper::setMimeTypes()
} }
} }
QJNIObjectPrivate QAndroidPlatformFileDialogHelper::getFileDialogIntent(const QString &intentType) QJniObject QAndroidPlatformFileDialogHelper::getFileDialogIntent(const QString &intentType)
{ {
const QJNIObjectPrivate ACTION_OPEN_DOCUMENT = QJNIObjectPrivate::getStaticObjectField( const QJniObject ACTION_OPEN_DOCUMENT = QJniObject::getStaticObjectField(
JniIntentClass, intentType.toLatin1(), "Ljava/lang/String;"); JniIntentClass, intentType.toLatin1(), "Ljava/lang/String;");
return QJNIObjectPrivate(JniIntentClass, "(Ljava/lang/String;)V", return QJniObject(JniIntentClass, "(Ljava/lang/String;)V",
ACTION_OPEN_DOCUMENT.object()); ACTION_OPEN_DOCUMENT.object());
} }

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB) ** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB)
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -41,11 +42,11 @@
#define QANDROIDPLATFORMFILEDIALOGHELPER_H #define QANDROIDPLATFORMFILEDIALOGHELPER_H
#include <jni.h> #include <jni.h>
#include <QEventLoop> #include <QEventLoop>
#include <qpa/qplatformdialoghelper.h> #include <QtCore/QJniObject>
#include <QtCore/private/qjnihelpers_p.h> #include <QtCore/private/qjnihelpers_p.h>
#include <private/qjni_p.h> #include <qpa/qplatformdialoghelper.h>
#include <QEventLoop>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -73,8 +74,8 @@ public:
bool handleActivityResult(jint requestCode, jint resultCode, jobject data) override; bool handleActivityResult(jint requestCode, jint resultCode, jobject data) override;
private: private:
QJNIObjectPrivate getFileDialogIntent(const QString &intentType); QJniObject getFileDialogIntent(const QString &intentType);
void takePersistableUriPermission(const QJNIObjectPrivate &uri); void takePersistableUriPermission(const QJniObject &uri);
void setIntentTitle(const QString &title); void setIntentTitle(const QString &title);
void setOpenableCategory(); void setOpenableCategory();
void setAllowMultipleSelections(bool allowMultiple); void setAllowMultipleSelections(bool allowMultiple);
@ -82,8 +83,8 @@ private:
QEventLoop m_eventLoop; QEventLoop m_eventLoop;
QList<QUrl> m_selectedFile; QList<QUrl> m_selectedFile;
QJNIObjectPrivate m_intent; QJniObject m_intent;
const QJNIObjectPrivate m_activity; const QJniObject m_activity;
}; };
} }

View File

@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -42,7 +42,8 @@
#include "androidsurfaceclient.h" #include "androidsurfaceclient.h"
#include "qandroidplatformwindow.h" #include "qandroidplatformwindow.h"
#include <QtCore/private/qjni_p.h>
#include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -61,7 +62,7 @@ public:
private: private:
int m_surfaceId; int m_surfaceId;
QJNIObjectPrivate m_view; QJniObject m_view;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org> ** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -39,35 +40,34 @@
#include "qandroidplatformintegration.h" #include "qandroidplatformintegration.h"
#include <QtCore/private/qjni_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QGuiApplication>
#include <QOpenGLContext>
#include <QOffscreenSurface>
#include <QtGui/private/qoffscreensurface_p.h>
#include <QThread>
#include <QtGui/private/qeglpbuffer_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformoffscreensurface.h>
#include "androidjnimain.h"
#include "androidjniaccessibility.h" #include "androidjniaccessibility.h"
#include "androidjnimain.h"
#include "qabstracteventdispatcher.h" #include "qabstracteventdispatcher.h"
#include "qandroideventdispatcher.h" #include "qandroideventdispatcher.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformaccessibility.h" #include "qandroidplatformaccessibility.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformclipboard.h" #include "qandroidplatformclipboard.h"
#include "qandroidplatformforeignwindow.h"
#include "qandroidplatformfontdatabase.h" #include "qandroidplatformfontdatabase.h"
#include "qandroidplatformforeignwindow.h"
#include "qandroidplatformoffscreensurface.h"
#include "qandroidplatformopenglcontext.h" #include "qandroidplatformopenglcontext.h"
#include "qandroidplatformopenglwindow.h" #include "qandroidplatformopenglwindow.h"
#include "qandroidplatformscreen.h" #include "qandroidplatformscreen.h"
#include "qandroidplatformservices.h" #include "qandroidplatformservices.h"
#include "qandroidplatformtheme.h" #include "qandroidplatformtheme.h"
#include "qandroidsystemlocale.h" #include "qandroidsystemlocale.h"
#include "qandroidplatformoffscreensurface.h"
#include <QGuiApplication>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QThread>
#include <QtCore/QJniObject>
#include <QtGui/private/qeglpbuffer_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qoffscreensurface_p.h>
#include <qpa/qplatformoffscreensurface.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <jni.h> #include <jni.h>
@ -200,17 +200,17 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
m_accessibility = new QAndroidPlatformAccessibility(); m_accessibility = new QAndroidPlatformAccessibility();
#endif // QT_NO_ACCESSIBILITY #endif // QT_NO_ACCESSIBILITY
QJNIObjectPrivate javaActivity(QtAndroid::activity()); QJniObject javaActivity(QtAndroid::activity());
if (!javaActivity.isValid()) if (!javaActivity.isValid())
javaActivity = QtAndroid::service(); javaActivity = QtAndroid::service();
if (javaActivity.isValid()) { if (javaActivity.isValid()) {
QJNIObjectPrivate resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;");
QJNIObjectPrivate configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;"); QJniObject configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;");
int touchScreen = configuration.getField<jint>("touchscreen"); int touchScreen = configuration.getField<jint>("touchscreen");
if (touchScreen == QJNIObjectPrivate::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_FINGER") if (touchScreen == QJniObject::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_FINGER")
|| touchScreen == QJNIObjectPrivate::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_STYLUS")) || touchScreen == QJniObject::getStaticField<jint>("android/content/res/Configuration", "TOUCHSCREEN_STYLUS"))
{ {
m_touchDevice = new QPointingDevice; m_touchDevice = new QPointingDevice;
m_touchDevice->setType(QInputDevice::DeviceType::TouchScreen); m_touchDevice->setType(QInputDevice::DeviceType::TouchScreen);
@ -219,16 +219,16 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
| QPointingDevice::Capability::Pressure | QPointingDevice::Capability::Pressure
| QPointingDevice::Capability::NormalizedPosition); | QPointingDevice::Capability::NormalizedPosition);
QJNIObjectPrivate pm = javaActivity.callObjectMethod("getPackageManager", "()Landroid/content/pm/PackageManager;"); QJniObject pm = javaActivity.callObjectMethod("getPackageManager", "()Landroid/content/pm/PackageManager;");
Q_ASSERT(pm.isValid()); Q_ASSERT(pm.isValid());
if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z", if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
QJNIObjectPrivate::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND", "Ljava/lang/String;").object())) { QJniObject::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH_JAZZHAND", "Ljava/lang/String;").object())) {
m_touchDevice->setMaximumTouchPoints(10); m_touchDevice->setMaximumTouchPoints(10);
} else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z", } else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
QJNIObjectPrivate::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT", "Ljava/lang/String;").object())) { QJniObject::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT", "Ljava/lang/String;").object())) {
m_touchDevice->setMaximumTouchPoints(4); m_touchDevice->setMaximumTouchPoints(4);
} else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z", } else if (pm.callMethod<jboolean>("hasSystemFeature","(Ljava/lang/String;)Z",
QJNIObjectPrivate::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH", "Ljava/lang/String;").object())) { QJniObject::getStaticObjectField("android/content/pm/PackageManager", "FEATURE_TOUCHSCREEN_MULTITOUCH", "Ljava/lang/String;").object())) {
m_touchDevice->setMaximumTouchPoints(2); m_touchDevice->setMaximumTouchPoints(2);
} }
QWindowSystemInterface::registerInputDevice(m_touchDevice); QWindowSystemInterface::registerInputDevice(m_touchDevice);
@ -236,11 +236,14 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
auto contentResolver = javaActivity.callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;"); auto contentResolver = javaActivity.callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;");
Q_ASSERT(contentResolver.isValid()); Q_ASSERT(contentResolver.isValid());
QJNIObjectPrivate txtShowPassValue = QJNIObjectPrivate::callStaticObjectMethod("android/provider/Settings$System", QJniObject txtShowPassValue = QJniObject::callStaticObjectMethod(
"android/provider/Settings$System",
"getString", "getString",
"(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;", "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;",
contentResolver.object(), contentResolver.object(),
QJNIObjectPrivate::getStaticObjectField("android/provider/Settings$System", "TEXT_SHOW_PASSWORD", "Ljava/lang/String;").object()); QJniObject::getStaticObjectField("android/provider/Settings$System",
"TEXT_SHOW_PASSWORD",
"Ljava/lang/String;").object());
if (txtShowPassValue.isValid()) { if (txtShowPassValue.isValid()) {
bool ok = false; bool ok = false;
const int txtShowPass = txtShowPassValue.toString().toInt(&ok); const int txtShowPass = txtShowPassValue.toString().toInt(&ok);

View File

@ -1,6 +1,7 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org> ** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the plugins of the Qt Toolkit. ** This file is part of the plugins of the Qt Toolkit.
@ -37,10 +38,12 @@
** **
****************************************************************************/ ****************************************************************************/
#include "androidjnimenu.h"
#include "qandroidplatformmenu.h" #include "qandroidplatformmenu.h"
#include "qandroidplatformmenuitem.h" #include "qandroidplatformmenuitem.h"
#include "androidjnimenu.h"
#include <QtCore/private/qjni_p.h> #include <QtCore/qjnienvironment.h>
#include <QtCore/qjniobject.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -152,7 +155,7 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t
Q_UNUSED(parentWindow); Q_UNUSED(parentWindow);
Q_UNUSED(item); Q_UNUSED(item);
setVisible(true); setVisible(true);
QtAndroidMenu::showContextMenu(this, targetRect, QJNIEnvironmentPrivate()); QtAndroidMenu::showContextMenu(this, targetRect, QJniEnvironment());
} }
QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const

View File

@ -40,20 +40,20 @@
#include "qandroidplatformopenglwindow.h" #include "qandroidplatformopenglwindow.h"
#include "qandroidplatformscreen.h" #include "androiddeadlockprotector.h"
#include "androidjnimain.h" #include "androidjnimain.h"
#include "qandroideventdispatcher.h" #include "qandroideventdispatcher.h"
#include "androiddeadlockprotector.h" #include "qandroidplatformscreen.h"
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QtGui/private/qwindow_p.h> #include <QtGui/private/qwindow_p.h>
#include <QtGui/qguiapplication.h> #include <QtGui/qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformscreen.h>
#include <QtGui/private/qeglconvenience_p.h> #include <QtGui/private/qeglconvenience_p.h>
#include <android/native_window.h> #include <android/native_window.h>
#include <android/native_window_jni.h> #include <android/native_window_jni.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -175,9 +175,9 @@ void QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState
void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config) void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config)
{ {
clearEgl(); clearEgl();
QJNIEnvironmentPrivate env; QJniEnvironment env;
m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object()); m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object());
m_androidSurfaceObject = QJNIObjectPrivate(); m_androidSurfaceObject = QJniObject();
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_nativeWindow, NULL); m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_nativeWindow, NULL);
m_format = q_glFormatFromConfig(m_eglDisplay, config, window()->requestedFormat()); m_format = q_glFormatFromConfig(m_eglDisplay, config, window()->requestedFormat());
if (Q_UNLIKELY(m_eglSurface == EGL_NO_SURFACE)) { if (Q_UNLIKELY(m_eglSurface == EGL_NO_SURFACE)) {

View File

@ -41,13 +41,15 @@
#ifndef QANDROIDPLATFORMOPENGLWINDOW_H #ifndef QANDROIDPLATFORMOPENGLWINDOW_H
#define QANDROIDPLATFORMOPENGLWINDOW_H #define QANDROIDPLATFORMOPENGLWINDOW_H
#include <EGL/egl.h>
#include <QWaitCondition>
#include <QtCore/private/qjni_p.h>
#include "androidsurfaceclient.h" #include "androidsurfaceclient.h"
#include "qandroidplatformwindow.h" #include "qandroidplatformwindow.h"
#include <QWaitCondition>
#include <QtCore/qjnienvironment.h>
#include <QtCore/qjniobject.h>
#include <EGL/egl.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAndroidPlatformOpenGLWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient class QAndroidPlatformOpenGLWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient
@ -77,7 +79,7 @@ private:
EGLNativeWindowType m_nativeWindow = nullptr; EGLNativeWindowType m_nativeWindow = nullptr;
int m_nativeSurfaceId = -1; int m_nativeSurfaceId = -1;
QJNIObjectPrivate m_androidSurfaceObject; QJniObject m_androidSurfaceObject;
QWaitCondition m_surfaceWaitCondition; QWaitCondition m_surfaceWaitCondition;
QSurfaceFormat m_format; QSurfaceFormat m_format;
QRect m_oldGeometry; QRect m_oldGeometry;

View File

@ -41,14 +41,14 @@
#ifndef QANDROIDPLATFORMSCREEN_H #ifndef QANDROIDPLATFORMSCREEN_H
#define QANDROIDPLATFORMSCREEN_H #define QANDROIDPLATFORMSCREEN_H
#include <qpa/qplatformscreen.h> #include "androidsurfaceclient.h"
#include <QList> #include <QList>
#include <QPainter> #include <QPainter>
#include <QTimer> #include <QTimer>
#include <QWaitCondition> #include <QWaitCondition>
#include <QtCore/private/qjni_p.h> #include <QtCore/QJniObject>
#include <qpa/qplatformscreen.h>
#include "androidsurfaceclient.h"
#include <android/native_window.h> #include <android/native_window.h>

View File

@ -38,11 +38,12 @@
****************************************************************************/ ****************************************************************************/
#include "qandroidplatformservices.h" #include "qandroidplatformservices.h"
#include <QUrl>
#include <QFile>
#include <QDebug> #include <QDebug>
#include <QFile>
#include <QMimeDatabase> #include <QMimeDatabase>
#include <QtCore/private/qjni_p.h> #include <QUrl>
#include <QtCore/QJniObject>
#include <private/qjnihelpers_p.h> #include <private/qjnihelpers_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -66,9 +67,9 @@ bool QAndroidPlatformServices::openUrl(const QUrl &theUrl)
mime = mimeDb.mimeTypeForUrl(url).name(); mime = mimeDb.mimeTypeForUrl(url).name();
} }
QJNIObjectPrivate urlString = QJNIObjectPrivate::fromString(url.toString()); QJniObject urlString = QJniObject::fromString(url.toString());
QJNIObjectPrivate mimeString = QJNIObjectPrivate::fromString(mime); QJniObject mimeString = QJniObject::fromString(mime);
return QJNIObjectPrivate::callStaticMethod<jboolean>( return QJniObject::callStaticMethod<jboolean>(
QtAndroid::applicationClass(), "openURL", QtAndroid::applicationClass(), "openURL",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Z", "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Z",
QtAndroidPrivate::context(), urlString.object(), mimeString.object()); QtAndroidPrivate::context(), urlString.object(), mimeString.object());

View File

@ -37,15 +37,15 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qandroidplatformvulkanwindow.h" #include "androiddeadlockprotector.h"
#include "qandroidplatformscreen.h"
#include "androidjnimain.h" #include "androidjnimain.h"
#include "qandroideventdispatcher.h" #include "qandroideventdispatcher.h"
#include "androiddeadlockprotector.h" #include "qandroidplatformscreen.h"
#include "qandroidplatformvulkanwindow.h"
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformscreen.h> #include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <android/native_window.h> #include <android/native_window.h>
#include <android/native_window_jni.h> #include <android/native_window_jni.h>
@ -172,7 +172,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid()) if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
return &m_vkSurface; return &m_vkSurface;
QJNIEnvironmentPrivate env; QJniEnvironment env;
m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object()); m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object());
VkAndroidSurfaceCreateInfoKHR surfaceInfo; VkAndroidSurfaceCreateInfoKHR surfaceInfo;

View File

@ -46,13 +46,13 @@
#define VK_USE_PLATFORM_ANDROID_KHR #define VK_USE_PLATFORM_ANDROID_KHR
#include <QWaitCondition>
#include <QtCore/private/qjni_p.h>
#include "androidsurfaceclient.h" #include "androidsurfaceclient.h"
#include "qandroidplatformvulkaninstance.h"
#include "qandroidplatformwindow.h" #include "qandroidplatformwindow.h"
#include "qandroidplatformvulkaninstance.h" #include <QWaitCondition>
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -77,7 +77,7 @@ private:
int m_nativeSurfaceId; int m_nativeSurfaceId;
ANativeWindow *m_nativeWindow; ANativeWindow *m_nativeWindow;
QJNIObjectPrivate m_androidSurfaceObject; QJniObject m_androidSurfaceObject;
QWaitCondition m_surfaceWaitCondition; QWaitCondition m_surfaceWaitCondition;
QSurfaceFormat m_format; QSurfaceFormat m_format;
QRect m_oldGeometry; QRect m_oldGeometry;

View File

@ -37,14 +37,15 @@
** **
****************************************************************************/ ****************************************************************************/
#include "qandroidsystemlocale.h"
#include "androidjnimain.h" #include "androidjnimain.h"
#include <QtCore/private/qjni_p.h> #include "qandroidsystemlocale.h"
#include <QtCore/private/qjnihelpers_p.h>
#include "qdatetime.h" #include "qdatetime.h"
#include "qstringlist.h" #include "qstringlist.h"
#include "qvariant.h" #include "qvariant.h"
#include <QtCore/private/qjnihelpers_p.h>
#include <QtCore/QJniObject>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QAndroidSystemLocale::QAndroidSystemLocale() : m_locale(QLocale::C) QAndroidSystemLocale::QAndroidSystemLocale() : m_locale(QLocale::C)
@ -55,17 +56,17 @@ void QAndroidSystemLocale::getLocaleFromJava() const
{ {
QWriteLocker locker(&m_lock); QWriteLocker locker(&m_lock);
QJNIObjectPrivate javaLocaleObject; QJniObject javaLocaleObject;
QJNIObjectPrivate javaActivity(QtAndroid::activity()); QJniObject javaActivity(QtAndroid::activity());
if (!javaActivity.isValid()) if (!javaActivity.isValid())
javaActivity = QtAndroid::service(); javaActivity = QtAndroid::service();
if (javaActivity.isValid()) { if (javaActivity.isValid()) {
QJNIObjectPrivate resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;"); QJniObject resources = javaActivity.callObjectMethod("getResources", "()Landroid/content/res/Resources;");
QJNIObjectPrivate configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;"); QJniObject configuration = resources.callObjectMethod("getConfiguration", "()Landroid/content/res/Configuration;");
javaLocaleObject = configuration.getObjectField("locale", "Ljava/util/Locale;"); javaLocaleObject = configuration.getObjectField("locale", "Ljava/util/Locale;");
} else { } else {
javaLocaleObject = QJNIObjectPrivate::callStaticObjectMethod("java/util/Locale", "getDefault", "()Ljava/util/Locale;"); javaLocaleObject = QJniObject::callStaticObjectMethod("java/util/Locale", "getDefault", "()Ljava/util/Locale;");
} }
QString languageCode = javaLocaleObject.callObjectMethod("getLanguage", "()Ljava/lang/String;").toString(); QString languageCode = javaLocaleObject.callObjectMethod("getLanguage", "()Ljava/lang/String;").toString();
@ -165,8 +166,8 @@ QVariant QAndroidSystemLocale::query(QueryType type, QVariant in) const
Q_ASSERT_X(false, Q_FUNC_INFO, "This can't happen."); Q_ASSERT_X(false, Q_FUNC_INFO, "This can't happen.");
case UILanguages: { case UILanguages: {
if (QtAndroidPrivate::androidSdkVersion() >= 24) { if (QtAndroidPrivate::androidSdkVersion() >= 24) {
QJNIObjectPrivate localeListObject = QJniObject localeListObject =
QJNIObjectPrivate::callStaticObjectMethod("android/os/LocaleList", "getDefault", QJniObject::callStaticObjectMethod("android/os/LocaleList", "getDefault",
"()Landroid/os/LocaleList;"); "()Landroid/os/LocaleList;");
if (localeListObject.isValid()) { if (localeListObject.isValid()) {
QString lang = localeListObject.callObjectMethod("toLanguageTags", QString lang = localeListObject.callObjectMethod("toLanguageTags",

View File

@ -45,3 +45,7 @@ endif()
if(QT_FEATURE_private_tests) if(QT_FEATURE_private_tests)
add_subdirectory(qproperty) add_subdirectory(qproperty)
endif() endif()
if(ANDROID AND NOT ANDROID_EMBEDDED)
add_subdirectory(qjnienvironment)
add_subdirectory(qjniobject)
endif()

View File

@ -0,0 +1,8 @@
#####################################################################
## tst_qjnienvironment Test:
#####################################################################
qt_internal_add_test(tst_qjnienvironment
SOURCES
tst_qjnienvironment.cpp
)

View File

@ -0,0 +1,106 @@
/****************************************************************************
**
** 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$
**
****************************************************************************/
#include <QtCore/QJniEnvironment>
#include <QtTest/QtTest>
class tst_QJniEnvironment : public QObject
{
Q_OBJECT
private slots:
void jniEnv();
void javaVM();
};
void tst_QJniEnvironment::jniEnv()
{
QJniEnvironment env;
JavaVM *javaVM = env.javaVM();
QVERIFY(javaVM);
{
// JNI environment should now be attached to the current thread
JNIEnv *jni = 0;
QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
JNIEnv *e = env;
QVERIFY(e);
QCOMPARE(env->GetVersion(), JNI_VERSION_1_6);
// try to find an existing class
QVERIFY(env->FindClass("java/lang/Object"));
QVERIFY(!env->ExceptionCheck());
// try to find a nonexistent class
QVERIFY(!env->FindClass("this/doesnt/Exist"));
QVERIFY(env->ExceptionCheck());
env->ExceptionClear();
QVERIFY(env->FindClass("java/lang/Object"));
QVERIFY(!QJniEnvironment::exceptionCheckAndClear(env));
// try to find a nonexistent class
QVERIFY(!env->FindClass("this/doesnt/Exist"));
QVERIFY(QJniEnvironment::exceptionCheckAndClear(env));
// try to find an existing class with QJniEnvironment
QJniEnvironment env;
QVERIFY(env.findClass("java/lang/Object"));
// try to find a nonexistent class
QVERIFY(!env.findClass("this/doesnt/Exist"));
// clear exception with member function
QVERIFY(!env->FindClass("this/doesnt/Exist"));
QVERIFY(env.exceptionCheckAndClear());
}
// The env does not detach automatically, even if it goes out of scope. The only way it can
// be detached is if it's done explicitly, or if the thread we attached to gets killed (TLS clean-up).
JNIEnv *jni = nullptr;
QCOMPARE(javaVM->GetEnv((void**)&jni, JNI_VERSION_1_6), JNI_OK);
}
void tst_QJniEnvironment::javaVM()
{
QJniEnvironment env;
JavaVM *javaVM = env.javaVM();
QVERIFY(javaVM);
QCOMPARE(env.javaVM(), javaVM);
JavaVM *vm = 0;
QCOMPARE(env->GetJavaVM(&vm), JNI_OK);
QCOMPARE(env.javaVM(), vm);
}
QTEST_MAIN(tst_QJniEnvironment)
#include "tst_qjnienvironment.moc"

View File

@ -0,0 +1,16 @@
#####################################################################
## tst_qjniobject Test:
#####################################################################
qt_internal_add_test(tst_qjniobject
SOURCES
tst_qjniobject.cpp
)
if(ANDROID)
set_property(TARGET tst_qjniobject APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/testdata
)
# QTBUG-88840 # special case
qt_android_generate_deployment_settings(tst_qjniobject) # special case
endif()

View File

@ -0,0 +1,177 @@
/****************************************************************************
**
** 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 QtJniObjectTestClass
{
static final byte A_BYTE_VALUE = 127;
static final short A_SHORT_VALUE = 32767;
static final int A_INT_VALUE = 060701;
static final long A_LONG_VALUE = 060701;
static final float A_FLOAT_VALUE = 1.0f;
static final double A_DOUBLE_VALUE = 1.0;
static final boolean A_BOOLEAN_VALUE = true;
static final char A_CHAR_VALUE = 'Q';
static final String A_STRING_OBJECT = "TEST_DATA_STRING";
static final Class A_CLASS_OBJECT = QtJniObjectTestClass.class;
static final Object A_OBJECT_OBJECT = new QtJniObjectTestClass();
static final Throwable A_THROWABLE_OBJECT = new Throwable(A_STRING_OBJECT);
// --------------------------------------------------------------------------------------------
public static void staticVoidMethod() { return; }
public static void staticVoidMethodWithArgs(int a, boolean b, char c) { return; }
public void voidMethod() { return; }
public void voidMethodWithArgs(int a, boolean b, char c) { return; }
// --------------------------------------------------------------------------------------------
public static boolean staticBooleanMethod() { return A_BOOLEAN_VALUE; }
public static boolean staticBooleanMethodWithArgs(boolean a, boolean b, boolean c)
{ return staticBooleanMethod(); }
public boolean booleanMethod() { return staticBooleanMethod(); }
public boolean booleanMethodWithArgs(boolean a, boolean b, boolean c)
{ return staticBooleanMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static byte staticByteMethod() { return A_BYTE_VALUE; }
public static byte staticByteMethodWithArgs(byte a, byte b, byte c) { return staticByteMethod(); }
public byte byteMethod() { return staticByteMethod(); }
public byte byteMethodWithArgs(byte a, byte b, byte c)
{ return staticByteMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static char staticCharMethod() { return A_CHAR_VALUE; }
public static char staticCharMethodWithArgs(char a, char b, char c) { return staticCharMethod(); }
public char charMethod() { return staticCharMethod(); }
public char charMethodWithArgs(char a, char b, char c)
{ return staticCharMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static short staticShortMethod() { return A_SHORT_VALUE; }
public static short staticShortMethodWithArgs(short a, short b, short c) { return staticShortMethod(); }
public short shortMethod() { return staticShortMethod(); }
public short shortMethodWithArgs(short a, short b, short c)
{ return staticShortMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static int staticIntMethod() { return A_INT_VALUE; }
public static int staticIntMethodWithArgs(int a, int b, int c) { return staticIntMethod(); }
public int intMethod() { return staticIntMethod(); }
public int intMethodWithArgs(int a, int b, int c) { return staticIntMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static long staticLongMethod() { return A_LONG_VALUE; }
public static long staticLongMethodWithArgs(long a, long b, long c) { return staticLongMethod(); }
public long longMethod() { return staticLongMethod(); }
public long longMethodWithArgs(long a, long b, long c)
{ return staticLongMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static float staticFloatMethod() { return A_FLOAT_VALUE; }
public static float staticFloatMethodWithArgs(float a, float b, float c) { return staticFloatMethod(); }
public float floatMethod() { return staticFloatMethod(); }
public float floatMethodWithArgs(float a, float b, float c)
{ return staticFloatMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static double staticDoubleMethod() { return A_DOUBLE_VALUE; }
public static double staticDoubleMethodWithArgs(double a, double b, double c)
{ return staticDoubleMethod(); }
public double doubleMethod() { return staticDoubleMethod(); }
public double doubleMethodWithArgs(double a, double b, double c)
{ return staticDoubleMethodWithArgs(a, b, c); }
// --------------------------------------------------------------------------------------------
public static Object staticObjectMethod() { return A_OBJECT_OBJECT; }
public Object objectMethod() { return staticObjectMethod(); }
// --------------------------------------------------------------------------------------------
public static Class staticClassMethod() { return A_CLASS_OBJECT; }
public Class classMethod() { return staticClassMethod(); }
// --------------------------------------------------------------------------------------------
public static String staticStringMethod() { return A_STRING_OBJECT; }
public String stringMethod() { return staticStringMethod(); }
// --------------------------------------------------------------------------------------------
public static Throwable staticThrowableMethod() { return A_THROWABLE_OBJECT; }
public Throwable throwableMethod() { return staticThrowableMethod(); }
// --------------------------------------------------------------------------------------------
public static Object[] staticObjectArrayMethod()
{ Object[] array = { new Object(), new Object(), new Object() }; return array; }
public Object[] objectArrayMethod() { return staticObjectArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static boolean[] staticBooleanArrayMethod()
{ boolean[] array = { true, true, true }; return array; }
public boolean[] booleanArrayMethod() { return staticBooleanArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static byte[] staticByteArrayMethod()
{ byte[] array = { 'a', 'b', 'c' }; return array; }
public byte[] byteArrayMethod() { return staticByteArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static char[] staticCharArrayMethod()
{ char[] array = { 'a', 'b', 'c' }; return array; }
public char[] charArrayMethod() { return staticCharArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static short[] staticShortArrayMethod() { short[] array = { 3, 2, 1 }; return array; }
public short[] shortArrayMethod() { return staticShortArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static int[] staticIntArrayMethod() { int[] array = { 3, 2, 1 }; return array; }
public int[] intArrayMethod() { return staticIntArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static long[] staticLongArrayMethod()
{ long[] array = { 3, 2, 1 }; return array; }
public long[] longArrayMethod() { return staticLongArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static float[] staticFloatArrayMethod()
{ float[] array = { 1.0f, 2.0f, 3.0f }; return array; }
public float[] floatArrayMethod() { return staticFloatArrayMethod(); }
// --------------------------------------------------------------------------------------------
public static double[] staticDoubleArrayMethod()
{ double[] array = { 3.0, 2.0, 1.0 }; return array; }
public double[] doubleArrayMethod() { return staticDoubleArrayMethod(); }
}

File diff suppressed because it is too large Load Diff