Use Knotificationpermission
This commit is contained in:
@@ -194,8 +194,6 @@ add_library(neochat STATIC
|
||||
neochatroommember.h
|
||||
models/threadmodel.cpp
|
||||
models/threadmodel.h
|
||||
permissionmanager.cpp
|
||||
permissionmanager.h
|
||||
)
|
||||
|
||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
@@ -306,10 +304,6 @@ add_subdirectory(devtools)
|
||||
add_subdirectory(login)
|
||||
add_subdirectory(chatbar)
|
||||
|
||||
if (ANDROID)
|
||||
add_subdirectory(kandroidextras)
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID AND NOT WIN32)
|
||||
qt_target_qml_sources(neochat QML_FILES
|
||||
qml/ShareAction.qml
|
||||
@@ -442,7 +436,7 @@ endif()
|
||||
|
||||
if(ANDROID)
|
||||
target_sources(neochat PRIVATE notifyrc.qrc)
|
||||
target_link_libraries(neochat PUBLIC KAndroidExtras PRIVATE Qt::Svg OpenSSL::SSL)
|
||||
target_link_libraries(neochat PRIVATE Qt::Svg OpenSSL::SSL)
|
||||
if(SQLite3_FOUND)
|
||||
target_link_libraries(neochat-app PRIVATE SQLite::SQLite3)
|
||||
endif()
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_library(KAndroidExtras STATIC)
|
||||
|
||||
target_sources(KAndroidExtras PRIVATE
|
||||
android/activity.cpp
|
||||
android/android_headers.cpp
|
||||
android/contentresolver.cpp
|
||||
android/context.cpp
|
||||
android/intent.cpp
|
||||
android/uri.cpp
|
||||
|
||||
java/java_headers.cpp
|
||||
java/javalocale.cpp
|
||||
|
||||
jni/jni_headers.cpp
|
||||
)
|
||||
|
||||
if (NOT ANDROID)
|
||||
target_sources(KAndroidExtras PRIVATE
|
||||
fake/mock_impl.cpp
|
||||
fake/mock_jniobject.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
generate_export_header(KAndroidExtras BASE_NAME KAndroidExtras)
|
||||
target_compile_features(KAndroidExtras PUBLIC cxx_std_20) # for __VA_OPT__
|
||||
target_link_libraries(KAndroidExtras PUBLIC Qt::Core)
|
||||
|
||||
if (ANDROID)
|
||||
target_link_libraries(KAndroidExtras PRIVATE Qt::CorePrivate)
|
||||
else()
|
||||
target_include_directories(KAndroidExtras PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/fake ${CMAKE_CURRENT_SOURCE_DIR}/fake/qt6)
|
||||
endif()
|
||||
|
||||
ecm_generate_headers(KAndroidExtras_android_FORWARDING_HEADERS
|
||||
HEADER_NAMES
|
||||
Activity
|
||||
AndroidTypes
|
||||
CalendarContract
|
||||
ContentResolver
|
||||
Context
|
||||
Intent
|
||||
ManifestPermission
|
||||
OpenableColumns
|
||||
Settings
|
||||
Uri
|
||||
PREFIX KAndroidExtras
|
||||
REQUIRED_HEADERS KAndroidExtras_android_HEADERS
|
||||
RELATIVE android
|
||||
)
|
||||
|
||||
ecm_generate_headers(KAndroidExtras_java_FORWARDING_HEADERS
|
||||
HEADER_NAMES
|
||||
JavaLocale
|
||||
JavaTypes
|
||||
PREFIX KAndroidExtras
|
||||
REQUIRED_HEADERS KAndroidExtras_java_HEADERS
|
||||
RELATIVE java
|
||||
)
|
||||
|
||||
ecm_generate_headers(KAndroidExtras_jni_FORWARDING_HEADERS
|
||||
HEADER_NAMES
|
||||
JniArgument
|
||||
JniArray
|
||||
JniObject
|
||||
JniMethod
|
||||
JniReturnValue
|
||||
JniPp
|
||||
JniProperty
|
||||
JniSignature
|
||||
JniTypes
|
||||
JniTypeTraits
|
||||
PREFIX KAndroidExtras
|
||||
REQUIRED_HEADERS KAndroidExtras_jni_HEADERS
|
||||
RELATIVE jni
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
# KAndroidExtras
|
||||
|
||||
Utilities for using Java Native Interface (JNI) to interface with Android platform API.
|
||||
|
||||
## Java Native Interface (JNI) wrapper
|
||||
|
||||
C++ header-only code for defining compile-time checked JNI wrappers.
|
||||
|
||||
Supported:
|
||||
- typed `jobject` wrappers (`Jni::Object`)
|
||||
- wrappers for Java arrays holding primitive or non-primitive content (`Jni::Array`)
|
||||
- reading static final properties (`JNI_CONSTANT`)
|
||||
- reading and writing non-static properties (`JNI_PROPERTY`)
|
||||
- static and non-static method calls, constructors (`JNI_METHOD`, `JNI_STATIC_METHOD`, `JNI_CONSTRUCTOR`)
|
||||
|
||||
Not yet supported:
|
||||
- registering native methods for Java -> C++ calls
|
||||
|
||||
## JNI mock implementation
|
||||
|
||||
This is useful for automated testing of JNI code on other platforms than Android.
|
||||
|
||||
## Wrappers for Java and Android types
|
||||
|
||||
Predefined wrappers for common platform types needed in multiple places.
|
||||
@@ -1,2 +0,0 @@
|
||||
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "activity.h"
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/Intent>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
#include "private/qandroidextras_p.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QJniEnvironment>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
Intent Activity::getIntent()
|
||||
{
|
||||
const QJniObject activity = QNativeInterface::QAndroidApplication::context();
|
||||
if (!activity.isValid())
|
||||
return {};
|
||||
|
||||
const auto intent = activity.callObjectMethod("getIntent", Jni::signature<android::content::Intent()>());
|
||||
return Intent(Jni::fromHandle<Intent>(intent));
|
||||
}
|
||||
|
||||
bool Activity::startActivity(const Intent &intent, int receiverRequestCode)
|
||||
{
|
||||
QJniEnvironment jniEnv;
|
||||
QtAndroidPrivate::startActivity(intent, receiverRequestCode);
|
||||
if (jniEnv->ExceptionCheck()) {
|
||||
jniEnv->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_ACTIVITY_H
|
||||
#define KANDROIDEXTRAS_ACTIVITY_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
class Intent;
|
||||
|
||||
/** Methods around android.app.Activity. */
|
||||
namespace Activity
|
||||
{
|
||||
/** Returns the Intent that started the activity. */
|
||||
KANDROIDEXTRAS_EXPORT Intent getIntent();
|
||||
|
||||
/** Same as QtAndroid::startActivity(), but with exception handling. */
|
||||
KANDROIDEXTRAS_EXPORT bool startActivity(const Intent &intent, int receiverRequestCode); // TODO add callback arg
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_ACTIVITY_H
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// list all headers here that have no .cpp file
|
||||
// this only serves as a guarantee that these headers actually compile
|
||||
#include "androidtypes.h"
|
||||
#include "calendarcontract.h"
|
||||
#include "manifestpermission.h"
|
||||
#include "openablecolumns.h"
|
||||
#include "settings.h"
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_ANDROIDTYPES_H
|
||||
#define KANDROIDEXTRAS_ANDROIDTYPES_H
|
||||
|
||||
#include <KAndroidExtras/JniTypes>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
JNI_TYPE(android, content, ContentResolver)
|
||||
JNI_TYPE(android, content, Context)
|
||||
JNI_TYPE(android, content, Intent)
|
||||
JNI_TYPE(android, database, Cursor)
|
||||
JNI_NESTED_TYPE(android, Manifest, permission)
|
||||
JNI_TYPE(android, net, Uri)
|
||||
JNI_NESTED_TYPE(android, provider, CalendarContract, AttendeesColumns)
|
||||
JNI_NESTED_TYPE(android, provider, CalendarContract, CalendarColumns)
|
||||
JNI_NESTED_TYPE(android, provider, CalendarContract, EventsColumns)
|
||||
JNI_NESTED_TYPE(android, provider, CalendarContract, RemindersColumns)
|
||||
JNI_TYPE(android, provider, OpenableColumns)
|
||||
JNI_TYPE(android, provider, Settings)
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_ANDROIDTYPES_H
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_CALENDARCONTRACT_H
|
||||
#define KANDROIDEXTRAS_CALENDARCONTRACT_H
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniObject>
|
||||
#include <KAndroidExtras/JniProperty>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** CalendarContracts.EventColumns wrapper. */
|
||||
class CalendarColumns
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(CalendarColumns, android::provider::CalendarContract_CalendarColumns)
|
||||
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_CONTRIBUTOR)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_EDITOR)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_FREEBUSY)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_NONE)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_OVERRIDE)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_OWNER)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_READ)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_RESPOND)
|
||||
JNI_CONSTANT(jint, CAL_ACCESS_ROOT)
|
||||
};
|
||||
|
||||
/** CalendarContracts.EventColumns wrapper. */
|
||||
class EventsColumns
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(EventsColumns, android::provider::CalendarContract_EventsColumns)
|
||||
|
||||
JNI_CONSTANT(jint, ACCESS_CONFIDENTIAL)
|
||||
JNI_CONSTANT(jint, ACCESS_DEFAULT)
|
||||
JNI_CONSTANT(jint, ACCESS_PRIVATE)
|
||||
JNI_CONSTANT(jint, ACCESS_PUBLIC)
|
||||
|
||||
JNI_CONSTANT(jint, AVAILABILITY_BUSY)
|
||||
JNI_CONSTANT(jint, AVAILABILITY_FREE)
|
||||
JNI_CONSTANT(jint, AVAILABILITY_TENTATIVE)
|
||||
};
|
||||
|
||||
/** CalendarContracts.AttendeesColumns wrapper. */
|
||||
class AttendeesColumns
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(AttendeesColumns, android::provider::CalendarContract_AttendeesColumns)
|
||||
|
||||
JNI_CONSTANT(jint, ATTENDEE_STATUS_ACCEPTED)
|
||||
JNI_CONSTANT(jint, ATTENDEE_STATUS_DECLINED)
|
||||
JNI_CONSTANT(jint, ATTENDEE_STATUS_INVITED)
|
||||
JNI_CONSTANT(jint, ATTENDEE_STATUS_NONE)
|
||||
JNI_CONSTANT(jint, ATTENDEE_STATUS_TENTATIVE)
|
||||
|
||||
JNI_CONSTANT(jint, RELATIONSHIP_ATTENDEE)
|
||||
JNI_CONSTANT(jint, RELATIONSHIP_NONE)
|
||||
JNI_CONSTANT(jint, RELATIONSHIP_ORGANIZER)
|
||||
JNI_CONSTANT(jint, RELATIONSHIP_PERFORMER)
|
||||
JNI_CONSTANT(jint, RELATIONSHIP_SPEAKER)
|
||||
|
||||
JNI_CONSTANT(jint, TYPE_NONE)
|
||||
JNI_CONSTANT(jint, TYPE_OPTIONAL)
|
||||
JNI_CONSTANT(jint, TYPE_REQUIRED)
|
||||
JNI_CONSTANT(jint, TYPE_RESOURCE)
|
||||
};
|
||||
|
||||
/** CalendarContract.RemindersColumns wrapper. */
|
||||
class RemindersColumns
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(RemindersColumns, android::provider::CalendarContract_RemindersColumns)
|
||||
|
||||
JNI_CONSTANT(jint, METHOD_ALARM)
|
||||
JNI_CONSTANT(jint, METHOD_ALERT)
|
||||
JNI_CONSTANT(jint, METHOD_DEFAULT)
|
||||
JNI_CONSTANT(jint, METHOD_EMAIL)
|
||||
JNI_CONSTANT(jint, METHOD_SMS)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_OPENABLECOLUMNS_H
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "contentresolver.h"
|
||||
#include "openablecolumns.h"
|
||||
#include "uri.h"
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
QJniObject ContentResolver::get()
|
||||
{
|
||||
const QJniObject context = QNativeInterface::QAndroidApplication::context();
|
||||
return context.callObjectMethod("getContentResolver", Jni::signature<android::content::ContentResolver()>());
|
||||
}
|
||||
|
||||
QString ContentResolver::mimeType(const QUrl &url)
|
||||
{
|
||||
auto cs = ContentResolver::get();
|
||||
const auto uri = Uri::fromUrl(url);
|
||||
auto mt = cs.callObjectMethod("getType", Jni::signature<java::lang::String(android::net::Uri)>(), uri.object<jobject>());
|
||||
return mt.toString();
|
||||
}
|
||||
|
||||
QString ContentResolver::fileName(const QUrl &url)
|
||||
{
|
||||
auto cs = ContentResolver::get();
|
||||
const auto uri = Uri::fromUrl(url);
|
||||
|
||||
// query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
|
||||
auto cursor = cs.callObjectMethod(
|
||||
"query",
|
||||
Jni::signature<android::database::Cursor(android::net::Uri, java::lang::String[], java::lang::String, java::lang::String[], java::lang::String)>(),
|
||||
uri.object<jobject>(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
const QJniObject DISPLAY_NAME = OpenableColumns::DISPLAY_NAME;
|
||||
const auto nameIndex = cursor.callMethod<jint>("getColumnIndex", (const char *)Jni::signature<int(java::lang::String)>(), DISPLAY_NAME.object());
|
||||
cursor.callMethod<jboolean>("moveToFirst", (const char *)Jni::signature<bool()>());
|
||||
return cursor.callObjectMethod("getString", Jni::signature<java::lang::String(int)>(), nameIndex).toString();
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_CONTENTRESOLVER_H
|
||||
#define KANDROIDEXTRAS_CONTENTRESOLVER_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
#include <qglobal.h>
|
||||
class QJniObject;
|
||||
class QString;
|
||||
class QUrl;
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Methods for working with Android's ContentResolver. */
|
||||
namespace ContentResolver
|
||||
{
|
||||
/** Get the JNI content resolver. */
|
||||
KANDROIDEXTRAS_EXPORT QJniObject get();
|
||||
|
||||
/** Returns the mime type of the given content: URL.
|
||||
* @see Android ContentResolver.getType
|
||||
*/
|
||||
KANDROIDEXTRAS_EXPORT QString mimeType(const QUrl &url);
|
||||
|
||||
/** File name of a file provided by a content: URL. */
|
||||
KANDROIDEXTRAS_EXPORT QString fileName(const QUrl &url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_CONTENTRESOLVER_H
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
QJniObject Context::getPackageName()
|
||||
{
|
||||
const QJniObject context = QNativeInterface::QAndroidApplication::context();
|
||||
return context.callObjectMethod("getPackageName", Jni::signature<java::lang::String()>());
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_CONTEXT_H
|
||||
#define KANDROIDEXTRAS_CONTEXT_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
class QJniObject;
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Methods around android.content.Context. */
|
||||
namespace Context
|
||||
{
|
||||
KANDROIDEXTRAS_EXPORT QJniObject getPackageName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_CONTEXT_H
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "intent.h"
|
||||
#include "uri.h"
|
||||
|
||||
#include <KAndroidExtras/JniArray>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
Intent::~Intent() = default;
|
||||
|
||||
Intent::operator QJniObject() const
|
||||
{
|
||||
return jniHandle();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
QJniObject Intent::getObjectExtra(const char *methodName, const QJniObject &name) const
|
||||
{
|
||||
return jniHandle().callObjectMethod(methodName, Jni::signature<T(java::lang::String)>(), name.object());
|
||||
}
|
||||
|
||||
QString Intent::getStringExtra(const QJniObject &name) const
|
||||
{
|
||||
return getObjectExtra<java::lang::String>("getStringExtra", name).toString();
|
||||
}
|
||||
|
||||
QStringList Intent::getStringArrayExtra(const QJniObject &name) const
|
||||
{
|
||||
const auto extra = getObjectExtra<Jni::Array<java::lang::String>>("getStringArrayExtra", name);
|
||||
return Jni::fromArray<QStringList>(extra);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_INTENT_H
|
||||
#define KANDROIDEXTRAS_INTENT_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniMethod>
|
||||
#include <KAndroidExtras/JniProperty>
|
||||
#include <KAndroidExtras/Uri>
|
||||
|
||||
class QUrl;
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Methods to interact with android.content.Intent objects.
|
||||
* This does not only offer features beyond what QAndroidIntent, it also provides
|
||||
* a putExtra() implementation that actually interoperates with system services.
|
||||
*/
|
||||
class KANDROIDEXTRAS_EXPORT Intent
|
||||
{
|
||||
JNI_OBJECT(Intent, android::content::Intent)
|
||||
public:
|
||||
/** Creates a new empty intent. */
|
||||
JNI_CONSTRUCTOR(Intent)
|
||||
~Intent();
|
||||
|
||||
/** Add a category to the intent. */
|
||||
JNI_METHOD(android::content::Intent, addCategory, java::lang::String)
|
||||
/** Add flags to this intent. */
|
||||
JNI_METHOD(android::content::Intent, addFlags, jint)
|
||||
/** Returns the data of this intent. */
|
||||
JNI_METHOD(android::net::Uri, getData)
|
||||
/** Get the intent action. */
|
||||
JNI_METHOD(java::lang::String, getAction)
|
||||
/** Sets the action of the intent. */
|
||||
JNI_METHOD(android::content::Intent, setAction, java::lang::String)
|
||||
/** Set the data URL of this intent. */
|
||||
JNI_METHOD(android::content::Intent, setData, android::net::Uri)
|
||||
|
||||
/** Returns the mimetype of this intent. */
|
||||
JNI_METHOD(java::lang::String, getType)
|
||||
/** Set the mime type for this intent. */
|
||||
JNI_METHOD(android::content::Intent, setType, java::lang::String)
|
||||
|
||||
/** Read extra intent data. */
|
||||
QString getStringExtra(const QJniObject &name) const;
|
||||
QStringList getStringArrayExtra(const QJniObject &name) const;
|
||||
/** Add extra intent data of type @tparam T. */
|
||||
template<typename T>
|
||||
inline void putExtra(const QJniObject &name, const QJniObject &value)
|
||||
{
|
||||
jniHandle().callObjectMethod("putExtra", Jni::signature<android::content::Intent(java::lang::String, T)>(), name.object(), value.object());
|
||||
}
|
||||
|
||||
/** Implicit conversion to an QJniObject. */
|
||||
operator QJniObject() const;
|
||||
|
||||
/** Action constant for create document intents. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_CREATE_DOCUMENT)
|
||||
/** Main activity entry point. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_MAIN)
|
||||
/** Action constant for open document intents. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_OPEN_DOCUMENT)
|
||||
/** Action constant for viewing intents. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_VIEW)
|
||||
/** Share data. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_SEND)
|
||||
/** Share multiple data items. */
|
||||
JNI_CONSTANT(java::lang::String, ACTION_SEND_MULTIPLE)
|
||||
|
||||
/** Category constant for openable content. */
|
||||
JNI_CONSTANT(java::lang::String, CATEGORY_OPENABLE)
|
||||
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_EMAIL)
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_STREAM)
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_SUBJECT)
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_TEXT)
|
||||
|
||||
/** Flag for granting read URI permissions on content providers. */
|
||||
JNI_CONSTANT(jint, FLAG_GRANT_READ_URI_PERMISSION)
|
||||
/** Flag for granting write URI permissions on content providers. */
|
||||
JNI_CONSTANT(jint, FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
QJniObject getObjectExtra(const char *methodName, const QJniObject &name) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_INTENT_H
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MANIFESTPERMISSIONM_H
|
||||
#define KANDROIDEXTRAS_MANIFESTPERMISSIONM_H
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniObject>
|
||||
#include <KAndroidExtras/JniProperty>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/**
|
||||
* Access to manifest permissions.
|
||||
* @see https://developer.android.com/reference/android/Manifest.permission
|
||||
*/
|
||||
class ManifestPermission
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(ManifestPermission, android::Manifest_permission)
|
||||
public:
|
||||
JNI_CONSTANT(java::lang::String, READ_CALENDAR)
|
||||
JNI_CONSTANT(java::lang::String, WRITE_CALENDAR)
|
||||
JNI_CONSTANT(java::lang::String, READ_EXTERNAL_STORAGE)
|
||||
JNI_CONSTANT(java::lang::String, WRITE_EXTERNAL_STORAGE)
|
||||
JNI_CONSTANT(java::lang::String, POST_NOTIFICATIONS)
|
||||
JNI_CONSTANT(java::lang::String, CAMERA)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_MANIFESTPERMISSIONM_H
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_OPENABLECOLUMNS_H
|
||||
#define KANDROIDEXTRAS_OPENABLECOLUMNS_H
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniObject>
|
||||
#include <KAndroidExtras/JniProperty>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/**
|
||||
* Constants for ContentResolver queries.
|
||||
* @see https://developer.android.com/reference/android/provider/OpenableColumns
|
||||
*/
|
||||
class OpenableColumns
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(OpenableColumns, android::provider::OpenableColumns)
|
||||
public:
|
||||
JNI_CONSTANT(java::lang::String, DISPLAY_NAME)
|
||||
JNI_CONSTANT(java::lang::String, SIZE)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_OPENABLECOLUMNS_H
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_SETTINGS_H
|
||||
#define KANDROIDEXTRAS_SETTINGS_H
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JniProperty>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Methods around android.provider.Settings. */
|
||||
class Settings
|
||||
{
|
||||
JNI_UNMANAGED_OBJECT(Settings, android::provider::Settings)
|
||||
JNI_CONSTANT(java::lang::String, ACTION_APP_NOTIFICATION_SETTINGS)
|
||||
JNI_CONSTANT(java::lang::String, ACTION_CHANNEL_NOTIFICATION_SETTINGS)
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_APP_PACKAGE)
|
||||
JNI_CONSTANT(java::lang::String, EXTRA_CHANNEL_ID)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_SETTINGS_H
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "uri.h"
|
||||
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
QJniObject Uri::fromUrl(const QUrl &url)
|
||||
{
|
||||
return QJniObject::callStaticObjectMethod(Jni::typeName<android::net::Uri>(),
|
||||
"parse",
|
||||
Jni::signature<android::net::Uri(java::lang::String)>(),
|
||||
QJniObject::fromString(url.toString(QUrl::FullyEncoded)).object<jstring>());
|
||||
}
|
||||
|
||||
QUrl Uri::toUrl(const QJniObject &uri)
|
||||
{
|
||||
if (!uri.isValid()) {
|
||||
return QUrl();
|
||||
}
|
||||
return QUrl(uri.callObjectMethod("toString", Jni::signature<java::lang::String()>()).toString());
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_URI_H
|
||||
#define KANDROIDEXTRAS_URI_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
#include <KAndroidExtras/AndroidTypes>
|
||||
#include <KAndroidExtras/JniTypeTraits>
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Conversion methods for android.net.Uri. */
|
||||
namespace Uri
|
||||
{
|
||||
/** Create an android.net.Uri from a QUrl. */
|
||||
KANDROIDEXTRAS_EXPORT QJniObject fromUrl(const QUrl &url);
|
||||
|
||||
/** Convert a android.net.Uri to a QUrl. */
|
||||
KANDROIDEXTRAS_EXPORT QUrl toUrl(const QJniObject &uri);
|
||||
}
|
||||
|
||||
JNI_DECLARE_CONVERTER(android::net::Uri, QUrl, (Uri::toUrl(value)), (Uri::fromUrl(value)))
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_URI_H
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef FAKE_JNI_H
|
||||
#define FAKE_JNI_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#error This is a mock object for use on non-Android!
|
||||
#endif
|
||||
|
||||
typedef uint8_t jboolean;
|
||||
typedef int8_t jbyte;
|
||||
typedef uint16_t jchar;
|
||||
typedef int16_t jshort;
|
||||
typedef int32_t jint;
|
||||
typedef int64_t jlong;
|
||||
typedef float jfloat;
|
||||
typedef double jdouble;
|
||||
|
||||
typedef jint jsize;
|
||||
|
||||
typedef void *jobject;
|
||||
typedef jobject jclass;
|
||||
typedef jobject jstring;
|
||||
typedef jobject jarray;
|
||||
typedef jarray jobjectArray;
|
||||
typedef jarray jbooleanArray;
|
||||
typedef jarray jbyteArray;
|
||||
typedef jarray jcharArray;
|
||||
typedef jarray jshortArray;
|
||||
typedef jarray jintArray;
|
||||
typedef jarray jlongArray;
|
||||
typedef jarray jfloatArray;
|
||||
typedef jarray jdoubleArray;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
inline T *getArrayElements(jsize size)
|
||||
{
|
||||
T *array = new T[size];
|
||||
std::iota(array, array + size, T{});
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
struct JNIEnv {
|
||||
inline bool ExceptionCheck()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
inline void ExceptionClear()
|
||||
{
|
||||
}
|
||||
|
||||
inline int GetArrayLength(jobjectArray)
|
||||
{
|
||||
return m_arrayLength;
|
||||
}
|
||||
inline jobjectArray NewObjectArray(jsize, jclass, jobject)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jobject GetObjectArrayElement(jobjectArray, int index)
|
||||
{
|
||||
return reinterpret_cast<jobject>(index);
|
||||
}
|
||||
inline void SetObjectArrayElement(jobjectArray, jsize, jobject)
|
||||
{
|
||||
}
|
||||
|
||||
inline jbooleanArray NewBooleanArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jbyteArray NewByteArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jcharArray NewCharArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jshortArray NewShortArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jintArray NewIntArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jlongArray NewLongArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jfloatArray NewFloatArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline jdoubleArray NewDoubleArray(jsize)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline jboolean *GetBooleanArrayElements(jbooleanArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jboolean>(m_arrayLength);
|
||||
}
|
||||
inline jbyte *GetByteArrayElements(jbyteArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jbyte>(m_arrayLength);
|
||||
}
|
||||
inline jchar *GetCharArrayElements(jcharArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jchar>(m_arrayLength);
|
||||
}
|
||||
inline jshort *GetShortArrayElements(jshortArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jshort>(m_arrayLength);
|
||||
}
|
||||
inline jint *GetIntArrayElements(jintArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jint>(m_arrayLength);
|
||||
}
|
||||
inline jlong *GetLongArrayElements(jlongArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jlong>(m_arrayLength);
|
||||
}
|
||||
inline jfloat *GetFloatArrayElements(jfloatArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jfloat>(m_arrayLength);
|
||||
}
|
||||
inline jdouble *GetDoubleArrayElements(jdoubleArray, jboolean *)
|
||||
{
|
||||
return detail::getArrayElements<jdouble>(m_arrayLength);
|
||||
}
|
||||
|
||||
inline void ReleaseBooleanArrayElements(jbooleanArray, jboolean *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseByteArrayElements(jbyteArray, jbyte *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseCharArrayElements(jcharArray, jchar *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseShortArrayElements(jshortArray, jshort *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseIntArrayElements(jintArray, jint *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseLongArrayElements(jlongArray, jlong *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseFloatArrayElements(jfloatArray, jfloat *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
inline void ReleaseDoubleArrayElements(jdoubleArray, jdouble *data, jint)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
inline void SetBooleanArrayRegion(jbooleanArray, jsize, jsize, const jboolean *)
|
||||
{
|
||||
}
|
||||
inline void SetByteArrayRegion(jbyteArray, jsize, jsize, const jbyte *)
|
||||
{
|
||||
}
|
||||
inline void SetCharArrayRegion(jcharArray, jsize, jsize, const jchar *)
|
||||
{
|
||||
}
|
||||
inline void SetShortArrayRegion(jshortArray, jsize, jsize, const jshort *)
|
||||
{
|
||||
}
|
||||
inline void SetIntArrayRegion(jintArray, jsize, jsize, const jint *)
|
||||
{
|
||||
}
|
||||
inline void SetLongArrayRegion(jlongArray, jsize, jsize, const jlong *)
|
||||
{
|
||||
}
|
||||
inline void SetFloatArrayRegion(jfloatArray, jsize, jsize, const jfloat *)
|
||||
{
|
||||
}
|
||||
inline void SetDoubleArrayRegion(jdoubleArray, jsize, jsize, const jdouble *)
|
||||
{
|
||||
}
|
||||
|
||||
static jsize m_arrayLength;
|
||||
};
|
||||
|
||||
#define JNI_COMMIT 1
|
||||
#define JNI_ABORT 2
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
int JNIEnv::m_arrayLength = 0;
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MOCK_JNIENVIRONMENT_H
|
||||
#define KANDROIDEXTRAS_MOCK_JNIENVIRONMENT_H
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
class MockJniEnvironment
|
||||
{
|
||||
public:
|
||||
inline jclass findClass(const char *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
inline JNIEnv *operator->()
|
||||
{
|
||||
return &m_env;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable JNIEnv m_env;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "mock_jniobject.h"
|
||||
|
||||
using namespace KAndroidExtras::Internal;
|
||||
|
||||
QStringList MockJniObjectBase::m_staticProtocol;
|
||||
|
||||
class MockJniObjectBasePrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
QStringList protocol;
|
||||
QHash<QByteArray, QVariant> properties;
|
||||
QVariant value;
|
||||
};
|
||||
|
||||
MockJniObjectBase::MockJniObjectBase()
|
||||
: d(new MockJniObjectBasePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
MockJniObjectBase::MockJniObjectBase(const char *className)
|
||||
: d(new MockJniObjectBasePrivate)
|
||||
{
|
||||
addToProtocol(QLatin1StringView("ctor: ") + QLatin1StringView(className));
|
||||
}
|
||||
|
||||
MockJniObjectBase::MockJniObjectBase(jobject object)
|
||||
: d(new MockJniObjectBasePrivate)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
addToProtocol(QLatin1StringView("ctor: o"));
|
||||
}
|
||||
|
||||
MockJniObjectBase::MockJniObjectBase(const MockJniObjectBase &) = default;
|
||||
MockJniObjectBase &MockJniObjectBase::operator=(const MockJniObjectBase &) = default;
|
||||
MockJniObjectBase::~MockJniObjectBase() = default;
|
||||
|
||||
QStringList MockJniObjectBase::protocol() const
|
||||
{
|
||||
return d->protocol;
|
||||
}
|
||||
|
||||
void MockJniObjectBase::addToProtocol(const QString &line) const
|
||||
{
|
||||
d->protocol.push_back(line);
|
||||
}
|
||||
|
||||
void MockJniObjectBase::setProtocol(const QStringList &protocol)
|
||||
{
|
||||
d->protocol = protocol;
|
||||
}
|
||||
|
||||
QVariant MockJniObjectBase::property(const QByteArray &name) const
|
||||
{
|
||||
return d->properties.value(name);
|
||||
}
|
||||
|
||||
void MockJniObjectBase::setProperty(const QByteArray &name, const QVariant &value)
|
||||
{
|
||||
d->properties.insert(name, value);
|
||||
}
|
||||
|
||||
QVariant MockJniObjectBase::value() const
|
||||
{
|
||||
return d->value;
|
||||
}
|
||||
|
||||
void MockJniObjectBase::setValue(const QVariant &value)
|
||||
{
|
||||
d->value = value;
|
||||
}
|
||||
|
||||
void MockJniObjectBase::setData(jobject object)
|
||||
{
|
||||
d = reinterpret_cast<MockJniObjectBasePrivate *>(object);
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MOCK_JNIOBJECT_H
|
||||
#define KANDROIDEXTRAS_MOCK_JNIOBJECT_H
|
||||
|
||||
#include "jni.h"
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
#include "kandroidextras/jnisignature.h"
|
||||
#include "kandroidextras/jnitypes.h"
|
||||
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
class MockJniObjectBasePrivate;
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
namespace Internal
|
||||
{
|
||||
template<typename T>
|
||||
constexpr inline const char *argTypeToString()
|
||||
{
|
||||
return KAndroidExtras::Jni::signature<T>();
|
||||
}
|
||||
template<>
|
||||
constexpr inline const char *argTypeToString<jobject>()
|
||||
{
|
||||
return "o";
|
||||
}
|
||||
|
||||
class KANDROIDEXTRAS_EXPORT MockJniObjectBase
|
||||
{
|
||||
public:
|
||||
MockJniObjectBase();
|
||||
MockJniObjectBase(const MockJniObjectBase &);
|
||||
~MockJniObjectBase();
|
||||
MockJniObjectBase &operator=(const MockJniObjectBase &);
|
||||
|
||||
MockJniObjectBase(const char *className);
|
||||
|
||||
inline MockJniObjectBase(const char *className, const char *signature)
|
||||
: MockJniObjectBase()
|
||||
{
|
||||
addToProtocol(QLatin1StringView("ctor: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(signature));
|
||||
}
|
||||
template<typename... Args>
|
||||
inline MockJniObjectBase(const char *className, const char *signature, Args...)
|
||||
: MockJniObjectBase()
|
||||
{
|
||||
addToProtocol(QLatin1StringView("ctor: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (")
|
||||
+ (... + QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')'));
|
||||
}
|
||||
|
||||
MockJniObjectBase(jobject object);
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static QStringList m_staticProtocol;
|
||||
|
||||
QStringList protocol() const;
|
||||
void addToProtocol(const QString &line) const;
|
||||
|
||||
protected:
|
||||
QVariant property(const QByteArray &name) const;
|
||||
void setProperty(const QByteArray &name, const QVariant &value);
|
||||
QVariant value() const;
|
||||
void setValue(const QVariant &value);
|
||||
void setData(jobject object);
|
||||
|
||||
void setProtocol(const QStringList &protocol);
|
||||
QExplicitlySharedDataPointer<MockJniObjectBasePrivate> d;
|
||||
};
|
||||
|
||||
template<typename JniObjectT>
|
||||
class MockJniObject : public MockJniObjectBase
|
||||
{
|
||||
public:
|
||||
using MockJniObjectBase::MockJniObjectBase;
|
||||
static inline JniObjectT fromString(const QString &s)
|
||||
{
|
||||
JniObjectT o;
|
||||
o.setValue(s);
|
||||
return o;
|
||||
}
|
||||
static inline JniObjectT fromLocalRef(jobject o)
|
||||
{
|
||||
JniObjectT obj;
|
||||
obj.addToProtocol(QLatin1StringView("ctor: ") + QString::number((qulonglong)o));
|
||||
return obj;
|
||||
}
|
||||
inline QString toString() const
|
||||
{
|
||||
return value().userType() == QMetaType::QString ? value().toString() : protocol().join(QLatin1Char('\n'));
|
||||
}
|
||||
|
||||
inline jobject object() const
|
||||
{
|
||||
return d.data();
|
||||
}
|
||||
template<typename T>
|
||||
inline T object() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
inline T callMethod(const char *methodName, const char *signature, Args...) const
|
||||
{
|
||||
const QString s = QLatin1StringView("callMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature)
|
||||
+ QLatin1StringView(" (") + (... + QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')');
|
||||
addToProtocol(s);
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
inline T callMethod(const char *methodName, const char *signature) const
|
||||
{
|
||||
const QString s =
|
||||
QLatin1StringView("callMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()");
|
||||
addToProtocol(s);
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline JniObjectT callObjectMethod(const char *methodName, const char *signature, Args...) const
|
||||
{
|
||||
const QString s = QLatin1StringView("callObjectMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature)
|
||||
+ QLatin1StringView(" (") + (... + QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')');
|
||||
addToProtocol(s);
|
||||
|
||||
JniObjectT obj;
|
||||
obj.setProtocol(protocol());
|
||||
return obj;
|
||||
}
|
||||
inline JniObjectT callObjectMethod(const char *methodName, const char *signature) const
|
||||
{
|
||||
addToProtocol(QLatin1StringView("callObjectMethod: ") + QLatin1StringView(methodName) + QLatin1Char(' ') + QLatin1StringView(signature)
|
||||
+ QLatin1StringView(" ()"));
|
||||
|
||||
JniObjectT obj;
|
||||
obj.setProtocol(protocol());
|
||||
return obj;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T getField(const char *fieldName) const
|
||||
{
|
||||
addToProtocol(QLatin1StringView("getField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ')
|
||||
+ QLatin1StringView(KAndroidExtras::Jni::signature<T>()));
|
||||
return property(fieldName).template value<T>();
|
||||
}
|
||||
|
||||
inline JniObjectT getObjectField(const char *fieldName, const char *signature) const
|
||||
{
|
||||
addToProtocol(QLatin1StringView("getObjectField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(signature));
|
||||
return property(fieldName).template value<JniObjectT>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void setField(const char *fieldName, const char *signature, T value)
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
addToProtocol(QLatin1StringView("setField: ") + QLatin1StringView(fieldName) + QLatin1Char(' ') + QLatin1StringView(signature));
|
||||
if constexpr (std::is_same_v<jobject, T>) {
|
||||
setObjectProperty(fieldName, value);
|
||||
} else {
|
||||
setProperty(fieldName, QVariant::fromValue(value));
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
inline void setField(const char *fieldName, T value)
|
||||
{
|
||||
setField(fieldName, KAndroidExtras::Jni::signature<T>(), value);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static inline T callStaticMethod(const char *className, const char *methodName, const char *signature, Args...)
|
||||
{
|
||||
const QString s = QLatin1StringView("callStaticMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(methodName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (")
|
||||
+ (... + QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')');
|
||||
m_staticProtocol.push_back(s);
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
static inline T callStaticMethod(const char *className, const char *methodName, const char *signature)
|
||||
{
|
||||
const QString s = QLatin1StringView("callStaticMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(methodName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()");
|
||||
m_staticProtocol.push_back(s);
|
||||
if constexpr (!std::is_same_v<T, void>) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static inline JniObjectT callStaticObjectMethod(const char *className, const char *methodName, const char *signature, Args...)
|
||||
{
|
||||
const QString s = QLatin1StringView("callStaticObjectMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(methodName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" (")
|
||||
+ (... + QLatin1StringView(KAndroidExtras::Internal::argTypeToString<Args>())) + QLatin1Char(')');
|
||||
JniObjectT obj;
|
||||
obj.addToProtocol(s);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline JniObjectT callStaticObjectMethod(const char *className, const char *methodName, const char *signature)
|
||||
{
|
||||
JniObjectT obj;
|
||||
obj.addToProtocol(QLatin1StringView("callStaticObjectMethod: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(methodName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(signature) + QLatin1StringView(" ()"));
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline JniObjectT getStaticObjectField(const char *className, const char *fieldName, const char *signature)
|
||||
{
|
||||
m_staticProtocol.push_back(QLatin1StringView("getStaticObjectField: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(fieldName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(signature));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline JniObjectT getStaticObjectField(const char *className, const char *fieldName)
|
||||
{
|
||||
m_staticProtocol.push_back(QLatin1StringView("getStaticObjectField<>: ") + QLatin1StringView(className) + QLatin1Char(' ')
|
||||
+ QLatin1StringView(fieldName));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T getStaticField(const char *className, const char *fieldName)
|
||||
{
|
||||
m_staticProtocol.push_back(QLatin1StringView("getStaticField<>: ") + QLatin1StringView(className) + QLatin1Char(' ') + QLatin1StringView(fieldName)
|
||||
+ QLatin1Char(' ') + QLatin1StringView(KAndroidExtras::Jni::signature<T>()));
|
||||
return {};
|
||||
}
|
||||
|
||||
inline void setObjectProperty(const QByteArray &name, jobject value)
|
||||
{
|
||||
JniObjectT o;
|
||||
o.setData(value);
|
||||
setProperty(name, QVariant::fromValue(o));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MOCK_QCOREAPPLICATION_H
|
||||
#define KANDROIDEXTRAS_MOCK_QCOREAPPLICATION_H
|
||||
|
||||
#include_next <QCoreApplication>
|
||||
|
||||
#include <QJniObject>
|
||||
|
||||
namespace QNativeInterface {
|
||||
namespace QAndroidApplication {
|
||||
inline QJniObject context()
|
||||
{
|
||||
QJniObject obj;
|
||||
obj.addToProtocol(QStringLiteral("global androidContext()"));
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MOCK_QJNIENVIRONMENT_H
|
||||
#define KANDROIDEXTRAS_MOCK_QJNIENVIRONMENT_H
|
||||
|
||||
#include "mock_jnienvironment.h"
|
||||
|
||||
class QJniEnvironment : public KAndroidExtras::MockJniEnvironment
|
||||
{
|
||||
public:
|
||||
inline JNIEnv* jniEnv() const { return &m_env; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qjniobject.h"
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MAKE_QTANDROIDEXTRAS_P_H
|
||||
#define KANDROIDEXTRAS_MAKE_QTANDROIDEXTRAS_P_H
|
||||
|
||||
#include <QJniObject>
|
||||
|
||||
/** Mock object for QtAndroid namespace. */
|
||||
namespace QtAndroidPrivate
|
||||
{
|
||||
inline void startActivity(const QJniObject &, int)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_MOCK_QJNIOBJECT_H
|
||||
#define KANDROIDEXTRAS_MOCK_QJNIOBJECT_H
|
||||
|
||||
#include "mock_jniobject.h"
|
||||
|
||||
/** Mock object for QJniObject outside of Android, for automated testing. */
|
||||
class KANDROIDEXTRAS_EXPORT QJniObject : public KAndroidExtras::Internal::MockJniObject<QJniObject>
|
||||
{
|
||||
public:
|
||||
using MockJniObject<QJniObject>::MockJniObject;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QJniObject)
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// list all headers here that have no .cpp file
|
||||
// this only serves as a guarantee that these headers actually compile
|
||||
#include "javatypes.h"
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "javalocale.h"
|
||||
|
||||
#include <KAndroidExtras/JavaTypes>
|
||||
#include <KAndroidExtras/JniSignature>
|
||||
|
||||
#include <QLocale>
|
||||
|
||||
using namespace KAndroidExtras;
|
||||
|
||||
QJniObject Locale::fromLocale(const QLocale &locale)
|
||||
{
|
||||
auto lang = QJniObject::fromString(QLocale::languageToString(locale.language()));
|
||||
auto country = QJniObject::fromString(QLocale::countryToString(locale.country()));
|
||||
auto script = QJniObject::fromString(QLocale::scriptToString(locale.script()));
|
||||
|
||||
return QJniObject(Jni::typeName<java::util::Locale>(),
|
||||
(const char *)Jni::signature<void(java::lang::String, java::lang::String, java::lang::String)>(),
|
||||
lang.object(),
|
||||
country.object(),
|
||||
script.object());
|
||||
}
|
||||
|
||||
QJniObject Locale::current()
|
||||
{
|
||||
return fromLocale(QLocale());
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_LOCALE_H
|
||||
#define KANDROIDEXTRAS_LOCALE_H
|
||||
|
||||
#include "kandroidextras_export.h"
|
||||
|
||||
class QJniObject;
|
||||
class QLocale;
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
/** Conversion methods between java.util.Locale and QLocale.
|
||||
* @note Do not rename this file to locale.h, that clashes with POSIX locale.h when your
|
||||
* include paths are unfortunately set up causing bizarre compilation issues.
|
||||
*/
|
||||
namespace Locale
|
||||
{
|
||||
/** Create an java.util.Locale object from a QLocale. */
|
||||
KANDROIDEXTRAS_EXPORT QJniObject fromLocale(const QLocale &locale);
|
||||
|
||||
/** Create an java.util.Locale object for the current QLocale. */
|
||||
KANDROIDEXTRAS_EXPORT QJniObject current();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_LOCALE_H
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JAVATYPES_H
|
||||
#define KANDROIDEXTRAS_JAVATYPES_H
|
||||
|
||||
#include <KAndroidExtras/JniTypeTraits>
|
||||
#include <KAndroidExtras/JniTypes>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
JNI_TYPE(java, io, File)
|
||||
JNI_TYPE(java, lang, String)
|
||||
JNI_TYPE(java, util, Locale)
|
||||
|
||||
JNI_DECLARE_CONVERTER(java::lang::String, QString, (value.toString()), (QJniObject::fromString(value)))
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_JAVATYPES_H
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
// list all headers here that have no .cpp file
|
||||
// this only serves as a guarantee that these headers actually compile
|
||||
#include "jniargument.h"
|
||||
#include "jniarray.h"
|
||||
#include "jnimethod.h"
|
||||
#include "jniobject.h"
|
||||
#include "jnipp.h"
|
||||
#include "jniprimitivetypes.h"
|
||||
#include "jniproperty.h"
|
||||
#include "jnireturnvalue.h"
|
||||
#include "jnisignature.h"
|
||||
#include "jnitypes.h"
|
||||
#include "jnitypetraits.h"
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIARGUMENTVALUE_H
|
||||
#define KANDROIDEXTRAS_JNIARGUMENTVALUE_H
|
||||
|
||||
#include "jniobject.h"
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
namespace Jni
|
||||
{
|
||||
template<typename T>
|
||||
class Array;
|
||||
}
|
||||
|
||||
///@cond internal
|
||||
namespace Internal
|
||||
{
|
||||
/** Call argument wrapper. */
|
||||
template<typename T, typename = std::void_t<>>
|
||||
struct argument {
|
||||
static_assert(!is_invalid_primitive_type<T>::value, "Using an incompatible primitive type!");
|
||||
typedef std::conditional_t<Jni::is_primitive_type<T>::value, T, const Jni::Object<T> &> type;
|
||||
static inline constexpr auto toCallArgument(type value)
|
||||
{
|
||||
if constexpr (Jni::is_primitive_type<T>::value) {
|
||||
return primitive_value<T>::toJni(value);
|
||||
} else {
|
||||
return value.jniHandle().object();
|
||||
}
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct argument<T, std::void_t<typename T::_jni_ThisType>> {
|
||||
typedef const T &type;
|
||||
static inline auto toCallArgument(const T &value)
|
||||
{
|
||||
return Jni::handle(value).object();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct argument<Jni::Array<T>> {
|
||||
typedef const Jni::Array<T> &type;
|
||||
static inline auto toCallArgument(const Jni::Array<T> &value)
|
||||
{
|
||||
return value.jniHandle().object();
|
||||
}
|
||||
};
|
||||
}
|
||||
///@endcond
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,395 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIARRAY_H
|
||||
#define KANDROIDEXTRAS_JNIARRAY_H
|
||||
|
||||
#include "jniargument.h"
|
||||
#include "jnireturnvalue.h"
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
#include <QJniEnvironment>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
///@cond internal
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
/** Primitive type array type traits. */
|
||||
template<typename T>
|
||||
struct array_trait {
|
||||
typedef jobjectArray type;
|
||||
};
|
||||
|
||||
#define MAKE_ARRAY_TRAIT(base_type, type_name) \
|
||||
template<> \
|
||||
struct array_trait<base_type> { \
|
||||
typedef base_type##Array type; \
|
||||
static inline type newArray(QJniEnvironment &env, jsize size) \
|
||||
{ \
|
||||
return env->New##type_name##Array(size); \
|
||||
} \
|
||||
static inline base_type *getArrayElements(QJniEnvironment &env, type array, jboolean *isCopy) \
|
||||
{ \
|
||||
return env->Get##type_name##ArrayElements(array, isCopy); \
|
||||
} \
|
||||
static inline void releaseArrayElements(QJniEnvironment &env, type array, base_type *data, jint mode) \
|
||||
{ \
|
||||
return env->Release##type_name##ArrayElements(array, data, mode); \
|
||||
} \
|
||||
static inline void setArrayRegion(QJniEnvironment &env, type array, jsize start, jsize length, const base_type *data) \
|
||||
{ \
|
||||
env->Set##type_name##ArrayRegion(array, start, length, data); \
|
||||
} \
|
||||
};
|
||||
|
||||
MAKE_ARRAY_TRAIT(jboolean, Boolean)
|
||||
MAKE_ARRAY_TRAIT(jbyte, Byte)
|
||||
MAKE_ARRAY_TRAIT(jchar, Char)
|
||||
MAKE_ARRAY_TRAIT(jshort, Short)
|
||||
MAKE_ARRAY_TRAIT(jint, Int)
|
||||
MAKE_ARRAY_TRAIT(jlong, Long)
|
||||
MAKE_ARRAY_TRAIT(jfloat, Float)
|
||||
MAKE_ARRAY_TRAIT(jdouble, Double)
|
||||
|
||||
#undef MAKE_ARRAY_TRAIT
|
||||
|
||||
/** Meta function for retrieving a JNI array .*/
|
||||
template<typename Container, typename Value, bool is_primitive>
|
||||
struct FromArray {
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct FromArray<Container, QJniObject, false> {
|
||||
inline auto operator()(const QJniObject &array) const
|
||||
{
|
||||
if (!array.isValid()) {
|
||||
return Container{};
|
||||
}
|
||||
const auto a = static_cast<jobjectArray>(array.object());
|
||||
QJniEnvironment env;
|
||||
const auto size = env->GetArrayLength(a);
|
||||
Container r;
|
||||
r.reserve(size);
|
||||
for (auto i = 0; i < size; ++i) {
|
||||
r.push_back(QJniObject::fromLocalRef(env->GetObjectArrayElement(a, i)));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Container, typename Value>
|
||||
struct FromArray<Container, Value, false> {
|
||||
inline auto operator()(const QJniObject &array) const
|
||||
{
|
||||
if (!array.isValid()) {
|
||||
return Container{};
|
||||
}
|
||||
const auto a = static_cast<jobjectArray>(array.object());
|
||||
QJniEnvironment env;
|
||||
const auto size = env->GetArrayLength(a);
|
||||
Container r;
|
||||
r.reserve(size);
|
||||
for (auto i = 0; i < size; ++i) {
|
||||
r.push_back(Jni::reverse_converter<Value>::type::convert(QJniObject::fromLocalRef(env->GetObjectArrayElement(a, i))));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
// specializations for primitive types
|
||||
template<typename Container, typename Value>
|
||||
struct FromArray<Container, Value, true> {
|
||||
typedef array_trait<Value> _t;
|
||||
inline auto operator()(const QJniObject &array) const
|
||||
{
|
||||
if (!array.isValid()) {
|
||||
return Container{};
|
||||
}
|
||||
|
||||
const auto a = static_cast<typename _t::type>(array.object());
|
||||
QJniEnvironment env;
|
||||
const auto size = env->GetArrayLength(a);
|
||||
Container r;
|
||||
r.reserve(size);
|
||||
|
||||
auto data = _t::getArrayElements(env, a, nullptr);
|
||||
std::copy(data, data + size, std::back_inserter(r));
|
||||
_t::releaseArrayElements(env, a, data, JNI_ABORT);
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
// array wrapper, common base for primitive and non-primitive types
|
||||
template<typename T>
|
||||
class ArrayImplBase
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef jsize size_type;
|
||||
typedef jsize difference_type;
|
||||
|
||||
ArrayImplBase() = default;
|
||||
inline ArrayImplBase(const QJniObject &array)
|
||||
: m_array(array)
|
||||
{
|
||||
}
|
||||
ArrayImplBase(const ArrayImplBase &) = default;
|
||||
ArrayImplBase(ArrayImplBase &&) = default;
|
||||
|
||||
inline size_type size() const
|
||||
{
|
||||
if (!m_array.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
const auto a = static_cast<typename _t::type>(m_array.object());
|
||||
QJniEnvironment env;
|
||||
return env->GetArrayLength(a);
|
||||
}
|
||||
|
||||
inline operator QJniObject() const
|
||||
{
|
||||
return m_array;
|
||||
}
|
||||
inline QJniObject jniHandle() const
|
||||
{
|
||||
return m_array;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef array_trait<T> _t;
|
||||
|
||||
typename _t::type handle() const
|
||||
{
|
||||
return static_cast<typename _t::type>(m_array.object());
|
||||
}
|
||||
|
||||
QJniObject m_array;
|
||||
};
|
||||
|
||||
template<typename T, bool is_primitive>
|
||||
class ArrayImpl
|
||||
{
|
||||
};
|
||||
|
||||
// array wrapper for primitive types
|
||||
template<typename T>
|
||||
class ArrayImpl<T, true> : public ArrayImplBase<T>
|
||||
{
|
||||
static_assert(!Internal::is_invalid_primitive_type<T>::value, "Using an incompatible primitive type!");
|
||||
|
||||
public:
|
||||
inline ArrayImpl(const QJniObject &array)
|
||||
: ArrayImplBase<T>(array)
|
||||
{
|
||||
// ### do this on demand?
|
||||
getArrayElements();
|
||||
}
|
||||
|
||||
/** Create a new array with @p size elements. */
|
||||
inline explicit ArrayImpl(jsize size)
|
||||
{
|
||||
QJniEnvironment env;
|
||||
ArrayImplBase<T>::m_array = QJniObject::fromLocalRef(ArrayImplBase<T>::_t::newArray(env, size));
|
||||
getArrayElements();
|
||||
}
|
||||
|
||||
ArrayImpl() = default;
|
||||
ArrayImpl(const ArrayImpl &) = delete; // ### ref count m_data and allow copying?
|
||||
ArrayImpl(ArrayImpl &&) = default;
|
||||
~ArrayImpl()
|
||||
{
|
||||
QJniEnvironment env;
|
||||
ArrayImplBase<T>::_t::releaseArrayElements(env, this->handle(), m_data, JNI_ABORT);
|
||||
}
|
||||
|
||||
T operator[](jsize index) const
|
||||
{
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
T *begin() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
T *end() const
|
||||
{
|
||||
return m_data + ArrayImplBase<T>::size();
|
||||
}
|
||||
|
||||
private:
|
||||
inline void getArrayElements()
|
||||
{
|
||||
if (!ArrayImplBase<T>::m_array.isValid()) {
|
||||
return;
|
||||
}
|
||||
QJniEnvironment env;
|
||||
m_data = ArrayImplBase<T>::_t::getArrayElements(env, this->handle(), nullptr);
|
||||
}
|
||||
|
||||
T *m_data = nullptr;
|
||||
};
|
||||
|
||||
// array wrapper for non-primitive types
|
||||
template<typename T>
|
||||
class ArrayImpl<T, false> : public ArrayImplBase<T>
|
||||
{
|
||||
public:
|
||||
using ArrayImplBase<T>::ArrayImplBase;
|
||||
|
||||
/** Create a new array with @p size elements initialized with @p value. */
|
||||
explicit inline ArrayImpl(jsize size, typename Internal::argument<T>::type value)
|
||||
{
|
||||
QJniEnvironment env;
|
||||
auto clazz = env.findClass(Jni::typeName<T>());
|
||||
ArrayImplBase<T>::m_array = QJniObject::fromLocalRef(env->NewObjectArray(size, clazz, Internal::argument<T>::toCallArgument(value)));
|
||||
}
|
||||
|
||||
/** Create a new array with @p size null elements. */
|
||||
explicit inline ArrayImpl(jsize size, std::nullptr_t = nullptr)
|
||||
{
|
||||
QJniEnvironment env;
|
||||
auto clazz = env.findClass(Jni::typeName<T>());
|
||||
ArrayImplBase<T>::m_array = QJniObject::fromLocalRef(env->NewObjectArray(size, clazz, nullptr));
|
||||
}
|
||||
|
||||
ArrayImpl() = default;
|
||||
ArrayImpl(const ArrayImpl &) = default;
|
||||
ArrayImpl(ArrayImpl &&) = default;
|
||||
|
||||
auto operator[](jsize index) const
|
||||
{
|
||||
QJniEnvironment env;
|
||||
return Internal::return_wrapper<T>::toReturnValue(QJniObject::fromLocalRef(env->GetObjectArrayElement(this->handle(), index)));
|
||||
}
|
||||
|
||||
class ref
|
||||
{
|
||||
public:
|
||||
inline operator auto()
|
||||
{
|
||||
QJniEnvironment env;
|
||||
return Internal::return_wrapper<T>::toReturnValue(QJniObject::fromLocalRef(env->GetObjectArrayElement(c.handle(), index)));
|
||||
}
|
||||
inline ref &operator=(typename Internal::argument<T>::type v)
|
||||
{
|
||||
QJniEnvironment env;
|
||||
env->SetObjectArrayElement(c.handle(), index, Internal::argument<T>::toCallArgument(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayImpl<T, false> &c;
|
||||
jsize index;
|
||||
|
||||
friend class ArrayImpl<T, false>;
|
||||
inline ref(jsize _i, ArrayImpl<T, false> &_c)
|
||||
: c(_c)
|
||||
, index(_i)
|
||||
{
|
||||
}
|
||||
};
|
||||
ref operator[](jsize index)
|
||||
{
|
||||
return ref(index, *this);
|
||||
}
|
||||
|
||||
class const_iterator
|
||||
{
|
||||
const ArrayImpl<T, false> &c;
|
||||
jsize i = 0;
|
||||
|
||||
public:
|
||||
typedef jsize difference_type;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
typedef T *pointer;
|
||||
|
||||
const_iterator(const ArrayImpl<T, false> &_c, jsize _i)
|
||||
: c(_c)
|
||||
, i(_i)
|
||||
{
|
||||
}
|
||||
|
||||
difference_type operator-(const_iterator other) const
|
||||
{
|
||||
return i - other.i;
|
||||
}
|
||||
|
||||
const_iterator &operator++()
|
||||
{
|
||||
++i;
|
||||
return *this;
|
||||
}
|
||||
const_iterator operator++(int)
|
||||
{
|
||||
return const_iterator(c, i++);
|
||||
}
|
||||
|
||||
bool operator==(const_iterator other) const
|
||||
{
|
||||
return i == other.i;
|
||||
}
|
||||
bool operator!=(const_iterator other) const
|
||||
{
|
||||
return i != other.i;
|
||||
}
|
||||
|
||||
auto operator*() const
|
||||
{
|
||||
return c[i];
|
||||
}
|
||||
};
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(*this, 0);
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(*this, ArrayImplBase<T>::size());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
///@endcond
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
|
||||
/** Convert a JNI array to a C++ container.
|
||||
* Container value types can be any of
|
||||
* - QJniObject
|
||||
* - a primitive JNI type
|
||||
* - a type with a conversion defined with @c JNI_DECLARE_CONVERTER
|
||||
*/
|
||||
template<typename Container>
|
||||
constexpr
|
||||
__attribute__((__unused__)) Internal::FromArray<Container, typename Container::value_type, Jni::is_primitive_type<typename Container::value_type>::value>
|
||||
fromArray = {};
|
||||
|
||||
/** Container-like wrapper for JNI arrays. */
|
||||
template<typename T>
|
||||
class Array : public Internal::ArrayImpl<T, Jni::is_primitive_type<T>::value>
|
||||
{
|
||||
public:
|
||||
using Internal::ArrayImpl<T, Jni::is_primitive_type<T>::value>::ArrayImpl;
|
||||
template<typename Container>
|
||||
inline operator Container() const
|
||||
{
|
||||
// ### should this be re-implemented in terms of Jni::Array API rather than direct JNI access?
|
||||
return Jni::fromArray<Container>(this->m_array);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIMETHOD_H
|
||||
#define KANDROIDEXTRAS_JNIMETHOD_H
|
||||
|
||||
#include "jniargument.h"
|
||||
#include "jniarray.h"
|
||||
#include "jniobject.h"
|
||||
#include "jnipp.h"
|
||||
#include "jnireturnvalue.h"
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
///@cond internal
|
||||
|
||||
// method parameter generation
|
||||
#define JNI_PARAM(Type, Name) typename KAndroidExtras::Internal::argument<Type>::type Name
|
||||
|
||||
#define JNI_PARAMS_0(accu, arg)
|
||||
#define JNI_PARAMS_1(accu, arg, ...) JNI_PARAM(arg, a1)
|
||||
#define JNI_PARAMS_2(accu, arg, ...) JNI_PARAM(arg, a2), JNI_PARAMS_1(accu, __VA_ARGS__)
|
||||
#define JNI_PARAMS_3(accu, arg, ...) JNI_PARAM(arg, a3), JNI_PARAMS_2(accu, __VA_ARGS__)
|
||||
|
||||
#define JNI_PARAMS_(N, accu, ...) JNI_PP_CONCAT(JNI_PARAMS_, N)(accu, __VA_ARGS__)
|
||||
#define JNI_PARAMS(...) JNI_PARAMS_(JNI_PP_NARG(__VA_ARGS__), "", __VA_ARGS__)
|
||||
|
||||
// method argument forwarding generation
|
||||
#define JNI_ARG(Type, Name) KAndroidExtras::Internal::argument<Type>::toCallArgument(Name)
|
||||
#define JNI_ARGS_0(accu, arg)
|
||||
#define JNI_ARGS_1(accu, arg, ...) JNI_ARG(arg, a1)
|
||||
#define JNI_ARGS_2(accu, arg, ...) JNI_ARG(arg, a2), JNI_ARGS_1(accu, __VA_ARGS__)
|
||||
#define JNI_ARGS_3(accu, arg, ...) JNI_ARG(arg, a3), JNI_ARGS_2(accu, __VA_ARGS__)
|
||||
|
||||
#define JNI_ARGS_(N, accu, ...) JNI_PP_CONCAT(JNI_ARGS_, N)(accu, __VA_ARGS__)
|
||||
#define JNI_ARGS(...) JNI_ARGS_(JNI_PP_NARG(__VA_ARGS__), "", __VA_ARGS__)
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
// method call wrapper
|
||||
template<typename RetT>
|
||||
struct caller {
|
||||
static_assert(!is_invalid_primitive_type<RetT>::value, "Using an incompatible primitive type!");
|
||||
template<typename... Args>
|
||||
static auto call(const QJniObject &handle, const char *name, const char *signature, Args &&...args)
|
||||
{
|
||||
if constexpr (std::is_same_v<RetT, void>) {
|
||||
handle.callMethod<RetT>(name, signature, std::forward<Args>(args)...);
|
||||
} else if constexpr (Jni::is_primitive_type<RetT>::value) {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(
|
||||
handle.callMethod<typename primitive_value<RetT>::JniType>(name, signature, std::forward<Args>(args)...));
|
||||
} else {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(handle.callObjectMethod(name, signature, std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
static auto call(const QJniObject &handle, const char *name, const char *signature)
|
||||
{
|
||||
if constexpr (std::is_same_v<RetT, void>) {
|
||||
return handle.callMethod<RetT>(name, signature);
|
||||
} else if constexpr (Jni::is_primitive_type<RetT>::value) {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(handle.callMethod<typename primitive_value<RetT>::JniType>(name, signature));
|
||||
} else {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(handle.callObjectMethod(name, signature));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// static method call wrapper
|
||||
template<typename RetT>
|
||||
struct static_caller {
|
||||
static_assert(!is_invalid_primitive_type<RetT>::value, "Using an incompatible primitive type!");
|
||||
template<typename... Args>
|
||||
static auto call(const char *className, const char *name, const char *signature, Args &&...args)
|
||||
{
|
||||
if constexpr (std::is_same_v<RetT, void>) {
|
||||
return QJniObject::callStaticMethod<RetT>(className, name, signature, std::forward<Args>(args)...);
|
||||
} else if constexpr (Jni::is_primitive_type<RetT>::value) {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(
|
||||
QJniObject::callStaticMethod<typename primitive_value<RetT>::JniType>(className, name, signature, std::forward<Args>(args)...));
|
||||
} else {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(QJniObject::callStaticObjectMethod(className, name, signature, std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
static auto call(const char *className, const char *name, const char *signature)
|
||||
{
|
||||
if constexpr (std::is_same_v<RetT, void>) {
|
||||
return QJniObject::callStaticMethod<RetT>(className, name, signature);
|
||||
} else if constexpr (Jni::is_primitive_type<RetT>::value) {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(
|
||||
QJniObject::callStaticMethod<typename primitive_value<RetT>::JniType>(className, name, signature));
|
||||
} else {
|
||||
return Internal::return_wrapper<RetT>::toReturnValue(QJniObject::callStaticObjectMethod(className, name, signature));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
///@endcond
|
||||
|
||||
/**
|
||||
* Wrap a JNI method call.
|
||||
* This will add a method named @p Name to the current class. Argument types are checked at compile time,
|
||||
* with the following inputs being accepted:
|
||||
* - primitive types have to match exactly
|
||||
* - non-primitive types can be either passed as @c QJniObject instance or with a type that has an
|
||||
* conversion registered with @c JNI_DECLARE_CONVERTER.
|
||||
*
|
||||
* The return type of the method is determined as follows:
|
||||
* - primitive types are returned directly
|
||||
* - non-primitive types without a registered type conversion are returned as @c QJniObject.
|
||||
* - non-primitive types with a registered type conversion are returned in a wrapper class that can
|
||||
* be implicitly converted either to the destination type of the conversion, or a @c QJniObject.
|
||||
* This allows to avoid type conversion when chaining calls for example, it however needs additional
|
||||
* care when used in combination with automatic type deduction.
|
||||
* - array return types also result in a wrapper class that can be implicitly converted to a sequential
|
||||
* container or a @p QJniObject representing the JNI array.
|
||||
*
|
||||
* Thie macro can only be placed in classes having the @c JNI_OBJECT macro.
|
||||
*
|
||||
* @param RetT The return type. Must either be a primitive type or a type declared with @c JNI_TYPE
|
||||
* @param Name The name of the method. Must match the JNI method to be called exactly.
|
||||
* @param Args A list or argument types (can be empty). Must either be primitive types or types declared
|
||||
* with @c JNI_TYPE.
|
||||
*/
|
||||
#define JNI_METHOD(RetT, Name, ...) \
|
||||
inline auto Name(JNI_PARAMS(__VA_ARGS__)) const \
|
||||
{ \
|
||||
using namespace KAndroidExtras; \
|
||||
return Internal::caller<RetT>::call(jniHandle(), "" #Name, Jni::signature<RetT(__VA_ARGS__)>() __VA_OPT__(, ) JNI_ARGS(__VA_ARGS__)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a JNI static method call.
|
||||
* This will add a static method named @p Name to the current class. Argument types are checked at compile time,
|
||||
* with the following inputs being accepted:
|
||||
* - primitive types have to match exactly
|
||||
* - non-primitive types can be either passed as @c QJniObject instance or with a type that has an
|
||||
* conversion registered with @c JNI_DECLARE_CONVERTER.
|
||||
*
|
||||
* The return type of the method is determined as follows:
|
||||
* - primitive types are returned directly
|
||||
* - non-primitive types without a registered type conversion are returned as @c QJniObject.
|
||||
* - non-primitive types with a registered type conversion are returned in a wrapper class that can
|
||||
* be implicitly converted either to the destination type of the conversion, or a @c QJniObject.
|
||||
* This allows to avoid type conversion when chaining calls for example, it however needs additional
|
||||
* care when used in combination with automatic type deduction.
|
||||
* - array return types also result in a wrapper class that can be implicitly converted to a sequential
|
||||
* container or a @p QJniObject representing the JNI array.
|
||||
*
|
||||
* Thie macro can only be placed in classes having the @c JNI_UNMANAGED_OBJECT or @c JNI_OBJECT macro.
|
||||
*
|
||||
* @param RetT The return type. Must either be a primitive type or a type declared with @c JNI_TYPE
|
||||
* @param Name The name of the method. Must match the JNI method to be called exactly.
|
||||
* @param Args A list or argument types (can be empty). Must either be primitive types or types declared
|
||||
* with @c JNI_TYPE.
|
||||
*/
|
||||
#define JNI_STATIC_METHOD(RetT, Name, ...) \
|
||||
static inline auto Name(JNI_PARAMS(__VA_ARGS__)) \
|
||||
{ \
|
||||
using namespace KAndroidExtras; \
|
||||
return Internal::static_caller<RetT>::call(Jni::typeName<_jni_ThisType>(), \
|
||||
"" #Name, \
|
||||
Jni::signature<RetT(__VA_ARGS__)>() __VA_OPT__(, ) JNI_ARGS(__VA_ARGS__)); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a JNI constructor call.
|
||||
* This will add a constructor named @p Name to the current class. Argument types are checked at compile time,
|
||||
* with the following inputs being accepted:
|
||||
* - primitive types have to match exactly
|
||||
* - non-primitive types can be either passed as @c QJniObject instance or with a type that has an
|
||||
* conversion registered with @c JNI_DECLARE_CONVERTER.
|
||||
*
|
||||
* Thie macro can only be placed in classes having @c JNI_OBJECT macro.
|
||||
*
|
||||
* @param Name The name of the method. Must match the JNI method to be called exactly.
|
||||
* @param Args A list or argument types (can be empty). Must either be primitive types or types declared
|
||||
* with @c JNI_TYPE.
|
||||
*/
|
||||
#define JNI_CONSTRUCTOR(Name, ...) \
|
||||
inline Name(JNI_PARAMS(__VA_ARGS__)) \
|
||||
{ \
|
||||
using namespace KAndroidExtras; \
|
||||
setJniHandle(QJniObject(Jni::typeName<_jni_ThisType>(), (const char *)Jni::signature<void(__VA_ARGS__)>() __VA_OPT__(, ) JNI_ARGS(__VA_ARGS__))); \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019-2021 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIOBJECT_H
|
||||
#define KANDROIDEXTRAS_JNIOBJECT_H
|
||||
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
namespace java
|
||||
{
|
||||
namespace lang
|
||||
{
|
||||
struct String;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
struct FromHandleTag {
|
||||
};
|
||||
}
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Object;
|
||||
|
||||
template<typename T>
|
||||
inline QJniObject handle(const T &wrapper)
|
||||
{
|
||||
return wrapper.jniHandle();
|
||||
}
|
||||
|
||||
/** Convert an untyped JNI object handle to a typed wrapper.
|
||||
* This is essentially the JNI equivalent to a reinterpret_cast from a void*.
|
||||
* Only use this if you are sure @p handle has the correct type, otherwise
|
||||
* things will horribly go wrong.
|
||||
*/
|
||||
template<typename T>
|
||||
inline auto fromHandle(const QJniObject &handle)
|
||||
{
|
||||
if constexpr (Jni::is_object_wrapper<T>::value) {
|
||||
return T(handle, Internal::FromHandleTag());
|
||||
} else {
|
||||
return Jni::Object<T>(handle);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline auto fromHandle(jobject handle)
|
||||
{
|
||||
return fromHandle<T>(QJniObject(handle));
|
||||
}
|
||||
|
||||
/** Wrapper for JNI objects with a convertible C++ type.
|
||||
* This provides implicit on-demand conversion to the C++ type, for types
|
||||
* that don't have a manually defined wrapper.
|
||||
*/
|
||||
template<typename T>
|
||||
class Object
|
||||
{
|
||||
private:
|
||||
template<typename DummyT>
|
||||
class _dummy_t
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
inline explicit Object(const QJniObject &v)
|
||||
: m_handle(v)
|
||||
{
|
||||
}
|
||||
|
||||
// implicit conversion from a compatible C++ type
|
||||
inline Object(const std::conditional_t<std::is_same_v<typename Jni::converter<T>::type, void>, _dummy_t<T>, typename Jni::converter<T>::type> &v)
|
||||
: m_handle(Jni::reverse_converter<T>::type::convert(v))
|
||||
{
|
||||
}
|
||||
|
||||
// implicit conversion from a custom wrapper for the same type
|
||||
template<typename WrapperT, typename = std::enable_if_t<std::is_same_v<typename WrapperT::_jni_BaseType, T>, WrapperT>>
|
||||
inline Object(const WrapperT &w)
|
||||
: m_handle(Jni::handle(w))
|
||||
{
|
||||
}
|
||||
|
||||
// special-case QString, as that often comes out of implicitly converted types,
|
||||
// and thus can't be consumed by another implicit conversion step
|
||||
template<typename StrT = QString, typename = std::enable_if_t<std::is_same_v<T, java::lang::String>, StrT>>
|
||||
inline Object(const QString &s)
|
||||
: m_handle(QJniObject::fromString(s))
|
||||
{
|
||||
}
|
||||
|
||||
// special case for null values
|
||||
inline Object(std::nullptr_t)
|
||||
: m_handle((jobject) nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
inline operator QJniObject() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
inline operator typename Jni::converter<T>::type() const
|
||||
{
|
||||
return Jni::converter<T>::convert(m_handle);
|
||||
}
|
||||
|
||||
inline QJniObject jniHandle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
// forward basic QJniObject API
|
||||
inline bool isValid() const
|
||||
{
|
||||
return m_handle.isValid();
|
||||
}
|
||||
template<typename StrT = QString, typename = std::enable_if_t<std::is_same_v<T, java::lang::String>, StrT>>
|
||||
inline QString toString() const
|
||||
{
|
||||
return m_handle.toString();
|
||||
}
|
||||
|
||||
private:
|
||||
QJniObject m_handle;
|
||||
};
|
||||
|
||||
/** Annotates a class for holding JNI method or property wrappers.
|
||||
*
|
||||
* Use this if the class only has static methods or constants. For methods
|
||||
* and properties, you either need to use @c JNI_OBJECT instead, or make
|
||||
* sure there is a @p jniHandle() method returning a @c QJniObject
|
||||
* representing the current instance.
|
||||
*
|
||||
* @param Class the name of the class this is added to.
|
||||
* @param BaseType the Java type this class represents, defined by the
|
||||
* @c JNI_TYPE or @c JNI_NESTED_TYPE macros.
|
||||
*/
|
||||
#define JNI_UNMANAGED_OBJECT(Class, BaseType) \
|
||||
public: \
|
||||
typedef Class _jni_ThisType; \
|
||||
typedef BaseType _jni_BaseType; \
|
||||
\
|
||||
private: \
|
||||
static inline constexpr const char *jniName() \
|
||||
{ \
|
||||
return KAndroidExtras::Jni::typeName<BaseType>(); \
|
||||
} \
|
||||
friend constexpr const char *KAndroidExtras::Jni::typeName<Class>();
|
||||
|
||||
/** Annotates a class for holding JNI method or property wrappers.
|
||||
*
|
||||
* @param Class the name of the class this is added to.
|
||||
* @param BaseType the Java type this class represents, defined by the
|
||||
* @c JNI_TYPE or @c JNI_NESTED_TYPE macros.
|
||||
*/
|
||||
#define JNI_OBJECT(Class, BaseType) \
|
||||
JNI_UNMANAGED_OBJECT(Class, BaseType) \
|
||||
private: \
|
||||
QJniObject _m_jni_handle; \
|
||||
inline QJniObject jniHandle() const \
|
||||
{ \
|
||||
return _m_jni_handle; \
|
||||
} \
|
||||
inline void setJniHandle(const QJniObject &h) \
|
||||
{ \
|
||||
_m_jni_handle = h; \
|
||||
} \
|
||||
friend QJniObject KAndroidExtras::Jni::handle<Class>(const Class &); \
|
||||
friend auto KAndroidExtras::Jni::fromHandle<Class>(const QJniObject &); \
|
||||
explicit inline Class(const QJniObject &handle, KAndroidExtras::Internal::FromHandleTag) \
|
||||
: _m_jni_handle(handle) \
|
||||
{ \
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIPP_H
|
||||
#define KANDROIDEXTRAS_JNIPP_H
|
||||
|
||||
/** @file jnipp.h
|
||||
* Preprocessor macro implementation details.
|
||||
*/
|
||||
|
||||
///@cond internal
|
||||
|
||||
// determine how many elements are in __VA_ARGS__
|
||||
#define JNI_PP_NARG(...) JNI_PP_NARG_(__VA_ARGS__ __VA_OPT__(, ) JNI_PP_RSEQ_N())
|
||||
#define JNI_PP_NARG_(...) JNI_PP_ARG_N(__VA_ARGS__)
|
||||
#define JNI_PP_ARG_N(_1, _2, _3, _4, _5, _6, _7, N, ...) N
|
||||
#define JNI_PP_RSEQ_N() 7, 6, 5, 4, 3, 2, 1, 0
|
||||
|
||||
// preprocessor-level token concat
|
||||
#define JNI_PP_CONCAT(arg1, arg2) JNI_PP_CONCAT1(arg1, arg2)
|
||||
#define JNI_PP_CONCAT1(arg1, arg2) JNI_PP_CONCAT2(arg1, arg2)
|
||||
#define JNI_PP_CONCAT2(arg1, arg2) arg1##arg2
|
||||
|
||||
///@endcond
|
||||
|
||||
#endif // KANDROIDEXTRAS_JNIPP_H
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIPRIMITIVETYPES_H
|
||||
#define KANDROIDEXTRAS_JNIPRIMITIVETYPES_H
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
|
||||
/** Type trait to check whether @tparam T is a primitive JNI type or an object type. */
|
||||
template<typename T>
|
||||
struct is_primitive_type : std::false_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jboolean> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jbyte> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jchar> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jshort> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jint> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jlong> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jfloat> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<jdouble> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_primitive_type<void> : std::true_type {
|
||||
};
|
||||
// special case for bool <-> jboolean conversion
|
||||
template<>
|
||||
struct is_primitive_type<bool> : std::true_type {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
/** Utility trait to check for basic C++ types that are not JNI primitive types. */
|
||||
template<typename T>
|
||||
struct is_invalid_primitive_type : std::false_type {
|
||||
};
|
||||
template<>
|
||||
struct is_invalid_primitive_type<uint8_t> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_invalid_primitive_type<char> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_invalid_primitive_type<uint32_t> : std::true_type {
|
||||
};
|
||||
template<>
|
||||
struct is_invalid_primitive_type<uint64_t> : std::true_type {
|
||||
};
|
||||
|
||||
// C++ primitive to JNI primitive conversion
|
||||
template<typename T>
|
||||
struct primitive_value {
|
||||
static_assert(!is_invalid_primitive_type<T>::value, "Using an incompatible primitive type!");
|
||||
typedef T JniType;
|
||||
typedef T NativeType;
|
||||
static constexpr inline T toJni(T value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
static constexpr inline T fromJni(T value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct primitive_value<void> {
|
||||
};
|
||||
template<>
|
||||
struct primitive_value<jboolean> {
|
||||
typedef jboolean JniType;
|
||||
typedef bool NativeType;
|
||||
static constexpr inline jboolean toJni(bool value)
|
||||
{
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
static constexpr inline bool fromJni(jboolean value)
|
||||
{
|
||||
return value != 0;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct primitive_value<bool> {
|
||||
typedef jboolean JniType;
|
||||
typedef bool NativeType;
|
||||
static constexpr inline jboolean toJni(bool value)
|
||||
{
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
static constexpr inline bool fromJni(jboolean value)
|
||||
{
|
||||
return value != 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIPROPERTIES_H
|
||||
#define KANDROIDEXTRAS_JNIPROPERTIES_H
|
||||
|
||||
#include "jniargument.h"
|
||||
#include "jniobject.h"
|
||||
#include "jnisignature.h"
|
||||
#include "jnitypes.h"
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
template<typename T>
|
||||
class Array;
|
||||
}
|
||||
|
||||
/** @cond internal */
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
/** Wrapper for static properties. */
|
||||
template<typename PropType, typename ClassType, typename NameHolder, bool PrimitiveType>
|
||||
struct StaticProperty {
|
||||
};
|
||||
template<typename PropType, typename ClassType, typename NameHolder>
|
||||
struct StaticProperty<PropType, ClassType, NameHolder, false> {
|
||||
static_assert(!is_invalid_primitive_type<PropType>::value, "Using an incompatible primitive type!");
|
||||
inline QJniObject get() const
|
||||
{
|
||||
return QJniObject::getStaticObjectField(Jni::typeName<ClassType>(), Jni::typeName<NameHolder>(), Jni::signature<PropType>());
|
||||
}
|
||||
inline operator QJniObject() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
inline operator typename Jni::converter<PropType>::type() const
|
||||
{
|
||||
return Jni::converter<PropType>::convert(get());
|
||||
}
|
||||
template<typename RetT = PropType, typename = std::enable_if_t<Jni::is_generic_wrapper<PropType>::value, RetT>>
|
||||
inline operator Jni::Object<PropType>() const
|
||||
{
|
||||
return Jni::Object<PropType>(get());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PropType, typename ClassType, typename NameHolder>
|
||||
struct StaticProperty<PropType, ClassType, NameHolder, true> {
|
||||
inline operator auto() const
|
||||
{
|
||||
return primitive_value<PropType>::fromJni(
|
||||
QJniObject::getStaticField<typename primitive_value<PropType>::JniType>(Jni::typeName<ClassType>(), Jni::typeName<NameHolder>()));
|
||||
}
|
||||
};
|
||||
|
||||
/** Shared code for non-static property wrappers. */
|
||||
template<typename ClassType, typename OffsetHolder>
|
||||
class PropertyBase
|
||||
{
|
||||
protected:
|
||||
inline QJniObject handle() const
|
||||
{
|
||||
const auto owner = reinterpret_cast<const ClassType *>(reinterpret_cast<const char *>(this) - OffsetHolder::offset());
|
||||
return owner->jniHandle();
|
||||
}
|
||||
};
|
||||
|
||||
/** Wrapper for non-static properties. */
|
||||
template<typename PropType, typename ClassType, typename NameHolder, typename OffsetHolder, bool PrimitiveType>
|
||||
struct Property {
|
||||
};
|
||||
template<typename PropType, typename ClassType, typename NameHolder, typename OffsetHolder>
|
||||
class Property<PropType, ClassType, NameHolder, OffsetHolder, false> : public PropertyBase<ClassType, OffsetHolder>
|
||||
{
|
||||
private:
|
||||
struct _jni_NoType {
|
||||
};
|
||||
static_assert(!is_invalid_primitive_type<PropType>::value, "Using an incompatible primitive type!");
|
||||
|
||||
public:
|
||||
inline QJniObject get() const
|
||||
{
|
||||
return this->handle().getObjectField(Jni::typeName<NameHolder>(), Jni::signature<PropType>());
|
||||
}
|
||||
inline operator QJniObject() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
inline operator typename Jni::converter<PropType>::type() const
|
||||
{
|
||||
return Jni::converter<PropType>::convert(get());
|
||||
}
|
||||
template<typename RetT = PropType, typename = std::enable_if_t<Jni::is_array<PropType>::value, RetT>>
|
||||
inline operator PropType() const
|
||||
{
|
||||
return PropType(get());
|
||||
}
|
||||
template<typename RetT = PropType, typename = std::enable_if_t<Jni::is_generic_wrapper<PropType>::value, RetT>>
|
||||
inline operator Jni::Object<PropType>() const
|
||||
{
|
||||
return Jni::Object<PropType>(get());
|
||||
}
|
||||
|
||||
inline Property &operator=(typename Internal::argument<PropType>::type value)
|
||||
{
|
||||
this->handle().setField(Jni::typeName<NameHolder>(), Jni::signature<PropType>(), Internal::argument<PropType>::toCallArgument(value));
|
||||
return *this;
|
||||
}
|
||||
inline Property &operator=(const QJniObject &value)
|
||||
{
|
||||
this->handle().setField(Jni::typeName<NameHolder>(), Jni::signature<PropType>(), value.object());
|
||||
return *this;
|
||||
}
|
||||
inline Property &operator=(const typename std::conditional<std::is_same_v<typename Jni::converter<PropType>::type, void>,
|
||||
_jni_NoType,
|
||||
typename Jni::converter<PropType>::type>::type &value)
|
||||
{
|
||||
this->handle().setField(Jni::typeName<NameHolder>(), Jni::signature<PropType>(), Jni::reverse_converter<PropType>::type::convert(value).object());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// special case for string comparison, which is often done against different types and thus the implicit conversion operator
|
||||
// isn't going to be enough
|
||||
template<typename CmpT, typename = std::enable_if_t<std::is_same_v<PropType, java::lang::String>, CmpT>>
|
||||
inline bool operator==(const CmpT &other) const
|
||||
{
|
||||
return QString(*this) == other;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PropType, typename ClassType, typename NameHolder, typename OffsetHolder>
|
||||
class Property<PropType, ClassType, NameHolder, OffsetHolder, true> : public PropertyBase<ClassType, OffsetHolder>
|
||||
{
|
||||
public:
|
||||
inline operator auto() const
|
||||
{
|
||||
return primitive_value<PropType>::fromJni(this->handle().template getField<typename primitive_value<PropType>::JniType>(Jni::typeName<NameHolder>()));
|
||||
}
|
||||
inline Property &operator=(PropType value)
|
||||
{
|
||||
this->handle().setField(Jni::typeName<NameHolder>(), primitive_value<PropType>::toJni(value));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO KF6: can be replaced by QT_WARNING_DISABLE_INVALID_OFFSETOF
|
||||
#if defined(Q_CC_CLANG)
|
||||
#define JNI_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_CLANG("-Winvalid-offsetof")
|
||||
#elif defined(Q_CC_GNU)
|
||||
#define JNI_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_GCC("-Winvalid-offsetof")
|
||||
#else
|
||||
#define JNI_WARNING_DISABLE_INVALID_OFFSETOF
|
||||
#endif
|
||||
|
||||
/** @endcond */
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a static final property.
|
||||
* This will add a public static member named @p name to the current class. This member defines an
|
||||
* implicit conversion operator which will trigger the corresponding a JNI read operation.
|
||||
* Can only be placed in classes with a @c JNI_OBJECT.
|
||||
*
|
||||
* @note Make sure to access this member with a specific type, assigning to an @c auto variable will
|
||||
* copy the wrapper type, not read the property value.
|
||||
*
|
||||
* @param type The data type of the property.
|
||||
* @param name The name of the property.
|
||||
*/
|
||||
#define JNI_CONSTANT(type, name) \
|
||||
private: \
|
||||
struct _jni_##name##__NameHolder { \
|
||||
static constexpr const char *jniName() \
|
||||
{ \
|
||||
return "" #name; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
public: \
|
||||
static inline const KAndroidExtras::Internal::StaticProperty<type, _jni_ThisType, _jni_##name##__NameHolder, Jni::is_primitive_type<type>::value> name;
|
||||
|
||||
/**
|
||||
* Wrap a member property.
|
||||
* This will add a public zero-size member named @p name to the current class. This member defines an
|
||||
* implicit conversion operator which will trigger the corresponding a JNI read operation, as well
|
||||
* as an overloaded assignment operator for the corresponding write operation.
|
||||
* Can only be placed in classes with a @c JNI_OBJECT.
|
||||
*
|
||||
* @note Make sure to access this member with a specific type, assigning to an @c auto variable will
|
||||
* copy the wrapper type, not read the property value.
|
||||
*
|
||||
* @param type The data type of the property.
|
||||
* @param name The name of the property.
|
||||
*/
|
||||
#define JNI_PROPERTY(type, name) \
|
||||
private: \
|
||||
struct _jni_##name##__NameHolder { \
|
||||
static constexpr const char *jniName() \
|
||||
{ \
|
||||
return "" #name; \
|
||||
} \
|
||||
}; \
|
||||
struct _jni_##name##__OffsetHolder { \
|
||||
static constexpr std::size_t offset() \
|
||||
{ \
|
||||
QT_WARNING_PUSH JNI_WARNING_DISABLE_INVALID_OFFSETOF return offsetof(_jni_ThisType, name); \
|
||||
QT_WARNING_POP \
|
||||
} \
|
||||
}; \
|
||||
friend class KAndroidExtras::Internal::PropertyBase<_jni_ThisType, _jni_##name##__OffsetHolder>; \
|
||||
\
|
||||
public: \
|
||||
[[no_unique_address]] KAndroidExtras::Internal:: \
|
||||
Property<type, _jni_ThisType, _jni_##name##__NameHolder, _jni_##name##__OffsetHolder, KAndroidExtras::Jni::is_primitive_type<type>::value> name;
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_JNIPROPERTIES_H
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021-2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNIRETURNVALUE_H
|
||||
#define KANDROIDEXTRAS_JNIRETURNVALUE_H
|
||||
|
||||
#include "jniobject.h"
|
||||
#include "jnitypetraits.h"
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
namespace Jni
|
||||
{
|
||||
template<typename T>
|
||||
class Array;
|
||||
}
|
||||
|
||||
///@cond internal
|
||||
namespace Internal
|
||||
{
|
||||
/** Return value wrapping helper. */
|
||||
template<typename RetT, typename = std::void_t<>>
|
||||
class return_wrapper
|
||||
{
|
||||
static_assert(!is_invalid_primitive_type<RetT>::value, "Using an incompatible primitive type!");
|
||||
static inline constexpr bool is_primitive = Jni::is_primitive_type<RetT>::value;
|
||||
static inline constexpr bool is_convertible = !std::is_same_v<typename Jni::converter<RetT>::type, void>;
|
||||
|
||||
typedef std::conditional_t<is_primitive, RetT, QJniObject> JniReturnT;
|
||||
|
||||
public:
|
||||
static inline constexpr auto toReturnValue(JniReturnT value)
|
||||
{
|
||||
if constexpr (is_convertible) {
|
||||
return Jni::Object<RetT>(value);
|
||||
} else if constexpr (is_primitive) {
|
||||
return primitive_value<RetT>::fromJni(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
||||
template<typename RetT>
|
||||
class return_wrapper<RetT, std::void_t<typename RetT::_jni_ThisType>>
|
||||
{
|
||||
public:
|
||||
static inline auto toReturnValue(const QJniObject &value)
|
||||
{
|
||||
return Jni::fromHandle<RetT>(value);
|
||||
}
|
||||
};
|
||||
template<typename RetT>
|
||||
class return_wrapper<Jni::Array<RetT>>
|
||||
{
|
||||
public:
|
||||
static inline auto toReturnValue(const QJniObject &value)
|
||||
{
|
||||
return Jni::Array<RetT>(value);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct return_wrapper<void> {
|
||||
};
|
||||
}
|
||||
///@endcond
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNISIGNATURE_H
|
||||
#define KANDROIDEXTRAS_JNISIGNATURE_H
|
||||
|
||||
#include "jnitypes.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
template<typename T>
|
||||
class Array;
|
||||
}
|
||||
|
||||
/** @cond internal */
|
||||
namespace Internal
|
||||
{
|
||||
|
||||
/** Compile-time concat-able string. */
|
||||
template<char... String>
|
||||
struct StaticString {
|
||||
inline operator const char *() const
|
||||
{
|
||||
static const char data[] = {String..., 0};
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
/** Compile-time strlen. */
|
||||
constexpr inline int static_strlen(const char *str)
|
||||
{
|
||||
return str[0] == '\0' ? 0 : static_strlen(str + 1) + 1;
|
||||
}
|
||||
|
||||
/** Compile-time concat for two StaticString. */
|
||||
template<char... String1, char... String2>
|
||||
constexpr inline auto static_concat(const StaticString<String1...> &, const StaticString<String2...> &)
|
||||
{
|
||||
return StaticString<String1..., String2...>();
|
||||
}
|
||||
|
||||
/** Compile-time concept for N StaticString. */
|
||||
template<typename String1, typename String2, class... Strings>
|
||||
constexpr inline auto static_concat(const String1 &str1, const String2 &str2, const Strings &...strs)
|
||||
{
|
||||
return static_concat(static_concat(str1, str2), strs...);
|
||||
}
|
||||
|
||||
/** Conversion from const char* literals to StaticString. */
|
||||
template<typename, typename>
|
||||
struct staticStringFromJniType;
|
||||
template<typename T, std::size_t... Indexes>
|
||||
struct staticStringFromJniType<T, std::index_sequence<Indexes...>> {
|
||||
typedef StaticString<Jni::typeName<T>()[Indexes]...> value;
|
||||
};
|
||||
|
||||
/** Meta function for assembling JNI signatures. */
|
||||
template<typename T>
|
||||
struct JniSignature {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
using namespace Internal;
|
||||
return static_concat(StaticString<'L'>(),
|
||||
typename staticStringFromJniType<T, std::make_index_sequence<static_strlen(Jni::typeName<T>())>>::value(),
|
||||
StaticString<';'>());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct JniSignature<jboolean> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'Z'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jbyte> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'B'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jchar> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'C'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jshort> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'S'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jint> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'I'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jlong> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'J'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jfloat> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'F'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<jdouble> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'D'>();
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct JniSignature<void> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'V'>();
|
||||
}
|
||||
};
|
||||
// special case due to jboolean != bool
|
||||
template<>
|
||||
struct JniSignature<bool> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
return StaticString<'Z'>();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct JniSignature<T *> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
using namespace Internal;
|
||||
return static_concat(StaticString<'['>(), JniSignature<T>()());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct JniSignature<Jni::Array<T>> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
using namespace Internal;
|
||||
return static_concat(StaticString<'['>(), JniSignature<T>()());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename RetT, typename... Args>
|
||||
struct JniSignature<RetT(Args...)> {
|
||||
constexpr inline auto operator()() const
|
||||
{
|
||||
using namespace Internal;
|
||||
return static_concat(StaticString<'('>(), JniSignature<Args>()()..., StaticString<')'>(), JniSignature<RetT>()());
|
||||
}
|
||||
};
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
/** Helper methods to deal with JNI. */
|
||||
namespace Jni
|
||||
{
|
||||
/** Returns the JNI signature string for the template argument types. */
|
||||
template<typename... Args>
|
||||
constexpr __attribute__((__unused__)) Internal::JniSignature<Args...> signature = {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_JNISIGNATURE_H
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNITYPES_H
|
||||
#define KANDROIDEXTRAS_JNITYPES_H
|
||||
|
||||
#include "jnipp.h"
|
||||
|
||||
/** C++/Android integration utilities built on top of @c QJniObject. */
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
///@cond internal
|
||||
|
||||
// preprocessor "iteration" for regular classes
|
||||
#define JNI_TYPE_1(name, type, ...) \
|
||||
struct type { \
|
||||
static constexpr const char *jniName() \
|
||||
{ \
|
||||
return name #type; \
|
||||
} \
|
||||
};
|
||||
#define JNI_TYPE_2(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_1(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_3(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_2(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_4(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_3(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_5(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_4(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_6(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_5(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_7(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_TYPE_6(#type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_TYPE_(N, name, ...) JNI_PP_CONCAT(JNI_TYPE_, N)(name, __VA_ARGS__)
|
||||
|
||||
// preprocessor "iteration" for nested classes
|
||||
#define JNI_NESTED_TYPE_2(name, type, nested_type, ...) \
|
||||
struct type##_##nested_type { \
|
||||
static constexpr const char *jniName() \
|
||||
{ \
|
||||
return name #type "$" #nested_type; \
|
||||
} \
|
||||
};
|
||||
#define JNI_NESTED_TYPE_3(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_NESTED_TYPE_2(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_NESTED_TYPE_4(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_NESTED_TYPE_3(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_NESTED_TYPE_5(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_NESTED_TYPE_4(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_NESTED_TYPE_6(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_NESTED_TYPE_5(name #type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_NESTED_TYPE_7(name, type, ...) \
|
||||
namespace type \
|
||||
{ \
|
||||
JNI_NESTED_TYPE_6(#type "/", __VA_ARGS__) \
|
||||
}
|
||||
#define JNI_NESTED_TYPE_(N, name, ...) JNI_PP_CONCAT(JNI_NESTED_TYPE_, N)(name, __VA_ARGS__)
|
||||
|
||||
///@endcond
|
||||
|
||||
/** Macro to define Java types with their corresponding JNI signature strings. */
|
||||
#define JNI_TYPE(...) JNI_TYPE_(JNI_PP_NARG(__VA_ARGS__), "", __VA_ARGS__)
|
||||
|
||||
/** Macro to define a nested Java class with its corresponding JNI signature string. */
|
||||
#define JNI_NESTED_TYPE(...) JNI_NESTED_TYPE_(JNI_PP_NARG(__VA_ARGS__), "", __VA_ARGS__)
|
||||
|
||||
/** Functions for interfacing with the Java Native Interface (JNI). */
|
||||
namespace Jni
|
||||
{
|
||||
/** Returns the JNI type name of the given template argument. */
|
||||
template<typename T>
|
||||
inline constexpr const char *typeName()
|
||||
{
|
||||
return T::jniName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // KANDROIDEXTRAS_JNITYPES_H
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KANDROIDEXTRAS_JNITYPETRAITS_H
|
||||
#define KANDROIDEXTRAS_JNITYPETRAITS_H
|
||||
|
||||
#include "jniprimitivetypes.h"
|
||||
#include "jnitypes.h"
|
||||
|
||||
#include <QJniObject>
|
||||
|
||||
namespace KAndroidExtras
|
||||
{
|
||||
|
||||
namespace Jni
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Array;
|
||||
|
||||
/** Type conversion trait, see @c JNI_DECLARE_CONVERTER. */
|
||||
template<typename T>
|
||||
struct converter {
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct reverse_converter {
|
||||
typedef converter<typename converter<T>::type> type;
|
||||
};
|
||||
|
||||
/** Type trait for checking whether @tparam T is a JNI array type. */
|
||||
template<typename T>
|
||||
struct is_array : std::false_type {
|
||||
};
|
||||
template<typename T>
|
||||
struct is_array<Array<T>> : std::true_type {
|
||||
};
|
||||
|
||||
/** Type trais for checking whether @tparam T is a JNI object wrapper type. */
|
||||
template<typename T, typename = std::void_t<>>
|
||||
struct is_object_wrapper : std::false_type {
|
||||
};
|
||||
template<typename T>
|
||||
struct is_object_wrapper<T, std::void_t<typename T::_jni_ThisType>> : std::true_type {
|
||||
};
|
||||
|
||||
/** Type trais for checking whether @tparam T is needs the generic JNI object wrapper (Jni::Object). */
|
||||
template<typename T>
|
||||
struct is_generic_wrapper
|
||||
: std::conditional_t<!is_primitive_type<T>::value && !is_array<T>::value && !is_object_wrapper<T>::value, std::true_type, std::false_type> {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Declare a JNI type to be convertible to a native type.
|
||||
* @param JniType A type declared with @p JNI_TYPE.
|
||||
* @param NativeType A C++ type @p JniType can be converted to/from.
|
||||
* @param FromJniFn Code converting a @c QJniObject @c value to @p NativeType.
|
||||
* @param ToJniCode converting a @p NativeType @c value to a QJniObject.
|
||||
*/
|
||||
#define JNI_DECLARE_CONVERTER(JniType, NativeType, FromJniFn, ToJniFn) \
|
||||
namespace Jni \
|
||||
{ \
|
||||
template<> \
|
||||
struct converter<NativeType> { \
|
||||
typedef JniType type; \
|
||||
static inline QJniObject convert(const NativeType &value) \
|
||||
{ \
|
||||
return (ToJniFn); \
|
||||
} \
|
||||
}; \
|
||||
template<> \
|
||||
struct converter<JniType> { \
|
||||
typedef NativeType type; \
|
||||
static inline NativeType convert(const QJniObject &value) \
|
||||
{ \
|
||||
return (FromJniFn); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <KNotification>
|
||||
#include <KNotificationPermission>
|
||||
#include <KNotificationReplyAction>
|
||||
|
||||
#include <QPainter>
|
||||
@@ -23,7 +24,6 @@
|
||||
#include "controller.h"
|
||||
#include "neochatconnection.h"
|
||||
#include "neochatroom.h"
|
||||
#include "permissionmanager.h"
|
||||
#include "roommanager.h"
|
||||
#include "texthandler.h"
|
||||
#include "windowcontroller.h"
|
||||
@@ -43,7 +43,7 @@ NotificationsManager::NotificationsManager(QObject *parent)
|
||||
|
||||
void NotificationsManager::handleNotifications(QPointer<NeoChatConnection> connection)
|
||||
{
|
||||
if (!PermissionManager::instance().checkPermission(Permission::PostNotification)) {
|
||||
if (KNotificationPermission::checkPermission() != Qt::PermissionStatus::Granted) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "permissionmanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include "private/qandroidextras_p.h"
|
||||
#include <KAndroidExtras/ManifestPermission>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
static QString permissionName(Permission::Permission p)
|
||||
{
|
||||
using namespace KAndroidExtras;
|
||||
switch (p) {
|
||||
case Permission::InvalidPermission:
|
||||
Q_UNREACHABLE();
|
||||
case Permission::ReadCalendar:
|
||||
return ManifestPermission::READ_CALENDAR;
|
||||
case Permission::WriteCalendar:
|
||||
return ManifestPermission::WRITE_CALENDAR;
|
||||
case Permission::PostNotification: // only for SDK >= 33
|
||||
return ManifestPermission::POST_NOTIFICATIONS;
|
||||
case Permission::Camera:
|
||||
return ManifestPermission::CAMERA;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PermissionManager &PermissionManager::instance()
|
||||
{
|
||||
static PermissionManager _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
PermissionManager::PermissionManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool PermissionManager::checkPermission(Permission::Permission permission)
|
||||
{
|
||||
if (permission == Permission::InvalidPermission) {
|
||||
qWarning() << "check for invalid permission - check your QML code!";
|
||||
return false;
|
||||
}
|
||||
#ifdef Q_OS_ANDROID
|
||||
if (permission == Permission::PostNotification && QtAndroidPrivate::androidSdkVersion() < 33) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return QtAndroidPrivate::checkPermission(permissionName(permission)).result() == QtAndroidPrivate::PermissionResult::Authorized;
|
||||
#else // non-Android
|
||||
Q_UNUSED(permission);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PermissionManager::requestPermission(Permission::Permission permission, QJSValue callback)
|
||||
{
|
||||
if (permission == Permission::InvalidPermission) {
|
||||
qWarning() << "request for invalid permission - check your QML code!";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << permission;
|
||||
// already got the permission
|
||||
if (PermissionManager::checkPermission(permission)) {
|
||||
callback.call();
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
// TODO make this properly async
|
||||
if (QtAndroidPrivate::checkPermission(permissionName(permission)).result() != QtAndroidPrivate::PermissionResult::Authorized) {
|
||||
if (QtAndroidPrivate::requestPermission(permissionName(permission)).result() != QtAndroidPrivate::PermissionResult::Authorized) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback.call();
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "moc_permissionmanager.cpp"
|
||||
@@ -1,44 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Volker Krause <vkrause@kde.org>
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
/** Permission enum for use in QML. */
|
||||
namespace Permission
|
||||
{
|
||||
Q_NAMESPACE
|
||||
enum Permission {
|
||||
InvalidPermission, // captures QML errors resulting in "0" enum values
|
||||
ReadCalendar,
|
||||
WriteCalendar,
|
||||
PostNotification,
|
||||
Camera,
|
||||
};
|
||||
Q_ENUM_NS(Permission)
|
||||
}
|
||||
|
||||
/** Check and request platform permissions for access to controlled resources (calendar, location, etc). */
|
||||
class PermissionManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
public:
|
||||
static PermissionManager &instance();
|
||||
static PermissionManager *create(QQmlEngine *engine, QJSEngine *)
|
||||
{
|
||||
engine->setObjectOwnership(&instance(), QQmlEngine::CppOwnership);
|
||||
return &instance();
|
||||
}
|
||||
|
||||
Q_INVOKABLE static bool checkPermission(Permission::Permission permission);
|
||||
Q_INVOKABLE static void requestPermission(Permission::Permission permission, QJSValue callback);
|
||||
|
||||
private:
|
||||
explicit PermissionManager(QObject *parent = nullptr);
|
||||
};
|
||||
Reference in New Issue
Block a user