forked from fyne-io/fyne
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp_mobile_and.c
130 lines (100 loc) · 5.34 KB
/
app_mobile_and.c
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
//go:build !ci && android
#include <android/log.h>
#include <jni.h>
#include <stdbool.h>
#include <stdlib.h>
#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Fyne", __VA_ARGS__)
static jclass find_class(JNIEnv *env, const char *class_name) {
jclass clazz = (*env)->FindClass(env, class_name);
if (clazz == NULL) {
(*env)->ExceptionClear(env);
LOG_FATAL("cannot find %s", class_name);
return NULL;
}
return clazz;
}
static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
if (m == 0) {
(*env)->ExceptionClear(env);
LOG_FATAL("cannot find method %s %s", name, sig);
return 0;
}
return m;
}
static jmethodID find_static_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) {
jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig);
if (m == 0) {
(*env)->ExceptionClear(env);
LOG_FATAL("cannot find method %s %s", name, sig);
return 0;
}
return m;
}
jobject getSystemService(uintptr_t jni_env, uintptr_t ctx, char *service) {
JNIEnv *env = (JNIEnv*)jni_env;
jstring serviceStr = (*env)->NewStringUTF(env, service);
jclass ctxClass = (*env)->GetObjectClass(env, (jobject)ctx);
jmethodID getSystemService = find_method(env, ctxClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
return (jobject)(*env)->CallObjectMethod(env, (jobject)ctx, getSystemService, serviceStr);
}
int nextId = 1;
bool isOreoOrLater(JNIEnv *env) {
jclass versionClass = find_class(env, "android/os/Build$VERSION" );
jfieldID sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I" );
int sdkVersion = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID );
return sdkVersion >= 26; // O = Oreo, will not be defined for older builds
}
jobject parseURL(uintptr_t jni_env, uintptr_t ctx, char* uriCstr) {
JNIEnv *env = (JNIEnv*)jni_env;
jstring uriStr = (*env)->NewStringUTF(env, uriCstr);
jclass uriClass = find_class(env, "android/net/Uri");
jmethodID parse = find_static_method(env, uriClass, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
return (jobject)(*env)->CallStaticObjectMethod(env, uriClass, parse, uriStr);
}
void openURL(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *url) {
JNIEnv *env = (JNIEnv*)jni_env;
jobject uri = parseURL(jni_env, ctx, url);
jclass intentClass = find_class(env, "android/content/Intent");
jfieldID viewFieldID = (*env)->GetStaticFieldID(env, intentClass, "ACTION_VIEW", "Ljava/lang/String;" );
jstring view = (*env)->GetStaticObjectField(env, intentClass, viewFieldID);
jmethodID constructor = find_method(env, intentClass, "<init>", "(Ljava/lang/String;Landroid/net/Uri;)V");
jobject intent = (*env)->NewObject(env, intentClass, constructor, view, uri);
jclass contextClass = find_class(env, "android/content/Context");
jmethodID start = find_method(env, contextClass, "startActivity", "(Landroid/content/Intent;)V");
(*env)->CallVoidMethod(env, (jobject)ctx, start, intent);
}
void sendNotification(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *title, char *body) {
JNIEnv *env = (JNIEnv*)jni_env;
jstring titleStr = (*env)->NewStringUTF(env, title);
jstring bodyStr = (*env)->NewStringUTF(env, body);
jclass cls = find_class(env, "android/app/Notification$Builder");
jmethodID constructor = find_method(env, cls, "<init>", "(Landroid/content/Context;)V");
jobject builder = (*env)->NewObject(env, cls, constructor, ctx);
jclass mgrCls = find_class(env, "android/app/NotificationManager");
jobject mgr = getSystemService((uintptr_t)env, ctx, "notification");
if (isOreoOrLater(env)) {
jstring channelId = (*env)->NewStringUTF(env, "fyne-notif");
jstring name = (*env)->NewStringUTF(env, "Fyne Notification");
int importance = 4; // IMPORTANCE_HIGH
jclass chanCls = find_class(env, "android/app/NotificationChannel");
jmethodID constructor = find_method(env, chanCls, "<init>", "(Ljava/lang/String;Ljava/lang/CharSequence;I)V");
jobject channel = (*env)->NewObject(env, chanCls, constructor, channelId, name, importance);
jmethodID createChannel = find_method(env, mgrCls, "createNotificationChannel", "(Landroid/app/NotificationChannel;)V");
(*env)->CallVoidMethod(env, mgr, createChannel, channel);
jmethodID setChannelId = find_method(env, cls, "setChannelId", "(Ljava/lang/String;)Landroid/app/Notification$Builder;");
(*env)->CallObjectMethod(env, builder, setChannelId, channelId);
}
jmethodID setContentTitle = find_method(env, cls, "setContentTitle", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;");
(*env)->CallObjectMethod(env, builder, setContentTitle, titleStr);
jmethodID setContentText = find_method(env, cls, "setContentText", "(Ljava/lang/CharSequence;)Landroid/app/Notification$Builder;");
(*env)->CallObjectMethod(env, builder, setContentText, bodyStr);
int iconID = 17629184; // constant of "unknown app icon"
jmethodID setSmallIcon = find_method(env, cls, "setSmallIcon", "(I)Landroid/app/Notification$Builder;");
(*env)->CallObjectMethod(env, builder, setSmallIcon, iconID);
jmethodID build = find_method(env, cls, "build", "()Landroid/app/Notification;");
jobject notif = (*env)->CallObjectMethod(env, builder, build);
jmethodID notify = find_method(env, mgrCls, "notify", "(ILandroid/app/Notification;)V");
(*env)->CallVoidMethod(env, mgr, notify, nextId, notif);
nextId++;
}