Remove old Android code that have now has alternative public APIs
* Remove the old qjni private APIs. * Remove the Android permission private APIs. * Remove runOnAndroidThread(). Pick-to: 6.2 Change-Id: I37ba8b4cb87a099f067e2e0b6744b8d01a0f9bbc Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
182afbe335
commit
03eb44394e
@ -994,7 +994,6 @@ qt_internal_extend_target(Core CONDITION ANDROID AND NOT ANDROID_EMBEDDED
|
|||||||
io/qstandardpaths_android.cpp
|
io/qstandardpaths_android.cpp
|
||||||
kernel/qcoreapplication_android.cpp
|
kernel/qcoreapplication_android.cpp
|
||||||
io/qstorageinfo_unix.cpp
|
io/qstorageinfo_unix.cpp
|
||||||
kernel/qjni.cpp kernel/qjni_p.h
|
|
||||||
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
|
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
|
||||||
kernel/qjniobject.cpp kernel/qjniobject.h
|
kernel/qjniobject.cpp kernel/qjniobject.h
|
||||||
kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
|
kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,292 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 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$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
// FIXME: Remove this once the JNI API is used by other modules.
|
|
||||||
|
|
||||||
#ifndef QJNI_P_H
|
|
||||||
#define QJNI_P_H
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
#include <QtCore/private/qglobal_p.h>
|
|
||||||
#include <QtCore/qsharedpointer.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
struct Q_CORE_EXPORT QJNILocalRefDeleter
|
|
||||||
{
|
|
||||||
static void cleanup(jobject obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
// To simplify this we only define it for jobjects.
|
|
||||||
typedef QScopedPointer<_jobject, QJNILocalRefDeleter> QJNIScopedLocalRef;
|
|
||||||
|
|
||||||
class Q_CORE_EXPORT QJNIEnvironmentPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QJNIEnvironmentPrivate();
|
|
||||||
~QJNIEnvironmentPrivate();
|
|
||||||
JNIEnv *operator->();
|
|
||||||
operator JNIEnv *() const;
|
|
||||||
static jclass findClass(const char *className, JNIEnv *env = nullptr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class QAndroidJniEnvironment;
|
|
||||||
Q_DISABLE_COPY_MOVE(QJNIEnvironmentPrivate)
|
|
||||||
JNIEnv *jniEnv;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Q_CORE_EXPORT QJNIObjectData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QJNIObjectData();
|
|
||||||
~QJNIObjectData();
|
|
||||||
jobject m_jobject;
|
|
||||||
jclass m_jclass;
|
|
||||||
bool m_own_jclass;
|
|
||||||
QByteArray m_className;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Q_CORE_EXPORT QJNIObjectPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QJNIObjectPrivate();
|
|
||||||
explicit QJNIObjectPrivate(const char *className);
|
|
||||||
QJNIObjectPrivate(const char *className, const char *sig, ...);
|
|
||||||
explicit QJNIObjectPrivate(jclass clazz);
|
|
||||||
QJNIObjectPrivate(jclass clazz, const char *sig, ...);
|
|
||||||
// In most cases you should never call this function with a local ref. unless you intend
|
|
||||||
// to manage the local ref. yourself.
|
|
||||||
// NOTE: see fromLocalRef() for converting a local ref. to QJNIObjectPrivate.
|
|
||||||
explicit QJNIObjectPrivate(jobject globalRef);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T callMethod(const char *methodName,
|
|
||||||
const char *sig,
|
|
||||||
...) const;
|
|
||||||
template <typename T>
|
|
||||||
T callMethod(const char *methodName) const;
|
|
||||||
template <typename T>
|
|
||||||
QJNIObjectPrivate callObjectMethod(const char *methodName) const;
|
|
||||||
QJNIObjectPrivate 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);
|
|
||||||
static QJNIObjectPrivate callStaticObjectMethod(const char *className,
|
|
||||||
const char *methodName,
|
|
||||||
const char *sig, ...);
|
|
||||||
|
|
||||||
static QJNIObjectPrivate 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);
|
|
||||||
|
|
||||||
QJNIObjectPrivate getObjectField(const char *fieldName, const char *sig) const;
|
|
||||||
static QJNIObjectPrivate getStaticObjectField(const char *className,
|
|
||||||
const char *fieldName,
|
|
||||||
const char *sig);
|
|
||||||
static QJNIObjectPrivate 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 QJNIObjectPrivate fromString(const QString &string);
|
|
||||||
QString toString() const;
|
|
||||||
|
|
||||||
static bool isClassAvailable(const char *className);
|
|
||||||
bool isValid() const;
|
|
||||||
jobject object() const { return d->m_jobject; }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline QJNIObjectPrivate &operator=(T o)
|
|
||||||
{
|
|
||||||
jobject jobj = static_cast<jobject>(o);
|
|
||||||
if (!isSameObject(jobj)) {
|
|
||||||
d = QSharedPointer<QJNIObjectData>::create();
|
|
||||||
if (jobj) {
|
|
||||||
QJNIEnvironmentPrivate env;
|
|
||||||
d->m_jobject = env->NewGlobalRef(jobj);
|
|
||||||
jclass objectClass = env->GetObjectClass(jobj);
|
|
||||||
d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass));
|
|
||||||
env->DeleteLocalRef(objectClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function takes ownership of the jobject and releases the local ref. before returning.
|
|
||||||
static QJNIObjectPrivate fromLocalRef(jobject lref);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class QAndroidJniObject;
|
|
||||||
|
|
||||||
struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; };
|
|
||||||
|
|
||||||
QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args);
|
|
||||||
QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T callMethodV(const char *methodName,
|
|
||||||
const char *sig,
|
|
||||||
va_list args) const;
|
|
||||||
QJNIObjectPrivate 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 QJNIObjectPrivate callStaticObjectMethodV(const char *className,
|
|
||||||
const char *methodName,
|
|
||||||
const char *sig,
|
|
||||||
va_list args);
|
|
||||||
|
|
||||||
static QJNIObjectPrivate callStaticObjectMethodV(jclass clazz,
|
|
||||||
const char *methodName,
|
|
||||||
const char *sig,
|
|
||||||
va_list args);
|
|
||||||
|
|
||||||
bool isSameObject(jobject obj) const;
|
|
||||||
bool isSameObject(const QJNIObjectPrivate &other) const;
|
|
||||||
|
|
||||||
friend bool operator==(const QJNIObjectPrivate &, const QJNIObjectPrivate &);
|
|
||||||
friend bool operator!=(const QJNIObjectPrivate&, const QJNIObjectPrivate&);
|
|
||||||
template <typename T> friend bool operator!=(const QJNIObjectPrivate&, T);
|
|
||||||
template <typename T> friend bool operator==(const QJNIObjectPrivate&, T);
|
|
||||||
template <typename T> friend bool operator!=(T, const QJNIObjectPrivate&);
|
|
||||||
template <typename T> friend bool operator==(T, const QJNIObjectPrivate&);
|
|
||||||
|
|
||||||
QSharedPointer<QJNIObjectData> d;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator==(const QJNIObjectPrivate &obj1, const QJNIObjectPrivate &obj2)
|
|
||||||
{
|
|
||||||
return obj1.isSameObject(obj2);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(const QJNIObjectPrivate &obj1, const QJNIObjectPrivate &obj2)
|
|
||||||
{
|
|
||||||
return !obj1.isSameObject(obj2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator==(const QJNIObjectPrivate &obj1, T obj2)
|
|
||||||
{
|
|
||||||
return obj1.isSameObject(static_cast<jobject>(obj2));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator==(T obj1, const QJNIObjectPrivate &obj2)
|
|
||||||
{
|
|
||||||
return obj2.isSameObject(static_cast<jobject>(obj1));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator!=(const QJNIObjectPrivate &obj1, T obj2)
|
|
||||||
{
|
|
||||||
return !obj1.isSameObject(obj2);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator!=(T obj1, const QJNIObjectPrivate &obj2)
|
|
||||||
{
|
|
||||||
return !obj2.isSameObject(obj1);
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
#endif // QJNI_P_H
|
|
@ -37,18 +37,14 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qcoreapplication.h"
|
|
||||||
#include "qjnienvironment.h"
|
|
||||||
#include "qjnihelpers_p.h"
|
#include "qjnihelpers_p.h"
|
||||||
|
|
||||||
|
#include "qjnienvironment.h"
|
||||||
#include "qjniobject.h"
|
#include "qjniobject.h"
|
||||||
#include "qlist.h"
|
#include "qlist.h"
|
||||||
#include "qmutex.h"
|
#include "qmutex.h"
|
||||||
#include "qsemaphore.h"
|
#include "qsemaphore.h"
|
||||||
#include "qsharedpointer.h"
|
|
||||||
#include "qthread.h"
|
|
||||||
|
|
||||||
#include <QtCore/private/qcoreapplication_p.h>
|
#include <QtCore/private/qcoreapplication_p.h>
|
||||||
#include <QtCore/qrunnable.h>
|
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@ -72,91 +68,20 @@ static JavaVM *g_javaVM = nullptr;
|
|||||||
static jobject g_jActivity = nullptr;
|
static jobject g_jActivity = nullptr;
|
||||||
static jobject g_jService = nullptr;
|
static jobject g_jService = nullptr;
|
||||||
static jobject g_jClassLoader = nullptr;
|
static jobject g_jClassLoader = nullptr;
|
||||||
static jclass g_jNativeClass = nullptr;
|
|
||||||
static jmethodID g_runPendingCppRunnablesMethodID = nullptr;
|
|
||||||
Q_GLOBAL_STATIC(std::deque<QtAndroidPrivate::Runnable>, g_pendingRunnables);
|
|
||||||
static QBasicMutex g_pendingRunnablesMutex;
|
|
||||||
|
|
||||||
Q_GLOBAL_STATIC_WITH_ARGS(QtAndroidPrivate::OnBindListener*, g_onBindListener, (nullptr));
|
Q_GLOBAL_STATIC_WITH_ARGS(QtAndroidPrivate::OnBindListener*, g_onBindListener, (nullptr));
|
||||||
Q_GLOBAL_STATIC(QMutex, g_onBindListenerMutex);
|
Q_GLOBAL_STATIC(QMutex, g_onBindListenerMutex);
|
||||||
Q_GLOBAL_STATIC(QSemaphore, g_waitForServiceSetupSemaphore);
|
Q_GLOBAL_STATIC(QSemaphore, g_waitForServiceSetupSemaphore);
|
||||||
Q_GLOBAL_STATIC(QAtomicInt, g_serviceSetupLockers);
|
Q_GLOBAL_STATIC(QAtomicInt, g_serviceSetupLockers);
|
||||||
|
|
||||||
class PermissionsResultClass : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
PermissionsResultClass(const QtAndroidPrivate::PermissionsResultFunc &func) : m_func(func) {}
|
|
||||||
Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); delete this;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QtAndroidPrivate::PermissionsResultFunc m_func;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QHash<int, PermissionsResultClass*> PendingPermissionRequestsHash;
|
|
||||||
Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests);
|
|
||||||
static QBasicMutex g_pendingPermissionRequestsMutex;
|
|
||||||
static int nextRequestCode()
|
|
||||||
{
|
|
||||||
static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(0);
|
|
||||||
return counter.fetchAndAddRelaxed(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// function called from Java from Android UI thread
|
|
||||||
static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/)
|
|
||||||
{
|
|
||||||
for (;;) { // run all posted runnables
|
|
||||||
QMutexLocker locker(&g_pendingRunnablesMutex);
|
|
||||||
if (g_pendingRunnables->empty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
QtAndroidPrivate::Runnable runnable(std::move(g_pendingRunnables->front()));
|
|
||||||
g_pendingRunnables->pop_front();
|
|
||||||
locker.unlock();
|
|
||||||
runnable(); // run it outside the sync block!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct GenericMotionEventListeners {
|
struct GenericMotionEventListeners {
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
QList<QtAndroidPrivate::GenericMotionEventListener *> listeners;
|
QList<QtAndroidPrivate::GenericMotionEventListener *> listeners;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
PERMISSION_GRANTED = 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners)
|
Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners)
|
||||||
|
|
||||||
static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requestCode,
|
|
||||||
jobjectArray permissions, jintArray grantResults)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&g_pendingPermissionRequestsMutex);
|
|
||||||
auto it = g_pendingPermissionRequests->find(requestCode);
|
|
||||||
if (it == g_pendingPermissionRequests->end()) {
|
|
||||||
// show an error or something ?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto request = *it;
|
|
||||||
g_pendingPermissionRequests->erase(it);
|
|
||||||
locker.unlock();
|
|
||||||
|
|
||||||
Qt::ConnectionType connection = QThread::currentThread() == request->thread() ? Qt::DirectConnection : Qt::QueuedConnection;
|
|
||||||
QtAndroidPrivate::PermissionsHash hash;
|
|
||||||
const int size = env->GetArrayLength(permissions);
|
|
||||||
std::unique_ptr<jint[]> results(new jint[size]);
|
|
||||||
env->GetIntArrayRegion(grantResults, 0, size, results.get());
|
|
||||||
for (int i = 0 ; i < size; ++i) {
|
|
||||||
const auto &permission = QJniObject(env->GetObjectArrayElement(permissions, i)).toString();
|
|
||||||
auto value = results[i] == PERMISSION_GRANTED ?
|
|
||||||
QtAndroidPrivate::PermissionsResult::Granted :
|
|
||||||
QtAndroidPrivate::PermissionsResult::Denied;
|
|
||||||
hash[permission] = value;
|
|
||||||
}
|
|
||||||
QMetaObject::invokeMethod(request, "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
|
static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event)
|
||||||
{
|
{
|
||||||
jboolean ret = JNI_FALSE;
|
jboolean ret = JNI_FALSE;
|
||||||
@ -344,14 +269,12 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const JNINativeMethod methods[] = {
|
static const JNINativeMethod methods[] = {
|
||||||
{"runPendingCppRunnables", "()V", reinterpret_cast<void *>(runPendingCppRunnables)},
|
|
||||||
{"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast<void *>(dispatchGenericMotionEvent)},
|
{"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast<void *>(dispatchGenericMotionEvent)},
|
||||||
{"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast<void *>(dispatchKeyEvent)},
|
{"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast<void *>(dispatchKeyEvent)},
|
||||||
{"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V", reinterpret_cast<void *>(sendRequestPermissionsResult)},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
env->DeleteLocalRef(jQtNative);
|
||||||
if (!regOk && QJniEnvironment::checkAndClearExceptions(env))
|
if (!regOk && QJniEnvironment::checkAndClearExceptions(env))
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
|
|
||||||
@ -361,17 +284,9 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
|
|||||||
if (!registerNativeInterfaceNatives())
|
if (!registerNativeInterfaceNatives())
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
|
|
||||||
g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative,
|
|
||||||
"runPendingCppRunnablesOnAndroidThread",
|
|
||||||
"()V");
|
|
||||||
g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative));
|
|
||||||
env->DeleteLocalRef(jQtNative);
|
|
||||||
|
|
||||||
qRegisterMetaType<QtAndroidPrivate::PermissionsHash>();
|
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jobject QtAndroidPrivate::activity()
|
jobject QtAndroidPrivate::activity()
|
||||||
{
|
{
|
||||||
return g_jActivity;
|
return g_jActivity;
|
||||||
@ -410,110 +325,6 @@ jint QtAndroidPrivate::androidSdkVersion()
|
|||||||
return sdkVersion;
|
return sdkVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtAndroidPrivate::runOnAndroidThread(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&g_pendingRunnablesMutex);
|
|
||||||
const bool triggerRun = g_pendingRunnables->empty();
|
|
||||||
g_pendingRunnables->push_back(runnable);
|
|
||||||
locker.unlock();
|
|
||||||
if (triggerRun)
|
|
||||||
env->CallStaticVoidMethod(g_jNativeClass, g_runPendingCppRunnablesMethodID);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool waitForSemaphore(int timeoutMs, QSharedPointer<QSemaphore> sem)
|
|
||||||
{
|
|
||||||
while (timeoutMs > 0) {
|
|
||||||
if (sem->tryAcquire(1, 10))
|
|
||||||
return true;
|
|
||||||
timeoutMs -= 10;
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable &runnable, JNIEnv *env, int timeoutMs)
|
|
||||||
{
|
|
||||||
QSharedPointer<QSemaphore> sem(new QSemaphore);
|
|
||||||
runOnAndroidThread([&runnable, sem]{
|
|
||||||
runnable();
|
|
||||||
sem->release();
|
|
||||||
}, env);
|
|
||||||
waitForSemaphore(timeoutMs, sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtAndroidPrivate::requestPermissions(JNIEnv *env,
|
|
||||||
const QStringList &permissions,
|
|
||||||
const QtAndroidPrivate::PermissionsResultFunc &callbackFunc,
|
|
||||||
bool directCall)
|
|
||||||
{
|
|
||||||
if (androidSdkVersion() < 23 || !activity()) {
|
|
||||||
QHash<QString, QtAndroidPrivate::PermissionsResult> res;
|
|
||||||
for (const auto &perm : permissions)
|
|
||||||
res[perm] = checkPermission(perm);
|
|
||||||
callbackFunc(res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check API 23+ permissions
|
|
||||||
const int requestCode = nextRequestCode();
|
|
||||||
if (!directCall) {
|
|
||||||
QMutexLocker locker(&g_pendingPermissionRequestsMutex);
|
|
||||||
(*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
runOnAndroidThread([permissions, callbackFunc, requestCode, directCall] {
|
|
||||||
if (directCall) {
|
|
||||||
QMutexLocker locker(&g_pendingPermissionRequestsMutex);
|
|
||||||
(*g_pendingPermissionRequests)[requestCode] = new PermissionsResultClass(callbackFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
QJniEnvironment env;
|
|
||||||
jclass clazz = env->FindClass("java/lang/String");
|
|
||||||
|
|
||||||
if (env.checkAndClearExceptions())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto array = env->NewObjectArray(permissions.size(), clazz, nullptr);
|
|
||||||
int index = 0;
|
|
||||||
for (const auto &perm : permissions)
|
|
||||||
env->SetObjectArrayElement(array, index++, QJniObject::fromString(perm).object());
|
|
||||||
QJniObject(activity()).callMethod<void>("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode);
|
|
||||||
env->DeleteLocalRef(array);
|
|
||||||
}, env);
|
|
||||||
}
|
|
||||||
|
|
||||||
QtAndroidPrivate::PermissionsHash QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs)
|
|
||||||
{
|
|
||||||
QSharedPointer<QHash<QString, QtAndroidPrivate::PermissionsResult>> res(new QHash<QString, QtAndroidPrivate::PermissionsResult>());
|
|
||||||
QSharedPointer<QSemaphore> sem(new QSemaphore);
|
|
||||||
requestPermissions(env, permissions, [sem, res](const QHash<QString, PermissionsResult> &result){
|
|
||||||
*res = result;
|
|
||||||
sem->release();
|
|
||||||
}, true);
|
|
||||||
if (waitForSemaphore(timeoutMs, sem))
|
|
||||||
return std::move(*res);
|
|
||||||
else // mustn't touch *res
|
|
||||||
return QHash<QString, QtAndroidPrivate::PermissionsResult>();
|
|
||||||
}
|
|
||||||
|
|
||||||
QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission)
|
|
||||||
{
|
|
||||||
const auto res = QJniObject::callStaticMethod<jint>("org/qtproject/qt/android/QtNative",
|
|
||||||
"checkSelfPermission",
|
|
||||||
"(Ljava/lang/String;)I",
|
|
||||||
QJniObject::fromString(permission).object());
|
|
||||||
return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtAndroidPrivate::shouldShowRequestPermissionRationale(const QString &permission)
|
|
||||||
{
|
|
||||||
if (androidSdkVersion() < 23 || !activity())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return QJniObject(activity()).callMethod<jboolean>("shouldShowRequestPermissionRationale",
|
|
||||||
"(Ljava/lang/String;)Z",
|
|
||||||
QJniObject::fromString(permission).object());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener)
|
void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
|
QMutexLocker locker(&g_genericMotionEventListeners()->mutex);
|
||||||
@ -538,13 +349,6 @@ void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventList
|
|||||||
g_keyEventListeners()->listeners.removeOne(listener);
|
g_keyEventListeners()->listeners.removeOne(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtAndroidPrivate::hideSplashScreen(JNIEnv *env, int duration)
|
|
||||||
{
|
|
||||||
Q_UNUSED(env)
|
|
||||||
QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative",
|
|
||||||
"hideSplashScreen", "(I)V", duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtAndroidPrivate::waitForServiceSetup()
|
void QtAndroidPrivate::waitForServiceSetup()
|
||||||
{
|
{
|
||||||
g_waitForServiceSetupSemaphore->acquire();
|
g_waitForServiceSetupSemaphore->acquire();
|
||||||
@ -608,5 +412,3 @@ Q_CORE_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||||||
|
|
||||||
return JNI_VERSION_1_6;
|
return JNI_VERSION_1_6;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "qjnihelpers.moc"
|
|
||||||
|
@ -54,13 +54,9 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <QtCore/private/qglobal_p.h>
|
#include <QtCore/private/qglobal_p.h>
|
||||||
#include <QHash>
|
|
||||||
#include <QMetaType>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QRunnable;
|
|
||||||
|
|
||||||
namespace QtAndroidPrivate
|
namespace QtAndroidPrivate
|
||||||
{
|
{
|
||||||
class Q_CORE_EXPORT ActivityResultListener
|
class Q_CORE_EXPORT ActivityResultListener
|
||||||
@ -106,14 +102,6 @@ namespace QtAndroidPrivate
|
|||||||
virtual jobject onBind(jobject intent) = 0;
|
virtual jobject onBind(jobject intent) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PermissionsResult {
|
|
||||||
Granted,
|
|
||||||
Denied
|
|
||||||
};
|
|
||||||
typedef QHash<QString, QtAndroidPrivate::PermissionsResult> PermissionsHash;
|
|
||||||
typedef std::function<void()> Runnable;
|
|
||||||
typedef std::function<void(const PermissionsHash &)> PermissionsResultFunc;
|
|
||||||
|
|
||||||
Q_CORE_EXPORT jobject activity();
|
Q_CORE_EXPORT jobject activity();
|
||||||
Q_CORE_EXPORT jobject service();
|
Q_CORE_EXPORT jobject service();
|
||||||
Q_CORE_EXPORT jobject context();
|
Q_CORE_EXPORT jobject context();
|
||||||
@ -122,12 +110,6 @@ namespace QtAndroidPrivate
|
|||||||
Q_CORE_EXPORT jclass findClass(const char *className, 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 runOnAndroidThreadSync(const Runnable &runnable, JNIEnv *env, int timeoutMs = INT_MAX);
|
|
||||||
Q_CORE_EXPORT void requestPermissions(JNIEnv *env, const QStringList &permissions, const PermissionsResultFunc &callbackFunc, bool directCall = false);
|
|
||||||
Q_CORE_EXPORT PermissionsHash requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX);
|
|
||||||
Q_CORE_EXPORT PermissionsResult checkPermission(const QString &permission);
|
|
||||||
Q_CORE_EXPORT bool shouldShowRequestPermissionRationale(const QString &permission);
|
|
||||||
|
|
||||||
bool registerPermissionNatives();
|
bool registerPermissionNatives();
|
||||||
bool registerNativeInterfaceNatives();
|
bool registerNativeInterfaceNatives();
|
||||||
@ -151,9 +133,6 @@ namespace QtAndroidPrivate
|
|||||||
Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener);
|
Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener);
|
||||||
Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener);
|
Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener);
|
||||||
|
|
||||||
// TODO: Remove once other modules refectoring is done and androidextras is not needed.
|
|
||||||
Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env, int duration = 0);
|
|
||||||
|
|
||||||
Q_CORE_EXPORT void waitForServiceSetup();
|
Q_CORE_EXPORT void waitForServiceSetup();
|
||||||
Q_CORE_EXPORT int acuqireServiceSetup(int flags);
|
Q_CORE_EXPORT int acuqireServiceSetup(int flags);
|
||||||
Q_CORE_EXPORT void setOnBindListener(OnBindListener *listener);
|
Q_CORE_EXPORT void setOnBindListener(OnBindListener *listener);
|
||||||
@ -162,6 +141,4 @@ namespace QtAndroidPrivate
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QtAndroidPrivate::PermissionsHash)
|
|
||||||
|
|
||||||
#endif // QJNIHELPERS_H
|
#endif // QJNIHELPERS_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user