File: android.cpp

package info (click to toggle)
syncthingtray 2.0.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,124 kB
  • sloc: cpp: 34,081; xml: 1,705; java: 1,258; sh: 97; javascript: 54; makefile: 25
file content (151 lines) | stat: -rw-r--r-- 6,274 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "./android.h"

#include "./app.h"
#include "./appservice.h"

#include <QJniEnvironment>
#include <QtCore/private/qandroidextras_p.h>

namespace QtGui {

/// \brief The JniFn namespace defines functions called from Java.
namespace JniFn {
static AppService *appServiceObjectForJava = nullptr;
static App *appObjectForJava = nullptr;

static void loadQtQuickGui(JNIEnv *, jobject)
{
    QMetaObject::invokeMethod(appObjectForJava, "initEngine", Qt::QueuedConnection);
}

static void unloadQtQuickGui(JNIEnv *, jobject)
{
    QMetaObject::invokeMethod(appObjectForJava, "destroyEngine", Qt::QueuedConnection);
}

static void openUrlExternally(JNIEnv *, jobject, jstring url)
{
    QMetaObject::invokeMethod(
        appObjectForJava, "openUrlExternally", Qt::QueuedConnection, Q_ARG(QUrl, QJniObject(url).toString()), Q_ARG(bool, true));
}

static void stopLibSyncthing(JNIEnv *, jobject)
{
    QMetaObject::invokeMethod(appServiceObjectForJava, "stopLibSyncthing", Qt::QueuedConnection);
}

static void handleMessageFromService(JNIEnv *, jobject, jint what, jint arg1, jint arg2, jstring str, jbyteArray variantArray)
{
    auto env = QJniEnvironment();
    auto variantSize = variantArray ? env->GetArrayLength(variantArray) : 0;
    auto variant = QByteArray(variantSize, Qt::Initialization::Uninitialized);
    if (variantArray) {
        env->GetByteArrayRegion(variantArray, 0, variantSize, reinterpret_cast<jbyte *>(variant.data()));
    }
    appObjectForJava->handleMessageFromService(static_cast<ActivityAction>(what), arg1, arg2, QJniObject(str).toString(), variant);
}

static void broadcastLauncherStatus(JNIEnv *, jobject)
{
    QMetaObject::invokeMethod(appServiceObjectForJava, "broadcastLauncherStatus", Qt::QueuedConnection);
}

static void handleLauncherStatusBroadcast(JNIEnv *, jobject, jobject intent)
{
    const auto status = QAndroidIntent(QJniObject(intent)).extraVariant(QStringLiteral("status"));
    QMetaObject::invokeMethod(appObjectForJava, "handleLauncherStatusBroadcast", Qt::QueuedConnection, Q_ARG(QVariant, status));
}

static void handleMessageFromActivity(JNIEnv *, jobject, jint what, jint arg1, jint arg2, jstring str)
{
    appServiceObjectForJava->handleMessageFromActivity(static_cast<ServiceAction>(what), arg1, arg2, QJniObject(str).toString());
}

static void handleAndroidIntent(JNIEnv *, jobject, jstring page, jboolean fromNotification)
{
    QMetaObject::invokeMethod(
        appObjectForJava, "handleAndroidIntent", Qt::QueuedConnection, Q_ARG(QString, QJniObject(page).toString()), Q_ARG(bool, fromNotification));
}

static void handleStoragePermissionChanged(JNIEnv *, jobject, jboolean storagePermissionGranted)
{
    QMetaObject::invokeMethod(appObjectForJava, "handleStoragePermissionChanged", Qt::QueuedConnection, Q_ARG(bool, storagePermissionGranted));
}

static void handleNotificationPermissionChanged(JNIEnv *, jobject, jboolean notificationPermissionGranted)
{
    QMetaObject::invokeMethod(
        appObjectForJava, "handleNotificationPermissionChanged", Qt::QueuedConnection, Q_ARG(bool, notificationPermissionGranted));
}

static bool returnFalse(JNIEnv *, jobject)
{
    return false;
}

void registerServiceJniMethods(AppService *appService)
{
    if (JniFn::appServiceObjectForJava) {
        return;
    }
    qDebug() << "Registering service JNI methods";
    JniFn::appServiceObjectForJava = appService;
    auto env = QJniEnvironment();
    auto registeredMethods = true;
    static const JNINativeMethod serviceMethods[] = {
        { "stopLibSyncthing", "()V", reinterpret_cast<void *>(JniFn::stopLibSyncthing) },
        { "handleMessageFromActivity", "(IIILjava/lang/String;)V", reinterpret_cast<void *>(JniFn::handleMessageFromActivity) },
        { "broadcastLauncherStatus", "()V", reinterpret_cast<void *>(JniFn::broadcastLauncherStatus) },
    };
    registeredMethods = env.registerNativeMethods("io/github/martchus/syncthingtray/SyncthingService", serviceMethods, 3) && registeredMethods;
    if (!registeredMethods) {
        qWarning() << "Unable to register all native service methods in JNI environment.";
    }
}

void unregisterServiceJniMethods(AppService *appService)
{
    if (JniFn::appServiceObjectForJava == appService) {
        JniFn::appServiceObjectForJava = nullptr;
    }
}

void registerActivityJniMethods(App *app)
{
    if (JniFn::appObjectForJava) {
        return;
    }
    qDebug() << "Registering activity JNI methods";
    JniFn::appObjectForJava = app;
    auto env = QJniEnvironment();
    auto registeredMethods = true;
    static const JNINativeMethod activityMethods[] = {
        { "handleLauncherStatusBroadcast", "(Landroid/content/Intent;)V", reinterpret_cast<void *>(JniFn::handleLauncherStatusBroadcast) },
        { "handleMessageFromService", "(IIILjava/lang/String;[B)V", reinterpret_cast<void *>(JniFn::handleMessageFromService) },
        { "handleAndroidIntent", "(Ljava/lang/String;Z)V", reinterpret_cast<void *>(JniFn::handleAndroidIntent) },
        { "handleStoragePermissionChanged", "(Z)V", reinterpret_cast<void *>(JniFn::handleStoragePermissionChanged) },
        { "handleNotificationPermissionChanged", "(Z)V", reinterpret_cast<void *>(JniFn::handleNotificationPermissionChanged) },
        { "loadQtQuickGui", "()V", reinterpret_cast<void *>(JniFn::loadQtQuickGui) },
        { "unloadQtQuickGui", "()V", reinterpret_cast<void *>(JniFn::unloadQtQuickGui) },
        { "openUrlExternally", "(Ljava/lang/String;)V", reinterpret_cast<void *>(JniFn::openUrlExternally) },
    };
    static const JNINativeMethod delegateMethods[] = {
        { "canOverrideColorSchemeHint", "()Z", reinterpret_cast<void *>(JniFn::returnFalse) },
    };
    registeredMethods = env.registerNativeMethods("io/github/martchus/syncthingtray/Activity", activityMethods, 8) && registeredMethods;
    registeredMethods = env.registerNativeMethods("org/qtproject/qt/android/QtActivityDelegateBase", delegateMethods, 1) && registeredMethods;
    if (!registeredMethods) {
        qWarning() << "Unable to register all native activity methods in JNI environment.";
    }
}

void unregisterActivityJniMethods(App *app)
{
    if (JniFn::appObjectForJava == app) {
        JniFn::appObjectForJava = nullptr;
    }
}

} // namespace JniFn

} // namespace QtGui