1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
27 extern JNIEnv* getEnv() noexcept;
28 
29 //==============================================================================
30 template <typename JavaType>
31 class LocalRef
32 {
33 public:
LocalRef()34     explicit inline LocalRef() noexcept                 : obj (nullptr) {}
LocalRef(JavaType o)35     explicit inline LocalRef (JavaType o) noexcept      : obj (o) {}
LocalRef(const LocalRef & other)36     inline LocalRef (const LocalRef& other) noexcept    : obj (retain (other.obj)) {}
LocalRef(LocalRef && other)37     inline LocalRef (LocalRef&& other) noexcept         : obj (nullptr) { std::swap (obj, other.obj); }
~LocalRef()38     ~LocalRef()                                         { clear(); }
39 
clear()40     void clear()
41     {
42         if (obj != nullptr)
43         {
44             getEnv()->DeleteLocalRef (obj);
45             obj = nullptr;
46         }
47     }
48 
49     LocalRef& operator= (const LocalRef& other)
50     {
51         JavaType newObj = retain (other.obj);
52         clear();
53         obj = newObj;
54         return *this;
55     }
56 
57     LocalRef& operator= (LocalRef&& other)
58     {
59         clear();
60         std::swap (other.obj, obj);
61         return *this;
62     }
63 
JavaType()64     inline operator JavaType() const noexcept   { return obj; }
get()65     inline JavaType get() const noexcept        { return obj; }
66 
67 private:
68     JavaType obj;
69 
retain(JavaType obj)70     static JavaType retain (JavaType obj)
71     {
72         return obj == nullptr ? nullptr : (JavaType) getEnv()->NewLocalRef (obj);
73     }
74 };
75 
76 //==============================================================================
77 class GlobalRef
78 {
79 public:
GlobalRef()80     inline GlobalRef() noexcept                             : obj (nullptr) {}
GlobalRef(const LocalRef<jobject> & o)81     inline explicit GlobalRef (const LocalRef<jobject>& o)  : obj (retain (o.get(), getEnv())) {}
GlobalRef(const LocalRef<jobject> & o,JNIEnv * env)82     inline explicit GlobalRef (const LocalRef<jobject>& o, JNIEnv* env)  : obj (retain (o.get(), env)) {}
GlobalRef(const GlobalRef & other)83     inline GlobalRef (const GlobalRef& other)           : obj (retain (other.obj, getEnv())) {}
GlobalRef(GlobalRef && other)84     inline GlobalRef (GlobalRef && other) noexcept      : obj (nullptr) { std::swap (other.obj, obj); }
~GlobalRef()85     ~GlobalRef()                                             { clear(); }
86 
87 
clear()88     inline void clear()                                 { if (obj != nullptr) clear (getEnv()); }
clear(JNIEnv * env)89     inline void clear (JNIEnv* env)
90     {
91         if (obj != nullptr)
92         {
93             env->DeleteGlobalRef (obj);
94             obj = nullptr;
95         }
96     }
97 
98     inline GlobalRef& operator= (const GlobalRef& other)
99     {
100         jobject newObj = retain (other.obj, getEnv());
101         clear();
102         obj = newObj;
103         return *this;
104     }
105 
106     inline GlobalRef& operator= (GlobalRef&& other)
107     {
108         clear();
109         std::swap (obj, other.obj);
110 
111         return *this;
112     }
113 
114     //==============================================================================
jobject()115     inline operator jobject() const noexcept    { return obj; }
get()116     inline jobject get() const noexcept         { return obj; }
117 
118     //==============================================================================
119     #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \
120         returnType call##typeName##Method (jmethodID methodID, ... ) const \
121         { \
122             va_list args; \
123             va_start (args, methodID); \
124             returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \
125             va_end (args); \
126             return result; \
127         }
128 
DECLARE_CALL_TYPE_METHOD(jobject,Object)129     DECLARE_CALL_TYPE_METHOD (jobject, Object)
130     DECLARE_CALL_TYPE_METHOD (jboolean, Boolean)
131     DECLARE_CALL_TYPE_METHOD (jbyte, Byte)
132     DECLARE_CALL_TYPE_METHOD (jchar, Char)
133     DECLARE_CALL_TYPE_METHOD (jshort, Short)
134     DECLARE_CALL_TYPE_METHOD (jint, Int)
135     DECLARE_CALL_TYPE_METHOD (jlong, Long)
136     DECLARE_CALL_TYPE_METHOD (jfloat, Float)
137     DECLARE_CALL_TYPE_METHOD (jdouble, Double)
138     #undef DECLARE_CALL_TYPE_METHOD
139 
140     void callVoidMethod (jmethodID methodID, ... ) const
141     {
142         va_list args;
143         va_start (args, methodID);
144         getEnv()->CallVoidMethodV (obj, methodID, args);
145         va_end (args);
146     }
147 
148 private:
149     //==============================================================================
150     jobject obj = nullptr;
151 
retain(jobject obj,JNIEnv * env)152     static jobject retain (jobject obj, JNIEnv* env)
153     {
154         return obj == nullptr ? nullptr : env->NewGlobalRef (obj);
155     }
156 };
157 
158 
159 //==============================================================================
160 extern LocalRef<jobject> getAppContext() noexcept;
161 extern LocalRef<jobject> getCurrentActivity() noexcept;
162 extern LocalRef<jobject> getMainActivity() noexcept;
163 
164 //==============================================================================
165 struct SystemJavaClassComparator;
166 class JNIClassBase
167 {
168 public:
169     explicit JNIClassBase (const char* classPath, int minSDK, const void* byteCode, size_t byteCodeSize);
170     virtual ~JNIClassBase();
171 
jclass()172     inline operator jclass() const noexcept  { return classRef; }
173 
174     static void initialiseAllClasses (JNIEnv*);
175     static void releaseAllClasses (JNIEnv*);
176 
getClassPath()177     inline const char* getClassPath() const noexcept { return classPath; }
178 
179 protected:
180     virtual void initialiseFields (JNIEnv*) = 0;
181 
182     jmethodID resolveMethod (JNIEnv*, const char* methodName, const char* params);
183     jmethodID resolveStaticMethod (JNIEnv*, const char* methodName, const char* params);
184     jfieldID resolveField (JNIEnv*, const char* fieldName, const char* signature);
185     jfieldID resolveStaticField (JNIEnv*, const char* fieldName, const char* signature);
186     void resolveCallbacks (JNIEnv*, const Array<JNINativeMethod>&);
187 
188 private:
189     friend struct SystemJavaClassComparator;
190 
191     const char* const classPath;
192     const void* byteCode;
193     size_t byteCodeSize;
194 
195     int minSDK;
196     jclass classRef = nullptr;
197 
198     static Array<JNIClassBase*>& getClasses();
199     void initialise (JNIEnv*);
200     void release (JNIEnv*);
201     void tryLoadingClassWithClassLoader (JNIEnv* env, jobject classLoader);
202 
203     JUCE_DECLARE_NON_COPYABLE (JNIClassBase)
204 };
205 
206 //==============================================================================
207 #define CREATE_JNI_METHOD(methodID, stringName, params)          methodID = resolveMethod (env, stringName, params);
208 #define CREATE_JNI_STATICMETHOD(methodID, stringName, params)    methodID = resolveStaticMethod (env, stringName, params);
209 #define CREATE_JNI_FIELD(fieldID, stringName, signature)         fieldID  = resolveField (env, stringName, signature);
210 #define CREATE_JNI_STATICFIELD(fieldID, stringName, signature)   fieldID  = resolveStaticField (env, stringName, signature);
211 #define CREATE_JNI_CALLBACK(callbackName, stringName, signature) callbacks.add ({stringName, signature, (void*) callbackName});
212 #define DECLARE_JNI_METHOD(methodID, stringName, params)         jmethodID methodID;
213 #define DECLARE_JNI_FIELD(fieldID, stringName, signature)        jfieldID  fieldID;
214 #define DECLARE_JNI_CALLBACK(fieldID, stringName, signature)
215 
216 #define DECLARE_JNI_CLASS_WITH_BYTECODE(CppClassName, javaPath, minSDK, byteCodeData, byteCodeSize) \
217     class CppClassName ## _Class   : public JNIClassBase \
218     { \
219     public: \
220         CppClassName ## _Class() : JNIClassBase (javaPath, minSDK, byteCodeData, byteCodeSize) {} \
221     \
222         void initialiseFields (JNIEnv* env) \
223         { \
224             Array<JNINativeMethod> callbacks; \
225             JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD, CREATE_JNI_CALLBACK); \
226             resolveCallbacks (env, callbacks); \
227         } \
228     \
229         JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD, DECLARE_JNI_CALLBACK) \
230     }; \
231     static CppClassName ## _Class CppClassName;
232 
233 //==============================================================================
234 #define DECLARE_JNI_CLASS_WITH_MIN_SDK(CppClassName, javaPath, minSDK) \
235     DECLARE_JNI_CLASS_WITH_BYTECODE (CppClassName, javaPath, minSDK, nullptr, 0)
236 
237 //==============================================================================
238 #define DECLARE_JNI_CLASS(CppClassName, javaPath) \
239     DECLARE_JNI_CLASS_WITH_MIN_SDK (CppClassName, javaPath, 16)
240 
241 //==============================================================================
242 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
243  METHOD (getAssets,                            "getAssets",                       "()Landroid/content/res/AssetManager;") \
244  METHOD (getSystemService,                     "getSystemService",                "(Ljava/lang/String;)Ljava/lang/Object;") \
245  METHOD (getPackageManager,                    "getPackageManager",               "()Landroid/content/pm/PackageManager;") \
246  METHOD (getPackageName,                       "getPackageName",                  "()Ljava/lang/String;") \
247  METHOD (getResources,                         "getResources",                    "()Landroid/content/res/Resources;") \
248  METHOD (bindService,                          "bindService",                     "(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z") \
249  METHOD (unbindService,                        "unbindService",                   "(Landroid/content/ServiceConnection;)V") \
250  METHOD (startActivity,                        "startActivity",                   "(Landroid/content/Intent;)V") \
251  METHOD (getContentResolver,                   "getContentResolver",              "()Landroid/content/ContentResolver;") \
252  METHOD (getApplicationContext,                "getApplicationContext",           "()Landroid/content/Context;") \
253  METHOD (getApplicationInfo,                   "getApplicationInfo",              "()Landroid/content/pm/ApplicationInfo;") \
254  METHOD (checkCallingOrSelfPermission,         "checkCallingOrSelfPermission",    "(Ljava/lang/String;)I") \
255  METHOD (getCacheDir,                          "getCacheDir",                     "()Ljava/io/File;")
256 
257 DECLARE_JNI_CLASS (AndroidContext, "android/content/Context")
258 #undef JNI_CLASS_MEMBERS
259 
260 //==============================================================================
261 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
262  METHOD (finish,                               "finish",                          "()V") \
263  METHOD (getWindowManager,                     "getWindowManager",                "()Landroid/view/WindowManager;") \
264  METHOD (setRequestedOrientation,              "setRequestedOrientation",         "(I)V") \
265  METHOD (startIntentSenderForResult,           "startIntentSenderForResult",      "(Landroid/content/IntentSender;ILandroid/content/Intent;III)V") \
266  METHOD (moveTaskToBack,                       "moveTaskToBack",                  "(Z)Z") \
267  METHOD (startActivityForResult,               "startActivityForResult",          "(Landroid/content/Intent;I)V") \
268  METHOD (getFragmentManager,                   "getFragmentManager",              "()Landroid/app/FragmentManager;") \
269  METHOD (setContentView,                       "setContentView",                  "(Landroid/view/View;)V") \
270  METHOD (getWindow,                            "getWindow",                       "()Landroid/view/Window;")
271 
272 DECLARE_JNI_CLASS (AndroidActivity, "android/app/Activity")
273 #undef JNI_CLASS_MEMBERS
274 
275 //==============================================================================
276 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
277  METHOD (startActivityForResult,               "startActivityForResult",          "(Landroid/content/Intent;I)V") \
278  METHOD (setArguments,                         "setArguments",                    "(Landroid/os/Bundle;)V")
279 
280 DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidFragment, "android/app/Fragment", 11)
281 #undef JNI_CLASS_MEMBERS
282 
283 //==============================================================================
284 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
285   METHOD (build,          "build",          "()Landroid/media/AudioAttributes;") \
286   METHOD (constructor,    "<init>",         "()V") \
287   METHOD (setContentType, "setContentType", "(I)Landroid/media/AudioAttributes$Builder;") \
288   METHOD (setUsage,       "setUsage",       "(I)Landroid/media/AudioAttributes$Builder;")
289 
290 DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidAudioAttributesBuilder, "android/media/AudioAttributes$Builder", 21)
291 #undef JNI_CLASS_MEMBERS
292 
293 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
294   METHOD (abandonAudioFocus, "abandonAudioFocus", "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I") \
295   METHOD (requestAudioFocus, "requestAudioFocus", "(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I")
296 
297 DECLARE_JNI_CLASS (AndroidAudioManager, "android/media/AudioManager")
298 #undef JNI_CLASS_MEMBERS
299 
300 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
301   STATICMETHOD (createBitmap,     "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \
302   STATICMETHOD (createBitmapFrom, "createBitmap", "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)Landroid/graphics/Bitmap;") \
303   METHOD (compress,  "compress",  "(Landroid/graphics/Bitmap$CompressFormat;ILjava/io/OutputStream;)Z") \
304   METHOD (getHeight, "getHeight", "()I") \
305   METHOD (getWidth,  "getWidth",  "()I") \
306   METHOD (recycle,   "recycle",   "()V") \
307   METHOD (setPixel,  "setPixel",  "(III)V") \
308   METHOD (getPixels, "getPixels",  "([IIIIIII)V")
309 
310 DECLARE_JNI_CLASS (AndroidBitmap, "android/graphics/Bitmap")
311 #undef JNI_CLASS_MEMBERS
312 
313 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
314   STATICMETHOD (valueOf, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;")
315 
316 DECLARE_JNI_CLASS (AndroidBitmapConfig, "android/graphics/Bitmap$Config")
317 #undef JNI_CLASS_MEMBERS
318 
319 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
320   STATICMETHOD (decodeByteArray, "decodeByteArray", "([BII)Landroid/graphics/Bitmap;")
321 
322 DECLARE_JNI_CLASS (AndroidBitmapFactory, "android/graphics/BitmapFactory")
323 #undef JNI_CLASS_MEMBERS
324 
325 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK)    \
326   METHOD (constructor,        "<init>",             "()V") \
327   METHOD (containsKey,        "containsKey",        "(Ljava/lang/String;)Z") \
328   METHOD (get,                "get",                "(Ljava/lang/String;)Ljava/lang/Object;") \
329   METHOD (getBoolean,         "getBoolean",         "(Ljava/lang/String;)Z") \
330   METHOD (getBundle,          "getBundle",          "(Ljava/lang/String;)Landroid/os/Bundle;") \
331   METHOD (getCharSequence,    "getCharSequence",    "(Ljava/lang/String;)Ljava/lang/CharSequence;") \
332   METHOD (getInt,             "getInt",             "(Ljava/lang/String;)I") \
333   METHOD (getLong,            "getLong",            "(Ljava/lang/String;)J") \
334   METHOD (getLongArray,       "getLongArray",       "(Ljava/lang/String;)[J") \
335   METHOD (getParcelable,      "getParcelable",      "(Ljava/lang/String;)Landroid/os/Parcelable;") \
336   METHOD (getString,          "getString",          "(Ljava/lang/String;)Ljava/lang/String;") \
337   METHOD (getStringArrayList, "getStringArrayList", "(Ljava/lang/String;)Ljava/util/ArrayList;") \
338   METHOD (keySet,             "keySet",             "()Ljava/util/Set;") \
339   METHOD (putBoolean,         "putBoolean",         "(Ljava/lang/String;Z)V") \
340   METHOD (putBundle,          "putBundle",          "(Ljava/lang/String;Landroid/os/Bundle;)V") \
341   METHOD (putFloat,           "putFloat",           "(Ljava/lang/String;F)V") \
342   METHOD (putInt,             "putInt",             "(Ljava/lang/String;I)V") \
343   METHOD (putLong,            "putLong",            "(Ljava/lang/String;J)V") \
344   METHOD (putLongArray,       "putLongArray",       "(Ljava/lang/String;[J)V") \
345   METHOD (putString,          "putString",          "(Ljava/lang/String;Ljava/lang/String;)V") \
346   METHOD (putStringArrayList, "putStringArrayList", "(Ljava/lang/String;Ljava/util/ArrayList;)V")
347 
348 DECLARE_JNI_CLASS (AndroidBundle, "android/os/Bundle")
349 #undef JNI_CLASS_MEMBERS
350 
351 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
352   STATICMETHOD (dumpReferenceTables, "dumpReferenceTables", "()V")
353 
354   DECLARE_JNI_CLASS (AndroidDebug, "android/os/Debug")
355 #undef JNI_CLASS_MEMBERS
356 
357 #define JUCE_LOG_JNI_REFERENCES_TABLE getEnv()->CallStaticVoidMethod (AndroidDebug, AndroidDebug.dumpReferenceTables);
358 
359 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
360  METHOD (getRotation, "getRotation", "()I") \
361  METHOD (getMetrics,  "getMetrics",  "(Landroid/util/DisplayMetrics;)V" ) \
362  METHOD (getSize,     "getSize",     "(Landroid/graphics/Point;)V" )
363 
364 DECLARE_JNI_CLASS (AndroidDisplay, "android/view/Display")
365 #undef JNI_CLASS_MEMBERS
366 
367 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
368   METHOD (constructor,           "<init>",      "()V") \
369   METHOD (constructorWithLooper, "<init>",      "(Landroid/os/Looper;)V") \
370   METHOD (post,                  "post",        "(Ljava/lang/Runnable;)Z") \
371   METHOD (postDelayed,           "postDelayed", "(Ljava/lang/Runnable;J)Z") \
372 
373 DECLARE_JNI_CLASS (AndroidHandler, "android/os/Handler")
374 #undef JNI_CLASS_MEMBERS
375 
376 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
377   METHOD (constructor, "<init>",     "(Ljava/lang/String;)V") \
378   METHOD (getLooper,   "getLooper",  "()Landroid/os/Looper;") \
379   METHOD (join,        "join",       "()V") \
380   METHOD (start,       "start",      "()V")
381 
382 DECLARE_JNI_CLASS (AndroidHandlerThread, "android/os/HandlerThread")
383 #undef JNI_CLASS_MEMBERS
384 
385 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
386   STATICMETHOD (createChooser, "createChooser", "(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;") \
387   METHOD (addCategory,                    "addCategory",    "(Ljava/lang/String;)Landroid/content/Intent;") \
388   METHOD (constructor,                    "<init>",         "()V") \
389   METHOD (constructorWithContextAndClass, "<init>",         "(Landroid/content/Context;Ljava/lang/Class;)V") \
390   METHOD (constructWithString,            "<init>",         "(Ljava/lang/String;)V") \
391   METHOD (constructWithUri,               "<init>",         "(Ljava/lang/String;Landroid/net/Uri;)V") \
392   METHOD (getAction,                      "getAction",      "()Ljava/lang/String;") \
393   METHOD (getCategories,                  "getCategories",  "()Ljava/util/Set;") \
394   METHOD (getData,                        "getData",        "()Landroid/net/Uri;") \
395   METHOD (getExtras,                      "getExtras",      "()Landroid/os/Bundle;") \
396   METHOD (getIntExtra,                    "getIntExtra",    "(Ljava/lang/String;I)I") \
397   METHOD (getStringExtra,                 "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;") \
398   METHOD (putExtra,                       "putExtra",       "(Ljava/lang/String;Ljava/lang/CharSequence;)Landroid/content/Intent;") \
399   METHOD (putExtras,                      "putExtras",      "(Landroid/os/Bundle;)Landroid/content/Intent;") \
400   METHOD (putExtraString,                 "putExtra",       "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;") \
401   METHOD (putExtraStrings,                "putExtra",       "(Ljava/lang/String;[Ljava/lang/String;)Landroid/content/Intent;") \
402   METHOD (putExtraParcelable,             "putExtra",       "(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;") \
403   METHOD (putParcelableArrayListExtra,    "putParcelableArrayListExtra", "(Ljava/lang/String;Ljava/util/ArrayList;)Landroid/content/Intent;") \
404   METHOD (setAction,                      "setAction",      "(Ljava/lang/String;)Landroid/content/Intent;") \
405   METHOD (setFlags,                       "setFlags",       "(I)Landroid/content/Intent;") \
406   METHOD (setPackage,                     "setPackage",     "(Ljava/lang/String;)Landroid/content/Intent;") \
407   METHOD (setType,                        "setType",        "(Ljava/lang/String;)Landroid/content/Intent;") \
408 
409 DECLARE_JNI_CLASS (AndroidIntent, "android/content/Intent")
410 #undef JNI_CLASS_MEMBERS
411 
412 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
413  METHOD (constructor,    "<init>",        "()V") \
414  METHOD (postRotate,     "postRotate",    "(FFF)Z") \
415  METHOD (postScale,      "postScale",     "(FFFF)Z") \
416  METHOD (postTranslate,  "postTranslate", "(FF)Z") \
417  METHOD (setValues,      "setValues",     "([F)V") \
418  METHOD (mapRect,        "mapRect",       "(Landroid/graphics/RectF;)Z")
419 
420 DECLARE_JNI_CLASS (AndroidMatrix, "android/graphics/Matrix")
421 #undef JNI_CLASS_MEMBERS
422 
423 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
424  METHOD (getPackageInfo, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;") \
425  METHOD (resolveActivity, "resolveActivity", "(Landroid/content/Intent;I)Landroid/content/pm/ResolveInfo;") \
426  METHOD (hasSystemFeature, "hasSystemFeature", "(Ljava/lang/String;)Z")
427 
428 DECLARE_JNI_CLASS (AndroidPackageManager, "android/content/pm/PackageManager")
429 #undef JNI_CLASS_MEMBERS
430 
431 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
432  FIELD (requestedPermissions,   "requestedPermissions",   "[Ljava/lang/String;") \
433  FIELD (activities,             "activities",             "[Landroid/content/pm/ActivityInfo;") \
434  FIELD (providers,              "providers",              "[Landroid/content/pm/ProviderInfo;")
435 
436  DECLARE_JNI_CLASS (AndroidPackageInfo, "android/content/pm/PackageInfo")
437 #undef JNI_CLASS_MEMBERS
438 
439 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
440  FIELD (name,        "name",        "Ljava/lang/String;") \
441  FIELD (packageName, "packageName", "Ljava/lang/String;")
442 
443  DECLARE_JNI_CLASS (AndroidPackageItemInfo, "android/content/pm/PackageItemInfo")
444 #undef JNI_CLASS_MEMBERS
445 
446 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
447  METHOD (constructor,   "<init>",           "(I)V") \
448  METHOD (setColor,      "setColor",         "(I)V") \
449  METHOD (setAlpha,      "setAlpha",         "(I)V") \
450  METHOD (setTypeface,   "setTypeface",      "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
451  METHOD (ascent,        "ascent",           "()F") \
452  METHOD (descent,       "descent",          "()F") \
453  METHOD (setTextSize,   "setTextSize",      "(F)V") \
454  METHOD (getTextWidths, "getTextWidths",    "(Ljava/lang/String;[F)I") \
455  METHOD (setTextScaleX, "setTextScaleX",    "(F)V") \
456  METHOD (getTextPath,   "getTextPath",      "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
457  METHOD (getCharsPath,  "getTextPath",      "([CIIFFLandroid/graphics/Path;)V") \
458  METHOD (setShader,     "setShader",        "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
459 
460 DECLARE_JNI_CLASS (AndroidPaint, "android/graphics/Paint")
461 #undef JNI_CLASS_MEMBERS
462 
463 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
464  METHOD (create,          "<init>",           "(Landroid/graphics/Bitmap;)V") \
465  METHOD (setMatrix,       "setMatrix",        "(Landroid/graphics/Matrix;)V") \
466  METHOD (drawPath,        "drawPath",         "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \
467  METHOD (drawBitmap,      "drawBitmap",       "([IIIFFIIZLandroid/graphics/Paint;)V") \
468  METHOD (getClipBounds,   "getClipBounds",    "()Landroid/graphics/Rect;")
469 
470  DECLARE_JNI_CLASS (AndroidCanvas, "android/graphics/Canvas")
471 #undef JNI_CLASS_MEMBERS
472 
473 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
474   STATICMETHOD (getActivity, "getActivity", "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;") \
475   METHOD (getIntentSender, "getIntentSender", "()Landroid/content/IntentSender;")
476 
477 DECLARE_JNI_CLASS (AndroidPendingIntent, "android/app/PendingIntent")
478 #undef JNI_CLASS_MEMBERS
479 
480 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
481   METHOD (toString, "toString", "()Ljava/lang/String;")
482 
483 DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidRange, "android/util/Range", 21)
484 #undef JNI_CLASS_MEMBERS
485 
486 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
487  METHOD (create,   "<init>",   "(II)V") \
488  FIELD  (x,        "x",        "I") \
489  FIELD  (y,        "y",        "I")
490 
491 DECLARE_JNI_CLASS (AndroidPoint, "android/graphics/Point")
492 #undef JNI_CLASS_MEMBERS
493 
494 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
495  METHOD (constructor,   "<init>",   "(IIII)V") \
496  FIELD (left,           "left",     "I") \
497  FIELD (right,          "right",    "I") \
498  FIELD (top,            "top",      "I") \
499  FIELD (bottom,         "bottom",   "I")
500 
501 DECLARE_JNI_CLASS (AndroidRect, "android/graphics/Rect")
502 #undef JNI_CLASS_MEMBERS
503 
504 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
505   METHOD (getIdentifier,     "getIdentifier",     "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I") \
506   METHOD (openRawResourceFd, "openRawResourceFd", "(I)Landroid/content/res/AssetFileDescriptor;")
507 
508 DECLARE_JNI_CLASS (AndroidResources, "android/content/res/Resources")
509 #undef JNI_CLASS_MEMBERS
510 
511 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
512   METHOD (getHeight, "getHeight", "()I") \
513   METHOD (getWidth,  "getWidth",  "()I")
514 
515 DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidSize, "android/util/Size", 21)
516 #undef JNI_CLASS_MEMBERS
517 
518 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
519   STATICMETHOD (parse, "parse", "(Ljava/lang/String;)Landroid/net/Uri;") \
520   METHOD (toString, "toString", "()Ljava/lang/String;")
521 
522 DECLARE_JNI_CLASS (AndroidUri, "android/net/Uri")
523 #undef JNI_CLASS_MEMBERS
524 
525 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
526  METHOD (construct,                 "<init>",                    "(Landroid/content/Context;)V") \
527  METHOD (layout,                    "layout",                    "(IIII)V") \
528  METHOD (getLeft,                   "getLeft",                   "()I") \
529  METHOD (getTop,                    "getTop",                    "()I") \
530  METHOD (getWidth,                  "getWidth",                  "()I") \
531  METHOD (getHeight,                 "getHeight",                 "()I") \
532  METHOD (getLocationOnScreen,       "getLocationOnScreen",       "([I)V") \
533  METHOD (getParent,                 "getParent",                 "()Landroid/view/ViewParent;") \
534  METHOD (bringToFront,              "bringToFront",              "()V") \
535  METHOD (requestFocus,              "requestFocus",              "()Z") \
536  METHOD (hasFocus,                  "hasFocus",                  "()Z") \
537  METHOD (invalidate,                "invalidate",                "(IIII)V") \
538  METHOD (setVisibility,             "setVisibility",             "(I)V") \
539  METHOD (setLayoutParams,           "setLayoutParams",           "(Landroid/view/ViewGroup$LayoutParams;)V") \
540  METHOD (setSystemUiVisibility,     "setSystemUiVisibility",     "(I)V") \
541  METHOD (findViewById,              "findViewById",              "(I)Landroid/view/View;") \
542  METHOD (getRootView,               "getRootView",               "()Landroid/view/View;") \
543  METHOD (addOnLayoutChangeListener, "addOnLayoutChangeListener", "(Landroid/view/View$OnLayoutChangeListener;)V")
544 
545 DECLARE_JNI_CLASS (AndroidView, "android/view/View")
546 #undef JNI_CLASS_MEMBERS
547 
548 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
549  METHOD (addView,    "addView",    "(Landroid/view/View;)V") \
550  METHOD (removeView, "removeView", "(Landroid/view/View;)V")
551 
552 DECLARE_JNI_CLASS (AndroidViewGroup, "android/view/ViewGroup")
553 #undef JNI_CLASS_MEMBERS
554 
555 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
556  METHOD (getDefaultDisplay, "getDefaultDisplay", "()Landroid/view/Display;")
557 
558 DECLARE_JNI_CLASS (AndroidWindowManager, "android/view/WindowManager")
559 #undef JNI_CLASS_MEMBERS
560 
561 //==============================================================================
562 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
563   METHOD (constructor, "<init>",   "(I)V") \
564   METHOD (add,         "add",      "(Ljava/lang/Object;)Z") \
565   METHOD (iterator,    "iterator", "()Ljava/util/Iterator;") \
566   METHOD (get,         "get",      "(I)Ljava/lang/Object;") \
567   METHOD (size,        "size",     "()I")
568 
569 DECLARE_JNI_CLASS (JavaArrayList, "java/util/ArrayList")
570 #undef JNI_CLASS_MEMBERS
571 
572 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
573   STATICMETHOD (valueOf, "valueOf", "(Z)Ljava/lang/Boolean;") \
574   METHOD (booleanValue, "booleanValue", "()Z")
575 
576 DECLARE_JNI_CLASS (JavaBoolean, "java/lang/Boolean")
577 #undef JNI_CLASS_MEMBERS
578 
579 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
580   METHOD (get,        "get",       "([B)Ljava/nio/ByteBuffer;") \
581   METHOD (remaining,  "remaining", "()I") \
582   STATICMETHOD (wrap, "wrap",      "([B)Ljava/nio/ByteBuffer;")
583 
584 DECLARE_JNI_CLASS (JavaByteBuffer, "java/nio/ByteBuffer")
585 #undef JNI_CLASS_MEMBERS
586 
587 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
588   METHOD (toString, "toString", "()Ljava/lang/String;")
589 
590 DECLARE_JNI_CLASS (JavaCharSequence, "java/lang/CharSequence")
591 #undef JNI_CLASS_MEMBERS
592 
593 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
594   STATICMETHOD (forName, "forName", "(Ljava/lang/String;)Ljava/lang/Class;") \
595   METHOD (getName,           "getName",           "()Ljava/lang/String;") \
596   METHOD (getModifiers,      "getModifiers",      "()I")            \
597   METHOD (isAnnotation,      "isAnnotation",      "()Z") \
598   METHOD (isAnonymousClass,  "isAnonymousClass",  "()Z") \
599   METHOD (isArray,           "isArray",           "()Z") \
600   METHOD (isEnum,            "isEnum",            "()Z") \
601   METHOD (isInterface,       "isInterface",       "()Z") \
602   METHOD (isLocalClass,      "isLocalClass",      "()Z") \
603   METHOD (isMemberClass,     "isMemberClass",     "()Z") \
604   METHOD (isPrimitive,       "isPrimitive",       "()Z") \
605   METHOD (isSynthetic,       "isSynthetic",       "()Z") \
606   METHOD (getComponentType,  "getComponentType",  "()Ljava/lang/Class;") \
607   METHOD (getSuperclass,     "getSuperclass",     "()Ljava/lang/Class;") \
608   METHOD (getClassLoader,    "getClassLoader",    "()Ljava/lang/ClassLoader;") \
609 
610 DECLARE_JNI_CLASS (JavaClass, "java/lang/Class")
611 #undef JNI_CLASS_MEMBERS
612 
613 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
614   METHOD (toString, "toString", "()Ljava/lang/String;")
615 
616 DECLARE_JNI_CLASS (JavaEnum, "java/lang/Enum")
617 #undef JNI_CLASS_MEMBERS
618 
619 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
620  METHOD (constructor,     "<init>",          "(Ljava/lang/String;)V") \
621  METHOD (getAbsolutePath, "getAbsolutePath", "()Ljava/lang/String;") \
622  METHOD (length,          "length",          "()J")
623 
624 DECLARE_JNI_CLASS (JavaFile, "java/io/File")
625 #undef JNI_CLASS_MEMBERS
626 
627 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
628  METHOD (constructor, "<init>", "(Ljava/lang/String;)V") \
629  METHOD (close,       "close",  "()V") \
630  METHOD (read,        "read",   "([B)I")
631 
632 DECLARE_JNI_CLASS (JavaFileInputStream, "java/io/FileInputStream")
633 #undef JNI_CLASS_MEMBERS
634 
635 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
636  METHOD (constructor, "<init>", "(Ljava/lang/String;)V") \
637  METHOD (close,       "close",  "()V") \
638  METHOD (write,       "write",  "([BII)V")
639 
640 DECLARE_JNI_CLASS (JavaFileOutputStream, "java/io/FileOutputStream")
641 #undef JNI_CLASS_MEMBERS
642 
643 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
644   METHOD (constructor,             "<init>", "()V") \
645   METHOD (constructorWithCapacity, "<init>", "(I)V")
646 
647 DECLARE_JNI_CLASS (JavaHashMap, "java/util/HashMap")
648 #undef JNI_CLASS_MEMBERS
649 
650 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
651   STATICMETHOD (parseInt, "parseInt", "(Ljava/lang/String;I)I") \
652   STATICMETHOD (valueOf,  "valueOf",  "(I)Ljava/lang/Integer;") \
653   METHOD (intValue, "intValue", "()I")
654 
655 DECLARE_JNI_CLASS (JavaInteger, "java/lang/Integer")
656 #undef JNI_CLASS_MEMBERS
657 
658 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
659   METHOD (hasNext, "hasNext", "()Z") \
660   METHOD (next,    "next",    "()Ljava/lang/Object;")
661 
662 DECLARE_JNI_CLASS (JavaIterator, "java/util/Iterator")
663 #undef JNI_CLASS_MEMBERS
664 
665 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
666   METHOD (get,  "get",  "(I)Ljava/lang/Object;") \
667   METHOD (size, "size", "()I")
668 
669 DECLARE_JNI_CLASS (JavaList, "java/util/List")
670 #undef JNI_CLASS_MEMBERS
671 
672 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
673   METHOD (constructor, "<init>", "(J)V")
674 
675 DECLARE_JNI_CLASS (JavaLong, "java/lang/Long")
676 #undef JNI_CLASS_MEMBERS
677 
678 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
679   METHOD (get,    "get",    "(Ljava/lang/Object;)Ljava/lang/Object;") \
680   METHOD (keySet, "keySet", "()Ljava/util/Set;") \
681   METHOD (put,    "put",    "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
682 
683 DECLARE_JNI_CLASS (JavaMap, "java/util/Map")
684 #undef JNI_CLASS_MEMBERS
685 
686 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
687   METHOD (getName,           "getName",           "()Ljava/lang/String;") \
688   METHOD (getModifiers,      "getModifiers",      "()I")            \
689   METHOD (getParameterTypes, "getParameterTypes", "()[Ljava/lang/Class;") \
690   METHOD (getReturnType,     "getReturnType",     "()Ljava/lang/Class;") \
691   METHOD (invoke,            "invoke",            "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;") \
692   METHOD (hashCode,          "hashCode",          "()I") \
693   METHOD (equals,            "equals",            "(Ljava/lang/Object;)Z") \
694 
695 DECLARE_JNI_CLASS (JavaMethod, "java/lang/reflect/Method")
696 #undef JNI_CLASS_MEMBERS
697 
698 
699 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
700   METHOD (constructor, "<init>", "()V") \
701   METHOD (getClass, "getClass", "()Ljava/lang/Class;") \
702   METHOD (toString, "toString", "()Ljava/lang/String;")
703 
704 DECLARE_JNI_CLASS (JavaObject, "java/lang/Object")
705 #undef JNI_CLASS_MEMBERS
706 
707 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
708   METHOD (contains, "contains", "(Ljava/lang/Object;)Z") \
709   METHOD (iterator, "iterator", "()Ljava/util/Iterator;") \
710   METHOD (size,     "size",     "()I")
711 
712 DECLARE_JNI_CLASS (JavaSet, "java/util/Set")
713 #undef JNI_CLASS_MEMBERS
714 
715 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
716   METHOD (concat,   "concat",   "(Ljava/lang/String;)Ljava/lang/String;") \
717   METHOD (getBytes, "getBytes", "()[B")
718 
719 DECLARE_JNI_CLASS (JavaString, "java/lang/String")
720 #undef JNI_CLASS_MEMBERS
721 
722 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK)
723 DECLARE_JNI_CLASS (AndroidBuild, "android/os/Build")
724 #undef JNI_CLASS_MEMBERS
725 
726 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK)
727 DECLARE_JNI_CLASS (AndroidBuildVersion, "android/os/Build$VERSION")
728 #undef JNI_CLASS_MEMBERS
729 
730 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
731  METHOD (registerActivityLifecycleCallbacks,   "registerActivityLifecycleCallbacks",   "(Landroid/app/Application$ActivityLifecycleCallbacks;)V") \
732  METHOD (unregisterActivityLifecycleCallbacks, "unregisterActivityLifecycleCallbacks", "(Landroid/app/Application$ActivityLifecycleCallbacks;)V")
733 
734  DECLARE_JNI_CLASS (AndroidApplication, "android/app/Application")
735 #undef JNI_CLASS_MEMBERS
736 
737 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
738  METHOD (constructor,     "<init>",          "(Landroid/content/Context;)V") \
739  METHOD (getHolder,       "getHolder",       "()Landroid/view/SurfaceHolder;") \
740  METHOD (getParent,       "getParent",       "()Landroid/view/ViewParent;")
741 
742  DECLARE_JNI_CLASS (AndroidSurfaceView, "android/view/SurfaceView")
743 #undef JNI_CLASS_MEMBERS
744 
745 
746 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
747  METHOD (getSurface,     "getSurface",     "()Landroid/view/Surface;") \
748  METHOD (addCallback,    "addCallback",    "(Landroid/view/SurfaceHolder$Callback;)V") \
749  METHOD (removeCallback, "removeCallback", "(Landroid/view/SurfaceHolder$Callback;)V")
750 
751  DECLARE_JNI_CLASS (AndroidSurfaceHolder, "android/view/SurfaceHolder")
752 #undef JNI_CLASS_MEMBERS
753 
754 //==============================================================================
755 namespace
756 {
juceString(JNIEnv * env,jstring s)757     inline String juceString (JNIEnv* env, jstring s)
758     {
759         if (s == nullptr)
760             return {};
761 
762         const char* const utf8 = env->GetStringUTFChars (s, nullptr);
763         CharPointer_UTF8 utf8CP (utf8);
764         const String result (utf8CP);
765         env->ReleaseStringUTFChars (s, utf8);
766         return result;
767     }
768 
juceString(jstring s)769     inline String juceString (jstring s)
770     {
771         return juceString (getEnv(), s);
772     }
773 
javaString(const String & s)774     inline LocalRef<jstring> javaString (const String& s)
775     {
776         return LocalRef<jstring> (getEnv()->NewStringUTF (s.toUTF8()));
777     }
778 
javaStringFromChar(const juce_wchar c)779     inline LocalRef<jstring> javaStringFromChar (const juce_wchar c)
780     {
781         char utf8[8] = { 0 };
782         CharPointer_UTF8 (utf8).write (c);
783         return LocalRef<jstring> (getEnv()->NewStringUTF (utf8));
784     }
785 
juceStringArrayToJava(const StringArray & juceArray)786     inline LocalRef<jobjectArray> juceStringArrayToJava (const StringArray& juceArray)
787     {
788         auto* env = getEnv();
789 
790         LocalRef<jobjectArray> result (env->NewObjectArray ((jsize) juceArray.size(),
791                                                             JavaString,
792                                                             javaString ("").get()));
793 
794         for (int i = 0; i < juceArray.size(); ++i)
795             env->SetObjectArrayElement (result, i, javaString (juceArray [i]).get());
796 
797         return result;
798     }
799 
javaStringArrayToJuce(const LocalRef<jobjectArray> & javaArray)800     inline StringArray javaStringArrayToJuce (const LocalRef<jobjectArray>& javaArray)
801     {
802         if (javaArray.get() == nullptr)
803             return {};
804 
805         auto* env = getEnv();
806 
807         StringArray result;
808 
809         for (int i = 0; i < env->GetArrayLength (javaArray.get()); ++i)
810         {
811             LocalRef<jstring> javaString ((jstring) env->GetObjectArrayElement (javaArray.get(), i));
812             result.add (juceString (javaString.get()));
813         }
814 
815         return result;
816     }
817 
jniCheckHasExceptionOccurredAndClear()818     inline bool jniCheckHasExceptionOccurredAndClear()
819     {
820         auto* env = getEnv();
821 
822         LocalRef<jobject> exception (env->ExceptionOccurred());
823 
824         if (exception != nullptr)
825         {
826             env->ExceptionClear();
827             return true;
828         }
829 
830         return false;
831     }
832 }
833 
834 //==============================================================================
835 int getAndroidSDKVersion();
836 bool isPermissionDeclaredInManifest (const String& requestedPermission);
837 
838 //==============================================================================
839 class AndroidInterfaceImplementer;
840 
841 // This function takes ownership of the implementer. When the returned GlobalRef
842 // goes out of scope (and no other Java routine has a reference on the return-value)
843 // then the implementer will be deleted as well.
844 LocalRef<jobject> CreateJavaInterface (AndroidInterfaceImplementer* implementer,
845                                        const StringArray& interfaceNames,
846                                        LocalRef<jobject> subclass);
847 
848 //==============================================================================
849 jobject juce_invokeImplementer (JNIEnv*, jobject, jlong, jobject, jobject, jobjectArray);
850 void    juce_dispatchDelete    (JNIEnv*, jobject, jlong);
851 
852 //==============================================================================
853 class AndroidInterfaceImplementer
854 {
855 protected:
856     virtual ~AndroidInterfaceImplementer();
857     virtual jobject invoke (jobject proxy, jobject method, jobjectArray args);
858     void clear();
859 
860     //==============================================================================
861     friend LocalRef<jobject> CreateJavaInterface (AndroidInterfaceImplementer*, const StringArray&, LocalRef<jobject>);
862     friend jobject juce_invokeImplementer (JNIEnv*, jobject, jlong, jobject, jobject, jobjectArray);
863     friend void    juce_dispatchDelete    (JNIEnv*, jobject, jlong);
864 private:
865     GlobalRef javaSubClass;
866     GlobalRef invocationHandler;
867 };
868 
869 LocalRef<jobject> CreateJavaInterface (AndroidInterfaceImplementer* implementer,
870                                        const StringArray& interfaceNames);
871 LocalRef<jobject> CreateJavaInterface (AndroidInterfaceImplementer* implementer,
872                                        const String& interfaceName);
873 
874 //==============================================================================
875 class ActivityLifecycleCallbacks     : public AndroidInterfaceImplementer
876 {
877 public:
onActivityPreCreated(jobject,jobject)878     virtual void onActivityPreCreated            (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityPreDestroyed(jobject)879     virtual void onActivityPreDestroyed          (jobject /*activity*/)                      {}
onActivityPrePaused(jobject)880     virtual void onActivityPrePaused             (jobject /*activity*/)                      {}
onActivityPreResumed(jobject)881     virtual void onActivityPreResumed            (jobject /*activity*/)                      {}
onActivityPreSaveInstanceState(jobject,jobject)882     virtual void onActivityPreSaveInstanceState  (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityPreStarted(jobject)883     virtual void onActivityPreStarted            (jobject /*activity*/)                      {}
onActivityPreStopped(jobject)884     virtual void onActivityPreStopped            (jobject /*activity*/)                      {}
885 
onActivityCreated(jobject,jobject)886     virtual void onActivityCreated               (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityDestroyed(jobject)887     virtual void onActivityDestroyed             (jobject /*activity*/)                      {}
onActivityPaused(jobject)888     virtual void onActivityPaused                (jobject /*activity*/)                      {}
onActivityResumed(jobject)889     virtual void onActivityResumed               (jobject /*activity*/)                      {}
onActivitySaveInstanceState(jobject,jobject)890     virtual void onActivitySaveInstanceState     (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityStarted(jobject)891     virtual void onActivityStarted               (jobject /*activity*/)                      {}
onActivityStopped(jobject)892     virtual void onActivityStopped               (jobject /*activity*/)                      {}
893 
onActivityPostCreated(jobject,jobject)894     virtual void onActivityPostCreated           (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityPostDestroyed(jobject)895     virtual void onActivityPostDestroyed         (jobject /*activity*/)                      {}
onActivityPostPaused(jobject)896     virtual void onActivityPostPaused            (jobject /*activity*/)                      {}
onActivityPostResumed(jobject)897     virtual void onActivityPostResumed           (jobject /*activity*/)                      {}
onActivityPostSaveInstanceState(jobject,jobject)898     virtual void onActivityPostSaveInstanceState (jobject /*activity*/, jobject /*bundle*/)  {}
onActivityPostStarted(jobject)899     virtual void onActivityPostStarted           (jobject /*activity*/)                      {}
onActivityPostStopped(jobject)900     virtual void onActivityPostStopped           (jobject /*activity*/)                      {}
901 
902 private:
903     jobject invoke (jobject, jobject, jobjectArray) override;
904 };
905 
906 //==============================================================================
907 struct SurfaceHolderCallback    : AndroidInterfaceImplementer
908 {
909     virtual ~SurfaceHolderCallback() override = default;
910 
911     virtual void surfaceChanged (LocalRef<jobject> holder, int format, int width, int height) = 0;
912     virtual void surfaceCreated (LocalRef<jobject> holder) = 0;
913     virtual void surfaceDestroyed (LocalRef<jobject> holder) = 0;
914 
915 private:
invokeSurfaceHolderCallback916     jobject invoke (jobject proxy, jobject method, jobjectArray args) override
917     {
918         auto* env = getEnv();
919         auto methodName = juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName));
920         LocalRef<jobject> holder (env->GetArrayLength (args) > 0 ? env->GetObjectArrayElement (args, 0) : (jobject) nullptr);
921 
922         if (methodName == "surfaceChanged")
923         {
924             int intArgs[3];
925 
926             for (int i = 0; i < 3; ++i)
927             {
928                 LocalRef<jobject> boxedType (env->GetObjectArrayElement (args, 1 + i));
929                 intArgs[i] = env->CallIntMethod (boxedType.get(), JavaInteger.intValue);
930             }
931 
932             surfaceChanged (std::move (holder), intArgs[0], intArgs[1], intArgs[2]);
933         }
934         else if (methodName == "surfaceCreated")
935         {
936             surfaceCreated (std::move (holder));
937         }
938         else if (methodName == "surfaceDestroyed")
939         {
940             surfaceDestroyed (std::move (holder));
941         }
942         else
943         {
944             return AndroidInterfaceImplementer::invoke (proxy, method, args);
945         }
946 
947         return nullptr;
948     }
949 };
950 
951 //==============================================================================
952 class FragmentOverlay
953 {
954 public:
955     FragmentOverlay();
956     virtual ~FragmentOverlay();
957 
958     void open();
959 
onCreated(LocalRef<jobject>)960     virtual void onCreated (LocalRef<jobject> /*bundle*/) {}
onStart()961     virtual void onStart() {}
onRequestPermissionsResult(int,const StringArray &,const Array<int> &)962     virtual void onRequestPermissionsResult (int /*requestCode*/,
963                                              const StringArray& /*permissions*/,
964                                              const Array<int>& /*grantResults*/) {}
onActivityResult(int,int,LocalRef<jobject>)965     virtual void onActivityResult (int /*requestCode*/, int /*resultCode*/, LocalRef<jobject> /*data*/) {}
966 
967 protected:
968     jobject getNativeHandle();
969 
970 private:
971 
972     GlobalRef native;
973 
974 public:
975     /* internal: do not use */
976     static void onActivityResultNative (JNIEnv*, jobject, jlong, jint, jint, jobject);
977     static void onCreateNative (JNIEnv*, jobject, jlong, jobject);
978     static void onStartNative (JNIEnv*, jobject, jlong);
979     static void onRequestPermissionsResultNative (JNIEnv*, jobject, jlong, jint,
980                                                   jobjectArray, jintArray);
981 };
982 
983 //==============================================================================
984 // Allows you to start an activity without requiring to have an activity
985 void startAndroidActivityForResult (const LocalRef<jobject>& intent, int requestCode,
986                                     std::function<void (int, int, LocalRef<jobject>)> && callback);
987 
988 //==============================================================================
989 bool androidHasSystemFeature (const String& property);
990 String audioManagerGetProperty (const String& property);
991 
992 } // namespace juce
993