diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj
index bca8d68e5c..151e200ddc 100644
--- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj
@@ -1045,6 +1045,7 @@
59C46E289F86C80D4341EAA3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Files.cpp"; path = "../../src/native/android/juce_android_Files.cpp"; sourceTree = "SOURCE_ROOT"; };
FA82460758BDCB2DCCE1EAAA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Fonts.cpp"; path = "../../src/native/android/juce_android_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; };
CE06EEED7426AA45C27B629C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../src/native/android/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; };
+ F439E6C4B2D2AF19645252C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../src/native/android/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; };
1D74C9567283836ECC70E48B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../src/native/android/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; };
40216CE846A54CE706131A23 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Midi.cpp"; path = "../../src/native/android/juce_android_Midi.cpp"; sourceTree = "SOURCE_ROOT"; };
E646726910F110DC34DD1662 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Misc.cpp"; path = "../../src/native/android/juce_android_Misc.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1889,6 +1890,7 @@
59C46E289F86C80D4341EAA3,
FA82460758BDCB2DCCE1EAAA,
CE06EEED7426AA45C27B629C,
+ F439E6C4B2D2AF19645252C0,
1D74C9567283836ECC70E48B,
40216CE846A54CE706131A23,
E646726910F110DC34DD1662,
diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj
index a36c3cef00..315e85a692 100644
--- a/Builds/VisualStudio2005/Juce.vcproj
+++ b/Builds/VisualStudio2005/Juce.vcproj
@@ -951,6 +951,7 @@
+
diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj
index 1c2aae5792..4bf4265ce0 100644
--- a/Builds/VisualStudio2008/Juce.vcproj
+++ b/Builds/VisualStudio2008/Juce.vcproj
@@ -951,6 +951,7 @@
+
diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj
index 1c8a608a17..16212248ae 100644
--- a/Builds/VisualStudio2008_DLL/Juce.vcproj
+++ b/Builds/VisualStudio2008_DLL/Juce.vcproj
@@ -953,6 +953,7 @@
+
diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj
index a119988e57..a2de3370d0 100644
--- a/Builds/VisualStudio2010/Juce.vcxproj
+++ b/Builds/VisualStudio2010/Juce.vcxproj
@@ -794,6 +794,7 @@
+
diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters
index 5fc890c022..cc426e1c8f 100644
--- a/Builds/VisualStudio2010/Juce.vcxproj.filters
+++ b/Builds/VisualStudio2010/Juce.vcxproj.filters
@@ -2313,6 +2313,9 @@
Juce\Source\native\windows
+
+ Juce\Source\native\android
+
Juce\Source\native\android
diff --git a/Builds/iOS/Juce.xcodeproj/project.pbxproj b/Builds/iOS/Juce.xcodeproj/project.pbxproj
index 9124e3dd91..e692a5f28f 100644
--- a/Builds/iOS/Juce.xcodeproj/project.pbxproj
+++ b/Builds/iOS/Juce.xcodeproj/project.pbxproj
@@ -1045,6 +1045,7 @@
59C46E289F86C80D4341EAA3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Files.cpp"; path = "../../src/native/android/juce_android_Files.cpp"; sourceTree = "SOURCE_ROOT"; };
FA82460758BDCB2DCCE1EAAA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Fonts.cpp"; path = "../../src/native/android/juce_android_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; };
CE06EEED7426AA45C27B629C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../src/native/android/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; };
+ F439E6C4B2D2AF19645252C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../src/native/android/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; };
1D74C9567283836ECC70E48B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../src/native/android/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; };
40216CE846A54CE706131A23 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Midi.cpp"; path = "../../src/native/android/juce_android_Midi.cpp"; sourceTree = "SOURCE_ROOT"; };
E646726910F110DC34DD1662 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Misc.cpp"; path = "../../src/native/android/juce_android_Misc.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1889,6 +1890,7 @@
59C46E289F86C80D4341EAA3,
FA82460758BDCB2DCCE1EAAA,
CE06EEED7426AA45C27B629C,
+ F439E6C4B2D2AF19645252C0,
1D74C9567283836ECC70E48B,
40216CE846A54CE706131A23,
E646726910F110DC34DD1662,
diff --git a/Juce.jucer b/Juce.jucer
index a27b39a836..0c7db697d7 100644
--- a/Juce.jucer
+++ b/Juce.jucer
@@ -1478,6 +1478,8 @@
file="src/native/android/juce_android_Fonts.cpp"/>
+
", "()V") \
- METHOD (stringBufferClass, stringBufferToString, "toString", "()Ljava/lang/String;") \
-\
- METHOD (httpStreamClass, httpStreamRelease, "release", "()V") \
- METHOD (httpStreamClass, httpStreamRead, "read", "([BI)I") \
- METHOD (httpStreamClass, getPosition, "getPosition", "()J") \
- METHOD (httpStreamClass, getTotalLength, "getTotalLength", "()J") \
- METHOD (httpStreamClass, isExhausted, "isExhausted", "()Z") \
- METHOD (httpStreamClass, setPosition, "setPosition", "(J)Z") \
-\
- METHOD (fileClass, fileExists, "exists", "()Z") \
- STATICMETHOD (systemClass, getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \
-\
- METHOD (componentPeerViewClass, setViewName, "setViewName", "(Ljava/lang/String;)V") \
- METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \
- METHOD (componentPeerViewClass, getLeft, "getLeft", "()I") \
- METHOD (componentPeerViewClass, getTop, "getTop", "()I") \
- METHOD (componentPeerViewClass, getWidth, "getWidth", "()I") \
- METHOD (componentPeerViewClass, getHeight, "getHeight", "()I") \
- METHOD (componentPeerViewClass, getLocationOnScreen, "getLocationOnScreen", "([I)V") \
- METHOD (componentPeerViewClass, bringToFront, "bringToFront", "()V") \
- METHOD (componentPeerViewClass, requestFocus, "requestFocus", "()Z") \
- METHOD (componentPeerViewClass, setVisible, "setVisible", "(Z)V") \
- METHOD (componentPeerViewClass, isVisible, "isVisible", "()Z") \
- METHOD (componentPeerViewClass, hasFocus, "hasFocus", "()Z") \
- METHOD (componentPeerViewClass, invalidate, "invalidate", "(IIII)V") \
- METHOD (componentPeerViewClass, containsPoint, "containsPoint", "(II)Z") \
-\
- METHOD (canvasClass, drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \
-\
- METHOD (paintClass, paintClassConstructor, "", "(I)V") \
- METHOD (paintClass, setColor, "setColor", "(I)V") \
- METHOD (paintClass, setAlpha, "setAlpha", "(I)V") \
- METHOD (paintClass, setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
- METHOD (paintClass, ascent, "ascent", "()F") \
- METHOD (paintClass, descent, "descent", "()F") \
- METHOD (paintClass, setTextSize, "setTextSize", "(F)V") \
- METHOD (paintClass, getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \
- METHOD (paintClass, setTextScaleX, "setTextScaleX", "(F)V") \
- METHOD (paintClass, getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
-\
- METHOD (matrixClass, matrixClassConstructor, "", "()V") \
- METHOD (matrixClass, setValues, "setValues", "([F)V") \
-\
- STATICMETHOD (typefaceClass, create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \
- STATICMETHOD (typefaceClass, createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
-\
- METHOD (rectClass, rectConstructor, "", "(IIII)V") \
- FIELD (rectClass, rectLeft, "left", "I") \
- FIELD (rectClass, rectRight, "right", "I") \
- FIELD (rectClass, rectTop, "top", "I") \
- FIELD (rectClass, rectBottom, "bottom", "I") \
-\
- METHOD (audioTrackClass, audioTrackConstructor, "", "(IIIIII)V") \
- STATICMETHOD (audioTrackClass, getMinBufferSize, "getMinBufferSize", "(III)I") \
- STATICMETHOD (audioTrackClass, getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \
- METHOD (audioTrackClass, audioTrackPlay, "play", "()V") \
- METHOD (audioTrackClass, audioTrackStop, "stop", "()V") \
- METHOD (audioTrackClass, audioTrackRelease, "release", "()V") \
- METHOD (audioTrackClass, audioTrackFlush, "flush", "()V") \
- METHOD (audioTrackClass, audioTrackWrite, "write", "([SII)I") \
-\
- METHOD (audioRecordClass, audioRecordConstructor, "", "(IIIII)V"); \
- STATICMETHOD (audioRecordClass, getMinRecordBufferSize, "getMinBufferSize", "(III)I") \
- METHOD (audioRecordClass, startRecording, "startRecording", "()V"); \
- METHOD (audioRecordClass, stopRecording, "stop", "()V"); \
- METHOD (audioRecordClass, audioRecordRead, "read", "([SII)I"); \
- METHOD (audioRecordClass, audioRecordRelease, "release", "()V"); \
-
-// List of extra methods needed when USE_ANDROID_CANVAS is enabled
-#if ! USE_ANDROID_CANVAS
-#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD)
-#else
-#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- METHOD (pathClass, pathClassConstructor, "", "()V") \
- METHOD (pathClass, moveTo, "moveTo", "(FF)V") \
- METHOD (pathClass, lineTo, "lineTo", "(FF)V") \
- METHOD (pathClass, quadTo, "quadTo", "(FFFF)V") \
- METHOD (pathClass, cubicTo, "cubicTo", "(FFFFFF)V") \
- METHOD (pathClass, closePath, "close", "()V") \
- METHOD (pathClass, computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \
-\
- STATICMETHOD (bitmapClass, createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \
- STATICFIELD (bitmapConfigClass, ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \
- STATICFIELD (bitmapConfigClass, ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \
- METHOD (bitmapClass, bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \
- METHOD (bitmapClass, getPixels, "getPixels", "([IIIIIII)V") \
- METHOD (bitmapClass, setPixels, "setPixels", "([IIIIIII)V") \
- METHOD (bitmapClass, recycle, "recycle", "()V") \
-\
- METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \
- STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \
-\
- METHOD (bitmapShaderClass, bitmapShaderConstructor, "", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
-\
- METHOD (canvasClass, canvasBitmapConstructor, "", "(Landroid/graphics/Bitmap;)V") \
- METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, translate, "translate", "(FF)V") \
- METHOD (canvasClass, clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \
- METHOD (canvasClass, clipRect, "clipRect", "(FFFF)Z") \
- METHOD (canvasClass, clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \
- METHOD (canvasClass, concat, "concat", "(Landroid/graphics/Matrix;)V") \
- METHOD (canvasClass, drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \
- METHOD (canvasClass, getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \
- METHOD (canvasClass, save, "save", "()I") \
- METHOD (canvasClass, restore, "restore", "()V") \
- METHOD (canvasClass, saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I") \
-\
- METHOD (linearGradientClass, linearGradientConstructor, "", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (radialGradientClass, radialGradientConstructor, "", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (regionClass, regionConstructor, "", "()V"); \
- METHOD (regionClass, regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \
+/*** Start of inlined file: juce_android_JNIHelpers.h ***/
+#ifndef __JUCE_ANDROID_JNIHELPERS_JUCEHEADER__
+#define __JUCE_ANDROID_JNIHELPERS_JUCEHEADER__
+#ifndef USE_ANDROID_CANVAS
+ #define USE_ANDROID_CANVAS 0
#endif
-class ThreadLocalJNIEnvHolder
-{
-public:
- ThreadLocalJNIEnvHolder()
- : jvm (0)
- {
- zeromem (threads, sizeof (threads));
- zeromem (envs, sizeof (envs));
- }
-
- void initialise (JNIEnv* env)
- {
- env->GetJavaVM (&jvm);
- addEnv (env);
- }
-
- void attach()
- {
- JNIEnv* env = nullptr;
- jvm->AttachCurrentThread (&env, 0);
-
- if (env != 0)
- addEnv (env);
- }
-
- void detach()
- {
- jvm->DetachCurrentThread();
-
- const pthread_t thisThread = pthread_self();
-
- SpinLock::ScopedLockType sl (addRemoveLock);
- for (int i = 0; i < maxThreads; ++i)
- if (threads[i] == thisThread)
- threads[i] = 0;
- }
-
- JNIEnv* get() const noexcept
- {
- const pthread_t thisThread = pthread_self();
-
- for (int i = 0; i < maxThreads; ++i)
- if (threads[i] == thisThread)
- return envs[i];
-
- return nullptr;
- }
-
- enum { maxThreads = 16 };
-
-private:
- JavaVM* jvm;
- pthread_t threads [maxThreads];
- JNIEnv* envs [maxThreads];
- SpinLock addRemoveLock;
-
- void addEnv (JNIEnv* env)
- {
- SpinLock::ScopedLockType sl (addRemoveLock);
-
- if (get() == 0)
- {
- const pthread_t thisThread = pthread_self();
-
- for (int i = 0; i < maxThreads; ++i)
- {
- if (threads[i] == 0)
- {
- envs[i] = env;
- threads[i] = thisThread;
- return;
- }
- }
- }
-
- jassertfalse; // too many threads!
- }
-};
-
-static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
-
-struct AndroidThreadScope
-{
- AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
- ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
-};
-
-static inline JNIEnv* getEnv() noexcept
-{
- return threadLocalJNIEnvHolder.get();
-}
+extern JNIEnv* getEnv() noexcept;
class GlobalRef
{
public:
- inline GlobalRef() noexcept
- : obj (0)
- {
- }
-
- inline explicit GlobalRef (jobject obj_)
- : obj (retain (obj_))
- {
- }
-
- inline GlobalRef (const GlobalRef& other)
- : obj (retain (other.obj))
- {
- }
-
- ~GlobalRef()
- {
- clear();
- }
+ inline GlobalRef() noexcept : obj (0) {}
+ inline explicit GlobalRef (jobject obj_) : obj (retain (obj_)) {}
+ inline GlobalRef (const GlobalRef& other) : obj (retain (other.obj)) {}
+ ~GlobalRef() { clear(); }
inline void clear()
{
@@ -288490,8 +288225,9 @@ public:
inline GlobalRef& operator= (const GlobalRef& other)
{
+ jobject newObj = retain (other.obj);
clear();
- obj = retain (other.obj);
+ obj = newObj;
return *this;
}
@@ -288541,17 +288277,11 @@ template
class LocalRef
{
public:
- explicit inline LocalRef (JavaType obj_) noexcept
- : obj (obj_)
- {
- }
-
- inline LocalRef (const LocalRef& other) noexcept
- : obj (retain (other.obj))
- {
- }
+ explicit inline LocalRef (JavaType obj_) noexcept : obj (obj_){}
+ inline LocalRef (const LocalRef& other) noexcept : obj (retain (other.obj)) {}
+ ~LocalRef() { clear(); }
- ~LocalRef()
+ void clear()
{
if (obj != 0)
getEnv()->DeleteLocalRef (obj);
@@ -288559,14 +288289,9 @@ public:
LocalRef& operator= (const LocalRef& other)
{
- if (obj != other.obj)
- {
- if (obj != 0)
- getEnv()->DeleteLocalRef (obj);
-
- obj = retain (other.obj);
- }
-
+ jobject newObj = retain (other.obj);
+ clear();
+ obj = newObj;
return *this;
}
@@ -288582,208 +288307,396 @@ private:
}
};
-static const String juceString (jstring s)
+namespace
{
- JNIEnv* env = getEnv();
+ String juceString (JNIEnv* env, jstring s)
+ {
+ jboolean isCopy;
+ const char* const utf8 = env->GetStringUTFChars (s, &isCopy);
+ CharPointer_UTF8 utf8CP (utf8);
+ const String result (utf8CP);
+ env->ReleaseStringUTFChars (s, utf8);
+ return result;
+ }
- jboolean isCopy;
- const char* const utf8 = env->GetStringUTFChars (s, &isCopy);
- CharPointer_UTF8 utf8CP (utf8);
- const String result (utf8CP);
- env->ReleaseStringUTFChars (s, utf8);
- return result;
+ String juceString (jstring s)
+ {
+ return juceString (getEnv(), s);
+ }
+
+ LocalRef javaString (const String& s)
+ {
+ return LocalRef (getEnv()->NewStringUTF (s.toUTF8()));
+ }
+
+ LocalRef javaStringFromChar (const juce_wchar c)
+ {
+ char utf8[8] = { 0 };
+ CharPointer_UTF8 (utf8).write (c);
+ return LocalRef (getEnv()->NewStringUTF (utf8));
+ }
+}
+
+class JNIClassBase
+{
+public:
+ explicit JNIClassBase (const char* classPath_);
+ virtual ~JNIClassBase();
+
+ inline operator jclass() const noexcept { return classRef; }
+
+ static void initialiseAllClasses (JNIEnv*);
+ static void releaseAllClasses (JNIEnv*);
+
+protected:
+ virtual void initialiseFields (JNIEnv*) = 0;
+
+ jmethodID resolveMethod (JNIEnv*, const char* methodName, const char* params);
+ jmethodID resolveStaticMethod (JNIEnv*, const char* methodName, const char* params);
+ jfieldID resolveField (JNIEnv*, const char* fieldName, const char* signature);
+ jfieldID resolveStaticField (JNIEnv*, const char* fieldName, const char* signature);
+
+private:
+ const char* const classPath;
+ jclass classRef;
+
+ static Array& getClasses();
+ void initialise (JNIEnv*);
+ void release (JNIEnv*);
+
+ JUCE_DECLARE_NON_COPYABLE (JNIClassBase);
+};
+
+#define CREATE_JNI_METHOD(methodID, stringName, params) methodID = resolveMethod (env, stringName, params);
+#define CREATE_JNI_STATICMETHOD(methodID, stringName, params) methodID = resolveStaticMethod (env, stringName, params);
+#define CREATE_JNI_FIELD(fieldID, stringName, signature) fieldID = resolveField (env, stringName, signature);
+#define CREATE_JNI_STATICFIELD(fieldID, stringName, signature) fieldID = resolveStaticField (env, stringName, signature);
+#define DECLARE_JNI_METHOD(methodID, stringName, params) jmethodID methodID;
+#define DECLARE_JNI_FIELD(fieldID, stringName, signature) jfieldID fieldID;
+
+#define DECLARE_JNI_CLASS(CppClassName, javaPath) \
+ class CppClassName ## _Class : public JNIClassBase \
+ { \
+ public: \
+ CppClassName ## _Class() : JNIClassBase (javaPath) {} \
+ \
+ void initialiseFields (JNIEnv* env) \
+ { \
+ JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD); \
+ } \
+ \
+ JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD); \
+ }; \
+ static CppClassName ## _Class CppClassName;
+
+#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \
+ extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params
+
+class AndroidSystem
+{
+public:
+ AndroidSystem();
+
+ void initialise (JNIEnv*, jobject activity, jstring appFile, jstring appDataDir);
+ void shutdown (JNIEnv*);
+
+ GlobalRef activity;
+ String appFile, appDataDir;
+ int screenWidth, screenHeight;
+
+ jobject createPaint (Graphics::ResamplingQuality quality);
+ const jobject createMatrix (JNIEnv*, const AffineTransform& t);
+};
+
+extern AndroidSystem android;
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (printToConsole, "printToConsole", "(Ljava/lang/String;)V") \
+ METHOD (createNewView, "createNewView", "(Z)Lcom/juce/ComponentPeerView;") \
+ METHOD (deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \
+ METHOD (postMessage, "postMessage", "(J)V") \
+ METHOD (finish, "finish", "()V") \
+ METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \
+ METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
+ METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
+ METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
+ STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \
+ METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+
+DECLARE_JNI_CLASS (JuceAppActivity, "com/juce/JuceAppActivity");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(I)V") \
+ METHOD (setColor, "setColor", "(I)V") \
+ METHOD (setAlpha, "setAlpha", "(I)V") \
+ METHOD (setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
+ METHOD (ascent, "ascent", "()F") \
+ METHOD (descent, "descent", "()F") \
+ METHOD (setTextSize, "setTextSize", "(F)V") \
+ METHOD (getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \
+ METHOD (setTextScaleX, "setTextScaleX", "(F)V") \
+ METHOD (getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
+ METHOD (setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
+
+DECLARE_JNI_CLASS (Paint, "android/graphics/Paint");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V") \
+ METHOD (setValues, "setValues", "([F)V") \
+
+DECLARE_JNI_CLASS (Matrix, "android/graphics/Matrix");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(IIII)V") \
+ FIELD (left, "left", "I") \
+ FIELD (right, "right", "I") \
+ FIELD (top, "top", "I") \
+ FIELD (bottom, "bottom", "I") \
+
+DECLARE_JNI_CLASS (RectClass, "android/graphics/Rect");
+#undef JNI_CLASS_MEMBERS
+
+#endif // __JUCE_ANDROID_JNIHELPERS_JUCEHEADER__
+
+/*** End of inlined file: juce_android_JNIHelpers.h ***/
+
+#define JUCE_INCLUDED_FILE 1
+
+// Now include the actual code files..
+
+/*** Start of inlined file: juce_android_SystemStats.cpp ***/
+// (This file gets included by juce_android_NativeCode.cpp, rather than being
+// compiled on its own).
+#if JUCE_INCLUDED_FILE
+
+JNIClassBase::JNIClassBase (const char* classPath_)
+ : classPath (classPath_), classRef (0)
+{
+ getClasses().add (this);
+}
+
+JNIClassBase::~JNIClassBase()
+{
+ getClasses().removeValue (this);
+}
+
+Array& JNIClassBase::getClasses()
+{
+ static Array classes;
+ return classes;
+}
+
+void JNIClassBase::initialise (JNIEnv* env)
+{
+ classRef = (jclass) env->NewGlobalRef (env->FindClass (classPath));
+ jassert (classRef != 0);
+
+ initialiseFields (env);
+}
+
+void JNIClassBase::release (JNIEnv* env)
+{
+ env->DeleteGlobalRef (classRef);
}
-static const LocalRef javaString (const String& s)
+void JNIClassBase::initialiseAllClasses (JNIEnv* env)
{
- return LocalRef (getEnv()->NewStringUTF (s.toUTF8()));
+ Array& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->initialise (env);
}
-static const LocalRef javaStringFromChar (const juce_wchar c)
+void JNIClassBase::releaseAllClasses (JNIEnv* env)
{
- char utf8[5] = { 0 };
- CharPointer_UTF8 (utf8).write (c);
- return LocalRef (getEnv()->NewStringUTF (utf8));
+ Array& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->release (env);
}
-class AndroidJavaCallbacks
+jmethodID JNIClassBase::resolveMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jmethodID JNIClassBase::resolveStaticMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetStaticMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jfieldID JNIClassBase::resolveField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+jfieldID JNIClassBase::resolveStaticField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetStaticFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+class ThreadLocalJNIEnvHolder
{
public:
- AndroidJavaCallbacks() : screenWidth (0), screenHeight (0)
+ ThreadLocalJNIEnvHolder()
+ : jvm (nullptr)
{
+ zeromem (threads, sizeof (threads));
+ zeromem (envs, sizeof (envs));
}
- void initialise (JNIEnv* env, jobject activity_,
- jstring appFile_, jstring appDataDir_)
+ void initialise (JNIEnv* env)
{
- threadLocalJNIEnvHolder.initialise (env);
- activity = GlobalRef (activity_);
- appFile = juceString (appFile_);
- appDataDir = juceString (appDataDir_);
-
- #define CREATE_JNI_CLASS(className, path) \
- className = (jclass) env->NewGlobalRef (env->FindClass (path)); \
- jassert (className != 0);
- JUCE_JNI_CLASSES (CREATE_JNI_CLASS);
- #undef CREATE_JNI_CLASS
-
- #define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \
- methodID = env->GetMethodID (ownerClass, stringName, params); \
- jassert (methodID != 0);
- #define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \
- methodID = env->GetStaticMethodID (ownerClass, stringName, params); \
- jassert (methodID != 0);
- #define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \
- fieldID = env->GetFieldID (ownerClass, stringName, signature); \
- jassert (fieldID != 0);
- #define CREATE_JNI_STATICFIELD(ownerClass, fieldID, stringName, signature) \
- fieldID = env->GetStaticFieldID (ownerClass, stringName, signature); \
- jassert (fieldID != 0);
- JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD);
- #undef CREATE_JNI_METHOD
+ env->GetJavaVM (&jvm);
+ addEnv (env);
}
- void shutdown()
+ void attach()
{
- JNIEnv* env = getEnv();
+ JNIEnv* env = nullptr;
+ jvm->AttachCurrentThread (&env, 0);
if (env != 0)
- {
- #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className);
- JUCE_JNI_CLASSES (RELEASE_JNI_CLASS);
- #undef RELEASE_JNI_CLASS
-
- activity.clear();
- }
+ addEnv (env);
}
- GlobalRef activity;
- String appFile, appDataDir;
- int screenWidth, screenHeight;
-
- jobject createPaint (Graphics::ResamplingQuality quality)
+ void detach()
{
- jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/
- | 4 /*DITHER_FLAG*/
- | 128 /*SUBPIXEL_TEXT_FLAG*/;
+ jvm->DetachCurrentThread();
- if (quality > Graphics::lowResamplingQuality)
- constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/
+ const pthread_t thisThread = pthread_self();
- return getEnv()->NewObject (paintClass, paintClassConstructor, constructorFlags);
+ SpinLock::ScopedLockType sl (addRemoveLock);
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ threads[i] = 0;
}
- const jobject createMatrix (JNIEnv* env, const AffineTransform& t)
+ JNIEnv* get() const noexcept
{
- jobject m = env->NewObject (matrixClass, matrixClassConstructor);
-
- jfloat values[9] = { t.mat00, t.mat01, t.mat02,
- t.mat10, t.mat11, t.mat12,
- 0.0f, 0.0f, 1.0f };
-
- jfloatArray javaArray = env->NewFloatArray (9);
- env->SetFloatArrayRegion (javaArray, 0, 9, values);
+ const pthread_t thisThread = pthread_self();
- env->CallVoidMethod (m, setValues, javaArray);
- env->DeleteLocalRef (javaArray);
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ return envs[i];
- return m;
+ return nullptr;
}
- #define DECLARE_JNI_CLASS(className, path) jclass className;
- JUCE_JNI_CLASSES (DECLARE_JNI_CLASS);
- #undef DECLARE_JNI_CLASS
-
- #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID;
- #define DECLARE_JNI_FIELD(ownerClass, fieldID, stringName, signature) jfieldID fieldID;
- JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD);
- #undef DECLARE_JNI_METHOD
-};
+ enum { maxThreads = 16 };
-static AndroidJavaCallbacks android;
+private:
+ JavaVM* jvm;
+ pthread_t threads [maxThreads];
+ JNIEnv* envs [maxThreads];
+ SpinLock addRemoveLock;
-// This is an unsatisfactory workaround for a linker warning that appeared in NDK5c.
-// If anyone actually understands what this symbol is for and why the linker gets confused by it,
-// please let me know!
-extern "C" { void* __dso_handle = 0; }
+ void addEnv (JNIEnv* env)
+ {
+ SpinLock::ScopedLockType sl (addRemoveLock);
-#define JUCE_INCLUDED_FILE 1
+ if (get() == nullptr)
+ {
+ const pthread_t thisThread = pthread_self();
-// Now include the actual code files..
+ for (int i = 0; i < maxThreads; ++i)
+ {
+ if (threads[i] == 0)
+ {
+ envs[i] = env;
+ threads[i] = thisThread;
+ return;
+ }
+ }
+ }
-/*** Start of inlined file: juce_android_Misc.cpp ***/
-// (This file gets included by juce_android_NativeCode.cpp, rather than being
-// compiled on its own).
-#if JUCE_INCLUDED_FILE
+ jassertfalse; // too many threads!
+ }
+};
-END_JUCE_NAMESPACE
-extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION)
-BEGIN_JUCE_NAMESPACE
+static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
-JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity,
- jstring appFile, jstring appDataDir))
+JNIEnv* getEnv() noexcept
{
- android.initialise (env, activity, appFile, appDataDir);
-
- DBG (SystemStats::getJUCEVersion());
-
- JUCEApplication::createInstance = &juce_CreateApplication;
-
- initialiseJuce_GUI();
+ return threadLocalJNIEnvHolder.get();
+}
- if (! JUCEApplication::createInstance()->initialiseApp (String::empty))
- exit (0);
+AndroidSystem::AndroidSystem() : screenWidth (0), screenHeight (0)
+{
}
-JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity))
+void AndroidSystem::initialise (JNIEnv* env, jobject activity_,
+ jstring appFile_, jstring appDataDir_)
{
- JUCEApplication::appWillTerminateByForce();
+ JNIClassBase::initialiseAllClasses (env);
- android.shutdown();
+ threadLocalJNIEnvHolder.initialise (env);
+ activity = GlobalRef (activity_);
+ appFile = juceString (env, appFile_);
+ appDataDir = juceString (env, appDataDir_);
}
-void LookAndFeel::playAlertSound()
+void AndroidSystem::shutdown (JNIEnv* env)
{
+ activity.clear();
+ JNIClassBase::releaseAllClasses (env);
}
-void Logger::outputDebugString (const String& text)
+jobject AndroidSystem::createPaint (Graphics::ResamplingQuality quality)
{
- JNIEnv* const env = getEnv();
+ jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/
+ | 4 /*DITHER_FLAG*/
+ | 128 /*SUBPIXEL_TEXT_FLAG*/;
- if (env != nullptr)
- env->CallStaticVoidMethod (android.activityClass, android.printToConsole,
- javaString (text).get());
-}
+ if (quality > Graphics::lowResamplingQuality)
+ constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/
-void SystemClipboard::copyTextToClipboard (const String& text)
-{
- const LocalRef t (javaString (text));
- android.activity.callVoidMethod (android.setClipboardContent, t.get());
+ return getEnv()->NewObject (Paint, Paint.constructor, constructorFlags);
}
-String SystemClipboard::getTextFromClipboard()
+const jobject AndroidSystem::createMatrix (JNIEnv* env, const AffineTransform& t)
{
- const LocalRef text ((jstring) android.activity.callObjectMethod (android.getClipboardContent));
- return juceString (text);
-}
+ jobject m = env->NewObject (Matrix, Matrix.constructor);
-#endif
+ jfloat values[9] = { t.mat00, t.mat01, t.mat02,
+ t.mat10, t.mat11, t.mat12,
+ 0.0f, 0.0f, 1.0f };
-/*** End of inlined file: juce_android_Misc.cpp ***/
+ jfloatArray javaArray = env->NewFloatArray (9);
+ env->SetFloatArrayRegion (javaArray, 0, 9, values);
+ env->CallVoidMethod (m, Matrix.setValues, javaArray);
+ env->DeleteLocalRef (javaArray);
+ return m;
+}
-/*** Start of inlined file: juce_android_SystemStats.cpp ***/
-// (This file gets included by juce_android_NativeCode.cpp, rather than being
-// compiled on its own).
-#if JUCE_INCLUDED_FILE
+AndroidSystem android;
namespace AndroidStatsHelpers
{
+
+ #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;")
+
+ DECLARE_JNI_CLASS (SystemClass, "java/lang/System");
+ #undef JNI_CLASS_MEMBERS
+
String getSystemProperty (const String& name)
{
- return juceString (LocalRef ((jstring) getEnv()->CallStaticObjectMethod (android.systemClass,
- android.getProperty,
+ return juceString (LocalRef ((jstring) getEnv()->CallStaticObjectMethod (SystemClass,
+ SystemClass.getProperty,
javaString (name).get())));
}
}
@@ -288800,11 +288713,11 @@ String SystemStats::getOperatingSystemName()
bool SystemStats::isOperatingSystem64Bit()
{
- #if JUCE_64BIT
+ #if JUCE_64BIT
return true;
- #else
+ #else
return false;
- #endif
+ #endif
}
String SystemStats::getCpuVendor()
@@ -288819,13 +288732,11 @@ int SystemStats::getCpuSpeedInMegaherz()
int SystemStats::getMemorySizeInMegabytes()
{
- // xxx they forgot to implement sysinfo in the library, dammit! Should put this stuff back when they fix it.
-/* struct sysinfo sysi;
+ struct sysinfo sysi;
if (sysinfo (&sysi) == 0)
return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
- */
- DBG ("warning! memory size is unavailable due to an Android bug!");
+
return 0;
}
@@ -288905,11 +288816,78 @@ bool Time::setSystemTimeToThisTime() const
return false;
}
+// This is an unsatisfactory workaround for a linker warning that appeared in NDK5c.
+// If anyone actually understands what this symbol is for and why the linker gets confused by it,
+// please let me know!
+extern "C" { void* __dso_handle = 0; }
+
#endif
/*** End of inlined file: juce_android_SystemStats.cpp ***/
+
+/*** Start of inlined file: juce_android_Misc.cpp ***/
+// (This file gets included by juce_android_NativeCode.cpp, rather than being
+// compiled on its own).
+#if JUCE_INCLUDED_FILE
+
+END_JUCE_NAMESPACE
+extern JUCE_NAMESPACE::JUCEApplication* juce_CreateApplication(); // (from START_JUCE_APPLICATION)
+BEGIN_JUCE_NAMESPACE
+
+JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity,
+ jstring appFile, jstring appDataDir))
+{
+ android.initialise (env, activity, appFile, appDataDir);
+
+ DBG (SystemStats::getJUCEVersion());
+
+ JUCEApplication::createInstance = &juce_CreateApplication;
+
+ initialiseJuce_GUI();
+
+ if (! JUCEApplication::createInstance()->initialiseApp (String::empty))
+ exit (0);
+}
+
+JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity))
+{
+ JUCEApplication::appWillTerminateByForce();
+
+ android.shutdown (env);
+}
+
+void LookAndFeel::playAlertSound()
+{
+}
+
+void Logger::outputDebugString (const String& text)
+{
+ JNIEnv* const env = getEnv();
+
+ if (env != nullptr)
+ env->CallStaticVoidMethod (JuceAppActivity, JuceAppActivity.printToConsole,
+ javaString (text).get());
+}
+
+void SystemClipboard::copyTextToClipboard (const String& text)
+{
+ const LocalRef t (javaString (text));
+ android.activity.callVoidMethod (JuceAppActivity.setClipboardContent, t.get());
+}
+
+String SystemClipboard::getTextFromClipboard()
+{
+ const LocalRef text ((jstring) android.activity.callObjectMethod (JuceAppActivity.getClipboardContent));
+ return juceString (text);
+}
+
+#endif
+
+/*** End of inlined file: juce_android_Misc.cpp ***/
+
+
/*** Start of inlined file: juce_posix_SharedCode.h ***/
/*
This file contains posix routines that are common to both the Linux and Mac builds.
@@ -289645,6 +289623,12 @@ void* threadEntryProc (void* userData)
JUCE_AUTORELEASEPOOL
#if JUCE_ANDROID
+ struct AndroidThreadScope
+ {
+ AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
+ ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
+ };
+
const AndroidThreadScope androidEnv;
#endif
@@ -290259,6 +290243,24 @@ void Process::lowerPrivilege() {}
// compiled on its own).
#if JUCE_INCLUDED_FILE
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V") \
+ METHOD (toString, "toString", "()Ljava/lang/String;") \
+
+DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (release, "release", "()V") \
+ METHOD (read, "read", "([BI)I") \
+ METHOD (getPosition, "getPosition", "()J") \
+ METHOD (getTotalLength, "getTotalLength", "()J") \
+ METHOD (isExhausted, "isExhausted", "()Z") \
+ METHOD (setPosition, "setPosition", "(J)Z") \
+
+DECLARE_JNI_CLASS (HTTPStream, "com/juce/JuceAppActivity$HTTPStream");
+#undef JNI_CLASS_MEMBERS
+
void MACAddress::findAllAddresses (Array& result)
{
// TODO
@@ -290294,10 +290296,10 @@ public:
env->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData());
}
- LocalRef responseHeaderBuffer (env->NewObject (android.stringBufferClass, android.stringBufferConstructor));
+ LocalRef responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor));
- stream = GlobalRef (env->CallStaticObjectMethod (android.activityClass,
- android.createHTTPStream,
+ stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
+ JuceAppActivity.createHTTPStream,
javaString (address).get(),
(jboolean) isPost,
postDataArray,
@@ -290314,8 +290316,8 @@ public:
{
LocalRef headersString ((jstring) env->CallObjectMethod (responseHeaderBuffer.get(),
- android.stringBufferToString));
- headerLines.addLines (juceString (headersString));
+ StringBuffer.toString));
+ headerLines.addLines (juceString (env, headersString));
}
if (responseHeaders != 0)
@@ -290336,13 +290338,13 @@ public:
~WebInputStream()
{
if (stream != 0)
- stream.callVoidMethod (android.httpStreamRelease);
+ stream.callVoidMethod (HTTPStream.release);
}
- bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (android.isExhausted); }
- int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (android.getTotalLength) : 0; }
- int64 getPosition() { return stream != nullptr ? stream.callLongMethod (android.getPosition) : 0; }
- bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (android.setPosition, (jlong) wantedPos); }
+ bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); }
+ int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; }
+ int64 getPosition() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; }
+ bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (HTTPStream.setPosition, (jlong) wantedPos); }
int read (void* buffer, int bytesToRead)
{
@@ -290353,7 +290355,7 @@ public:
jbyteArray javaArray = env->NewByteArray (bytesToRead);
- int numBytes = stream.callIntMethod (android.httpStreamRead, javaArray, (jint) bytesToRead);
+ int numBytes = stream.callIntMethod (HTTPStream.read, javaArray, (jint) bytesToRead);
if (numBytes > 0)
env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast (buffer));
@@ -290403,7 +290405,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend
bool MessageManager::postMessageToSystemQueue (Message* message)
{
message->incReferenceCount();
- getEnv()->CallVoidMethod (android.activity, android.postMessage, (jlong) (pointer_sized_uint) message);
+ getEnv()->CallVoidMethod (android.activity, JuceAppActivity.postMessage, (jlong) (pointer_sized_uint) message);
return true;
}
@@ -290467,7 +290469,7 @@ public:
void messageCallback()
{
- android.activity.callVoidMethod (android.finish);
+ android.activity.callVoidMethod (JuceAppActivity.finish);
}
};
@@ -290487,6 +290489,13 @@ void MessageManager::stopDispatchLoop()
// compiled on its own).
#if JUCE_INCLUDED_FILE
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \
+ STATICMETHOD (createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
+
+DECLARE_JNI_CLASS (TypefaceClass, "android/graphics/Typeface");
+#undef JNI_CLASS_MEMBERS
+
StringArray Font::findAllTypefaceNames()
{
StringArray results;
@@ -290525,21 +290534,21 @@ public:
File fontFile (File ("/system/fonts").getChildFile (name).withFileExtension (".ttf"));
if (fontFile.exists())
- typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.createFromFile,
+ typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile,
javaString (fontFile.getFullPathName()).get()));
else
- typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.create,
+ typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create,
javaString (getName()).get(), flags));
- rect = GlobalRef (env->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0));
+ rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
paint = GlobalRef (android.createPaint (Graphics::highResamplingQuality));
- const LocalRef ignored (paint.callObjectMethod (android.setTypeface, typeface.get()));
+ const LocalRef ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get()));
const float standardSize = 256.0f;
- paint.callVoidMethod (android.setTextSize, standardSize);
- ascent = std::abs (paint.callFloatMethod (android.ascent)) / standardSize;
- descent = paint.callFloatMethod (android.descent) / standardSize;
+ paint.callVoidMethod (Paint.setTextSize, standardSize);
+ ascent = std::abs (paint.callFloatMethod (Paint.ascent)) / standardSize;
+ descent = paint.callFloatMethod (Paint.descent) / standardSize;
const float height = ascent + descent;
unitsToHeightScaleFactor = 1.0f / 256.0f;//(height * standardSize);
@@ -290554,7 +290563,7 @@ public:
const int numChars = text.length();
jfloatArray widths = env->NewFloatArray (numChars);
- const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths);
+ const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
HeapBlock localWidths (numDone);
env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
@@ -290573,7 +290582,7 @@ public:
const int numChars = text.length();
jfloatArray widths = env->NewFloatArray (numChars);
- const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths);
+ const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
HeapBlock localWidths (numDone);
env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
@@ -290602,14 +290611,14 @@ public:
JNIEnv* env = getEnv();
jobject matrix = android.createMatrix (env, AffineTransform::scale (unitsToHeightScaleFactor, unitsToHeightScaleFactor).followedBy (t));
- jintArray maskData = (jintArray) android.activity.callObjectMethod (android.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
+ jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
env->DeleteLocalRef (matrix);
- const int left = env->GetIntField (rect.get(), android.rectLeft);
- const int top = env->GetIntField (rect.get(), android.rectTop);
- const int right = env->GetIntField (rect.get(), android.rectRight);
- const int bottom = env->GetIntField (rect.get(), android.rectBottom);
+ const int left = env->GetIntField (rect.get(), RectClass.left);
+ const int top = env->GetIntField (rect.get(), RectClass.top);
+ const int right = env->GetIntField (rect.get(), RectClass.right);
+ const int bottom = env->GetIntField (rect.get(), RectClass.bottom);
const Rectangle bounds (left, top, right - left, bottom - top);
@@ -290663,6 +290672,96 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
#if USE_ANDROID_CANVAS
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Landroid/graphics/Bitmap;)V") \
+ METHOD (drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \
+ METHOD (translate, "translate", "(FF)V") \
+ METHOD (clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \
+ METHOD (clipRect, "clipRect", "(FFFF)Z") \
+ METHOD (clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \
+ METHOD (concat, "concat", "(Landroid/graphics/Matrix;)V") \
+ METHOD (drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \
+ METHOD (drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \
+ METHOD (drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
+ METHOD (drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \
+ METHOD (drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \
+ METHOD (drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \
+ METHOD (getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \
+ METHOD (getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \
+ METHOD (getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \
+ METHOD (save, "save", "()I") \
+ METHOD (restore, "restore", "()V") \
+ METHOD (saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I")
+
+DECLARE_JNI_CLASS (Canvas, "android/graphics/Canvas");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V") \
+ METHOD (moveTo, "moveTo", "(FF)V") \
+ METHOD (lineTo, "lineTo", "(FF)V") \
+ METHOD (quadTo, "quadTo", "(FFFF)V") \
+ METHOD (cubicTo, "cubicTo", "(FFFFFF)V") \
+ METHOD (closePath, "close", "()V") \
+ METHOD (computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \
+
+DECLARE_JNI_CLASS (PathClass, "android/graphics/Path");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V"); \
+ METHOD (regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \
+
+DECLARE_JNI_CLASS (RegionClass, "android/graphics/Region");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \
+ METHOD (bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \
+ METHOD (getPixels, "getPixels", "([IIIIIII)V") \
+ METHOD (setPixels, "setPixels", "([IIIIIII)V") \
+ METHOD (recycle, "recycle", "()V") \
+
+DECLARE_JNI_CLASS (BitmapClass, "android/graphics/Bitmap");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICFIELD (ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \
+ STATICFIELD (ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \
+
+DECLARE_JNI_CLASS (BitmapConfig, "android/graphics/Bitmap$Config");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V")
+
+DECLARE_JNI_CLASS (BitmapShader, "android/graphics/BitmapShader");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V")
+
+DECLARE_JNI_CLASS (ShaderClass, "android/graphics/Shader");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICFIELD (CLAMP, "CLAMP", "Landroid/graphics/Shader$TileMode;")
+
+DECLARE_JNI_CLASS (ShaderTileMode, "android/graphics/Shader$TileMode");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \
+
+DECLARE_JNI_CLASS (LinearGradientClass, "android/graphics/LinearGradient");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \
+
+DECLARE_JNI_CLASS (RadialGradientClass, "android/graphics/RadialGradient");
+#undef JNI_CLASS_MEMBERS
+
class AndroidImage : public Image::SharedImage
{
public:
@@ -290682,7 +290781,7 @@ public:
~AndroidImage()
{
if (bitmap != 0)
- bitmap.callVoidMethod (android.recycle);
+ bitmap.callVoidMethod (BitmapClass.recycle);
}
Image::ImageType getType() const { return Image::NativeImage; }
@@ -290699,8 +290798,8 @@ public:
SharedImage* clone()
{
JNIEnv* env = getEnv();
- jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, android.ARGB_8888);
- GlobalRef newCopy (bitmap.callObjectMethod (android.bitmapCopy, mode, true));
+ jobject mode = env->GetStaticObjectField (BitmapConfig, BitmapConfig.ARGB_8888);
+ GlobalRef newCopy (bitmap.callObjectMethod (BitmapClass.bitmapCopy, mode, true));
env->DeleteLocalRef (mode);
return new AndroidImage (width, height, newCopy);
@@ -290709,8 +290808,9 @@ public:
static jobject createBitmap (int width, int height, bool asSingleChannel)
{
JNIEnv* env = getEnv();
- jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, asSingleChannel ? android.ALPHA_8 : android.ARGB_8888);
- jobject result = env->CallStaticObjectMethod (android.bitmapClass, android.createBitmap, width, height, mode);
+ jobject mode = env->GetStaticObjectField (BitmapConfig, asSingleChannel ? BitmapConfig.ALPHA_8
+ : BitmapConfig.ARGB_8888);
+ jobject result = env->CallStaticObjectMethod (BitmapClass, BitmapClass.createBitmap, width, height, mode);
env->DeleteLocalRef (mode);
return result;
}
@@ -290730,7 +290830,7 @@ private:
intArray = env->NewIntArray (bitmapData.width * bitmapData.height);
if (mode != Image::BitmapData::writeOnly)
- owner_.bitmap.callVoidMethod (android.getPixels, intArray, 0, bitmapData.width, x_, y_,
+ owner_.bitmap.callVoidMethod (BitmapClass.getPixels, intArray, 0, bitmapData.width, x_, y_,
bitmapData.width, bitmapData.height);
bitmapData.data = (uint8*) env->GetIntArrayElements (intArray, 0);
@@ -290765,7 +290865,7 @@ private:
env->ReleaseIntArrayElements (intArray, (jint*) bitmapData.data, 0);
if (mode != Image::BitmapData::readOnly)
- owner.bitmap.callVoidMethod (android.setPixels, intArray, 0, bitmapData.width, x, y,
+ owner.bitmap.callVoidMethod (BitmapClass.setPixels, intArray, 0, bitmapData.width, x, y,
bitmapData.width, bitmapData.height);
env->DeleteLocalRef (intArray);
@@ -290819,12 +290919,12 @@ public:
void setOrigin (int x, int y)
{
- getCanvas().callVoidMethod (android.translate, (float) x, (float) y);
+ getCanvas().callVoidMethod (Canvas.translate, (float) x, (float) y);
}
void addTransform (const AffineTransform& transform)
{
- getCanvas().callVoidMethod (android.concat, createMatrixRef (getEnv(), transform).get());
+ getCanvas().callVoidMethod (Canvas.concat, createMatrixRef (getEnv(), transform).get());
}
float getScaleFactor()
@@ -290834,7 +290934,7 @@ public:
bool clipToRectangle (const Rectangle& r)
{
- return getCanvas().callBooleanMethod (android.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
+ return getCanvas().callBooleanMethod (Canvas.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
}
bool clipToRectangleList (const RectangleList& clipRegion)
@@ -290850,13 +290950,13 @@ public:
void excludeClipRectangle (const Rectangle& r)
{
- android.activity.callVoidMethod (android.excludeClipRegion, getCanvas().get(),
+ android.activity.callVoidMethod (JuceAppActivity.excludeClipRegion, getCanvas().get(),
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
}
void clipToPath (const Path& path, const AffineTransform& transform)
{
- (void) getCanvas().callBooleanMethod (android.clipPath, createPath (getEnv(), path, transform).get());
+ (void) getCanvas().callBooleanMethod (Canvas.clipPath, createPath (getEnv(), path, transform).get());
}
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
@@ -290873,14 +290973,14 @@ public:
Rectangle bounds (getClipBounds());
jobject temporaryLayerBitmap = AndroidImage::createBitmap (bounds.getWidth(), bounds.getHeight(), false);
- jobject temporaryCanvas = env->NewObject (android.canvasClass, android.canvasBitmapConstructor, temporaryLayerBitmap);
+ jobject temporaryCanvas = env->NewObject (Canvas, Canvas.constructor, temporaryLayerBitmap);
setFill (Colours::red);
- env->CallVoidMethod (temporaryCanvas, android.drawRect,
+ env->CallVoidMethod (temporaryCanvas, Canvas.drawRect,
(jfloat) 20, (jfloat) 20, (jfloat) 300, (jfloat) 200,
getCurrentPaint());
- env->CallVoidMethod (temporaryCanvas, android.translate,
+ env->CallVoidMethod (temporaryCanvas, Canvas.translate,
(jfloat) -bounds.getX(), (jfloat) -bounds.getY());
Image maskImage (Image::SingleChannel, bounds.getWidth(), bounds.getHeight(), true);
@@ -290905,12 +291005,12 @@ public:
const Rectangle getClipBounds() const
{
JNIEnv* env = getEnv();
- jobject rect = getCanvas().callObjectMethod (android.getClipBounds2);
+ jobject rect = getCanvas().callObjectMethod (Canvas.getClipBounds2);
- const int left = env->GetIntField (rect, android.rectLeft);
- const int top = env->GetIntField (rect, android.rectTop);
- const int right = env->GetIntField (rect, android.rectRight);
- const int bottom = env->GetIntField (rect, android.rectBottom);
+ const int left = env->GetIntField (rect, RectClass.left);
+ const int top = env->GetIntField (rect, RectClass.top);
+ const int right = env->GetIntField (rect, RectClass.right);
+ const int bottom = env->GetIntField (rect, RectClass.bottom);
env->DeleteLocalRef (rect);
return Rectangle (left, top, right - left, bottom - top);
@@ -290918,8 +291018,8 @@ public:
bool isClipEmpty() const
{
- LocalRef tempRect (getEnv()->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0));
- return ! getCanvas().callBooleanMethod (android.getClipBounds, tempRect.get());
+ LocalRef tempRect (getEnv()->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
+ return ! getCanvas().callBooleanMethod (Canvas.getClipBounds, tempRect.get());
}
void setFill (const FillType& fillType)
@@ -290939,14 +291039,14 @@ public:
void fillRect (const Rectangle& r, bool replaceExistingContents)
{
- getCanvas().callVoidMethod (android.drawRect,
+ getCanvas().callVoidMethod (Canvas.drawRect,
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(),
getCurrentPaint());
}
void fillPath (const Path& path, const AffineTransform& transform)
{
- getCanvas().callVoidMethod (android.drawPath, createPath (getEnv(), path, transform).get(),
+ getCanvas().callVoidMethod (Canvas.drawPath, createPath (getEnv(), path, transform).get(),
getCurrentPaint());
}
@@ -290957,7 +291057,7 @@ public:
if (androidImage != 0)
{
JNIEnv* env = getEnv();
- getCanvas().callVoidMethod (android.drawBitmap, androidImage->bitmap.get(),
+ getCanvas().callVoidMethod (Canvas.drawBitmap, androidImage->bitmap.get(),
createMatrixRef (env, transform).get(), getImagePaint());
}
else
@@ -290992,7 +291092,7 @@ public:
env->ReleaseIntArrayElements (imageData, dest, 0);
- getCanvas().callVoidMethod (android.drawMemoryBitmap, imageData, 0, bm.width,
+ getCanvas().callVoidMethod (Canvas.drawMemoryBitmap, imageData, 0, bm.width,
transform.getTranslationX(), transform.getTranslationY(),
bm.width, bm.height, true, getImagePaint());
env->DeleteLocalRef (imageData);
@@ -291010,18 +291110,18 @@ public:
void drawLine (const Line & line)
{
- getCanvas().callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(),
+ getCanvas().callVoidMethod (Canvas.drawLine, line.getStartX(), line.getStartY(),
line.getEndX(), line.getEndY(), getCurrentPaint());
}
void drawVerticalLine (int x, float top, float bottom)
{
- getCanvas().callVoidMethod (android.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint());
+ getCanvas().callVoidMethod (Canvas.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint());
}
void drawHorizontalLine (int y, float left, float right)
{
- getCanvas().callVoidMethod (android.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint());
+ getCanvas().callVoidMethod (Canvas.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint());
}
void setFont (const Font& newFont)
@@ -291042,7 +291142,7 @@ public:
{
if (transform.isOnlyTranslation())
{
- getCanvas().callVoidMethod (android.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(),
+ getCanvas().callVoidMethod (Canvas.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(),
transform.getTranslationX(), transform.getTranslationY(),
currentState->getPaintForTypeface());
}
@@ -291057,7 +291157,7 @@ public:
void saveState()
{
- (void) getCanvas().callIntMethod (android.save);
+ (void) getCanvas().callIntMethod (Canvas.save);
stateStack.add (new SavedState (*currentState));
}
@@ -291077,14 +291177,14 @@ public:
jassertfalse; // trying to pop with an empty stack!
}
- getCanvas().callVoidMethod (android.restore);
+ getCanvas().callVoidMethod (Canvas.restore);
}
void beginTransparencyLayer (float opacity)
{
Rectangle clip (getClipBounds());
- (void) getCanvas().callIntMethod (android.saveLayerAlpha,
+ (void) getCanvas().callIntMethod (Canvas.saveLayerAlpha,
(float) clip.getX(),
(float) clip.getY(),
(float) clip.getRight(),
@@ -291148,8 +291248,8 @@ public:
if (fillType.isColour())
{
- env->DeleteLocalRef (paint.callObjectMethod (android.setShader, (jobject) 0));
- paint.callVoidMethod (android.setColor, colourToInt (fillType.colour));
+ env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, (jobject) 0));
+ paint.callVoidMethod (Paint.setColor, colourToInt (fillType.colour));
}
else if (fillType.isGradient())
{
@@ -291175,13 +291275,13 @@ public:
env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData());
}
- jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode);
+ jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP);
jobject shader;
if (fillType.gradient->isRadial)
{
- shader = env->NewObject (android.radialGradientClass,
- android.radialGradientConstructor,
+ shader = env->NewObject (RadialGradientClass,
+ RadialGradientClass.constructor,
p1.getX(), p1.getY(),
p1.getDistanceFrom (p2),
coloursArray, positionsArray,
@@ -291189,8 +291289,8 @@ public:
}
else
{
- shader = env->NewObject (android.linearGradientClass,
- android.linearGradientConstructor,
+ shader = env->NewObject (LinearGradientClass,
+ LinearGradientClass.constructor,
p1.getX(), p1.getY(), p2.getX(), p2.getY(),
coloursArray, positionsArray,
tileMode);
@@ -291200,8 +291300,8 @@ public:
env->DeleteLocalRef (coloursArray);
env->DeleteLocalRef (positionsArray);
- env->CallVoidMethod (shader, android.setLocalMatrix, createMatrixRef (env, fillType.transform).get());
- env->DeleteLocalRef (paint.callObjectMethod (android.setShader, shader));
+ env->CallVoidMethod (shader, ShaderClass.setLocalMatrix, createMatrixRef (env, fillType.transform).get());
+ env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, shader));
env->DeleteLocalRef (shader);
}
@@ -291226,17 +291326,17 @@ public:
if (atf != 0)
{
- paint.callObjectMethod (android.setTypeface, atf->typeface.get());
- paint.callVoidMethod (android.setTextSize, font.getHeight());
+ paint.callObjectMethod (Paint.setTypeface, atf->typeface.get());
+ paint.callVoidMethod (Paint.setTextSize, font.getHeight());
const float hScale = font.getHorizontalScale();
if (hScale < 0.99f || hScale > 1.01f)
- paint.callVoidMethod (android.setTextScaleX, hScale);
+ paint.callVoidMethod (Paint.setTextScaleX, hScale);
}
fillNeedsUpdate = true;
- paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha());
+ paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha());
}
return p;
@@ -291245,7 +291345,7 @@ public:
jobject getImagePaint()
{
jobject p = getPaint();
- paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha());
+ paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha());
fillNeedsUpdate = true;
return p;
}
@@ -291258,27 +291358,27 @@ public:
{
JNIEnv* env = getEnv();
- jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode);
- jobject shader = env->NewObject (android.bitmapShaderClass, android.bitmapShaderConstructor,
+ jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP);
+ jobject shader = env->NewObject (BitmapShader, BitmapShader.constructor,
temporaryLayerBitmap.get(), tileMode, tileMode);
env->DeleteLocalRef (tileMode);
jobject compositingPaint = android.createPaint (quality);
- env->CallObjectMethod (compositingPaint, android.setShader, shader);
+ env->CallObjectMethod (compositingPaint, Paint.setShader, shader);
env->DeleteLocalRef (shader);
LocalRef maskBitmap (createAlphaBitmap (env, maskImage));
maskImage = Image::null;
- env->CallVoidMethod (previousCanvas, android.drawBitmapAt,
+ env->CallVoidMethod (previousCanvas, Canvas.drawBitmapAt,
maskBitmap.get(), (jfloat) maskLayerX, (jfloat) maskLayerY, compositingPaint);
env->DeleteLocalRef (compositingPaint);
canvas = GlobalRef (previousCanvas);
- env->CallVoidMethod (temporaryLayerBitmap.get(), android.recycle);
- env->CallVoidMethod (maskBitmap.get(), android.recycle);
+ env->CallVoidMethod (temporaryLayerBitmap.get(), BitmapClass.recycle);
+ env->CallVoidMethod (maskBitmap.get(), BitmapClass.recycle);
temporaryLayerBitmap.clear();
}
@@ -291321,7 +291421,7 @@ public:
}
env->ReleaseIntArrayElements (intArray, (jint*) dest, 0);
- env->CallVoidMethod (bitmap, android.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height);
+ env->CallVoidMethod (bitmap, BitmapClass.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height);
env->DeleteLocalRef (intArray);
return bitmap;
}
@@ -291348,9 +291448,9 @@ private:
jobject getCurrentPaint() const { return currentState->getPaint(); }
jobject getImagePaint() const { return currentState->getImagePaint(); }
- static const LocalRef createPath (JNIEnv* env, const Path& path)
+ static LocalRef createPath (JNIEnv* env, const Path& path)
{
- jobject p = env->NewObject (android.pathClass, android.pathClassConstructor);
+ jobject p = env->NewObject (PathClass, PathClass.constructor);
Path::Iterator i (path);
@@ -291358,11 +291458,11 @@ private:
{
switch (i.elementType)
{
- case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, android.moveTo, i.x1, i.y1); break;
- case Path::Iterator::lineTo: env->CallVoidMethod (p, android.lineTo, i.x1, i.y1); break;
- case Path::Iterator::quadraticTo: env->CallVoidMethod (p, android.quadTo, i.x1, i.y1, i.x2, i.y2); break;
- case Path::Iterator::cubicTo: env->CallVoidMethod (p, android.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break;
- case Path::Iterator::closePath: env->CallVoidMethod (p, android.closePath); break;
+ case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, PathClass.moveTo, i.x1, i.y1); break;
+ case Path::Iterator::lineTo: env->CallVoidMethod (p, PathClass.lineTo, i.x1, i.y1); break;
+ case Path::Iterator::quadraticTo: env->CallVoidMethod (p, PathClass.quadTo, i.x1, i.y1, i.x2, i.y2); break;
+ case Path::Iterator::cubicTo: env->CallVoidMethod (p, PathClass.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break;
+ case Path::Iterator::closePath: env->CallVoidMethod (p, PathClass.closePath); break;
default: jassertfalse; break;
}
}
@@ -291370,7 +291470,7 @@ private:
return LocalRef (p);
}
- static const LocalRef createPath (JNIEnv* env, const Path& path, const AffineTransform& transform)
+ static LocalRef createPath (JNIEnv* env, const Path& path, const AffineTransform& transform)
{
if (transform.isIdentity())
return createPath (env, path);
@@ -291380,25 +291480,25 @@ private:
return createPath (env, tempPath);
}
- static const LocalRef createMatrixRef (JNIEnv* env, const AffineTransform& t)
+ static LocalRef createMatrixRef (JNIEnv* env, const AffineTransform& t)
{
- return LocalRef (android.createMatrix (*env, t));
+ return LocalRef (android.createMatrix (env, t));
}
- static const LocalRef createRect (JNIEnv* env, const Rectangle& r)
+ static LocalRef createRect (JNIEnv* env, const Rectangle& r)
{
- return LocalRef (env->NewObject (android.rectClass, android.rectConstructor,
+ return LocalRef (env->NewObject (RectClass, RectClass.constructor,
r.getX(), r.getY(), r.getRight(), r.getBottom()));
}
- static const LocalRef createRegion (JNIEnv* env, const RectangleList& list)
+ static LocalRef createRegion (JNIEnv* env, const RectangleList& list)
{
- jobject region = env->NewObject (android.regionClass, android.regionConstructor);
+ jobject region = env->NewObject (RegionClass, RegionClass.constructor);
const int numRects = list.getNumRectangles();
for (int i = 0; i < numRects; ++i)
- env->CallBooleanMethod (region, android.regionUnion, createRect (env, list.getRectangle(i)).get());
+ env->CallBooleanMethod (region, RegionClass.regionUnion, createRect (env, list.getRectangle(i)).get());
return LocalRef (region);
}
@@ -291423,7 +291523,7 @@ private:
LowLevelGraphicsContext* AndroidImage::createLowLevelContext()
{
- jobject canvas = getEnv()->NewObject (android.canvasClass, android.canvasBitmapConstructor, bitmap.get());
+ jobject canvas = getEnv()->NewObject (Canvas, Canvas.constructor, bitmap.get());
return new AndroidLowLevelGraphicsContext (canvas);
}
#endif
@@ -291438,13 +291538,39 @@ LowLevelGraphicsContext* AndroidImage::createLowLevelContext()
// compiled on its own).
#if JUCE_INCLUDED_FILE
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (drawBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
+ METHOD (getClipBounds, "getClipBounds", "()Landroid/graphics/Rect;")
+
+DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \
+ METHOD (layout, "layout", "(IIII)V") \
+ METHOD (getLeft, "getLeft", "()I") \
+ METHOD (getTop, "getTop", "()I") \
+ METHOD (getWidth, "getWidth", "()I") \
+ METHOD (getHeight, "getHeight", "()I") \
+ METHOD (getLocationOnScreen, "getLocationOnScreen", "([I)V") \
+ METHOD (bringToFront, "bringToFront", "()V") \
+ METHOD (requestFocus, "requestFocus", "()Z") \
+ METHOD (setVisible, "setVisible", "(Z)V") \
+ METHOD (isVisible, "isVisible", "()Z") \
+ METHOD (hasFocus, "hasFocus", "()Z") \
+ METHOD (invalidate, "invalidate", "(IIII)V") \
+ METHOD (containsPoint, "containsPoint", "(II)Z") \
+
+DECLARE_JNI_CLASS (ComponentPeerView, "com/juce/ComponentPeerView");
+#undef JNI_CLASS_MEMBERS
+
class AndroidComponentPeer : public ComponentPeer
{
public:
AndroidComponentPeer (Component* const component, const int windowStyleFlags)
: ComponentPeer (component, windowStyleFlags),
- view (android.activity.callObjectMethod (android.createNewView, component->isOpaque())),
+ view (android.activity.callObjectMethod (JuceAppActivity.createNewView, component->isOpaque())),
usingAndroidGraphics (false),
fullScreen (false),
sizeAllocated (0)
@@ -291457,7 +291583,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- android.activity.callVoidMethod (android.deleteView, view.get());
+ android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get());
}
else
{
@@ -291472,7 +291598,7 @@ public:
void messageCallback()
{
- android.activity.callVoidMethod (android.deleteView, view.get());
+ android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get());
}
private:
@@ -291494,7 +291620,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- view.callVoidMethod (android.setVisible, shouldBeVisible);
+ view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
}
else
{
@@ -291509,7 +291635,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.setVisible, shouldBeVisible);
+ view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
}
private:
@@ -291523,7 +291649,7 @@ public:
void setTitle (const String& title)
{
- view.callVoidMethod (android.setViewName, javaString (title).get());
+ view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get());
}
void setPosition (int x, int y)
@@ -291546,7 +291672,7 @@ public:
w = jmax (0, w);
h = jmax (0, h);
- view.callVoidMethod (android.layout, x, y, x + w, y + h);
+ view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h);
}
else
{
@@ -291561,7 +291687,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.layout, x, y, x + w, y + h);
+ view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h);
}
private:
@@ -291575,16 +291701,16 @@ public:
const Rectangle getBounds() const
{
- return Rectangle (view.callIntMethod (android.getLeft),
- view.callIntMethod (android.getTop),
- view.callIntMethod (android.getWidth),
- view.callIntMethod (android.getHeight));
+ return Rectangle (view.callIntMethod (ComponentPeerView.getLeft),
+ view.callIntMethod (ComponentPeerView.getTop),
+ view.callIntMethod (ComponentPeerView.getWidth),
+ view.callIntMethod (ComponentPeerView.getHeight));
}
const Point getScreenPosition() const
{
- return Point (view.callIntMethod (android.getLeft),
- view.callIntMethod (android.getTop));
+ return Point (view.callIntMethod (ComponentPeerView.getLeft),
+ view.callIntMethod (ComponentPeerView.getTop));
}
const Point localToGlobal (const Point& relativePosition)
@@ -291636,7 +291762,8 @@ public:
{
return isPositiveAndBelow (position.getX(), component->getWidth())
&& isPositiveAndBelow (position.getY(), component->getHeight())
- && ((! trueIfInAChildWindow) || view.callBooleanMethod (android.containsPoint, position.getX(), position.getY()));
+ && ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint,
+ position.getX(), position.getY()));
}
const BorderSize getFrameSize() const
@@ -291653,7 +291780,7 @@ public:
void toFront (bool makeActive)
{
- view.callVoidMethod (android.bringToFront);
+ view.callVoidMethod (ComponentPeerView.bringToFront);
if (makeActive)
grabFocus();
@@ -291690,12 +291817,12 @@ public:
bool isFocused() const
{
- return view.callBooleanMethod (android.hasFocus);
+ return view.callBooleanMethod (ComponentPeerView.hasFocus);
}
void grabFocus()
{
- view.callBooleanMethod (android.requestFocus);
+ view.callBooleanMethod (ComponentPeerView.requestFocus);
}
void handleFocusChangeCallback (bool hasFocus)
@@ -291713,20 +291840,20 @@ public:
void handlePaintCallback (JNIEnv* env, jobject canvas)
{
-#if USE_ANDROID_CANVAS
+ #if USE_ANDROID_CANVAS
if (usingAndroidGraphics)
{
AndroidLowLevelGraphicsContext g (canvas);
handlePaint (g);
}
else
-#endif
+ #endif
{
- jobject rect = env->CallObjectMethod (canvas, android.getClipBounds2);
- const int left = env->GetIntField (rect, android.rectLeft);
- const int top = env->GetIntField (rect, android.rectTop);
- const int right = env->GetIntField (rect, android.rectRight);
- const int bottom = env->GetIntField (rect, android.rectBottom);
+ jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds);
+ const int left = env->GetIntField (rect, RectClass.left);
+ const int top = env->GetIntField (rect, RectClass.top);
+ const int right = env->GetIntField (rect, RectClass.right);
+ const int bottom = env->GetIntField (rect, RectClass.bottom);
env->DeleteLocalRef (rect);
const Rectangle clip (left, top, right - left, bottom - top);
@@ -291756,7 +291883,7 @@ public:
env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0);
- env->CallVoidMethod (canvas, android.drawMemoryBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),
+ env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),
(jfloat) clip.getX(), (jfloat) clip.getY(),
clip.getWidth(), clip.getHeight(), true, (jobject) 0);
}
@@ -291767,7 +291894,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
+ view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
}
else
{
@@ -291782,7 +291909,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
+ view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
}
private:
@@ -291914,25 +292041,16 @@ Point AndroidComponentPeer::lastMousePos;
JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \
{ \
AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \
- if (peer != 0) \
+ if (peer != nullptr) \
peer->juceMethodInvocation; \
}
-JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas),
- handlePaintCallback (env, canvas))
-
-JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseDownCallback ((float) x, (float) y, (int64) time))
-JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseDragCallback ((float) x, (float) y, (int64) time))
-JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseUpCallback ((float) x, (float) y, (int64) time))
-
-JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view),
- handleMovedOrResized())
-
-JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus),
- handleFocusChangeCallback (hasFocus))
+JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), handlePaintCallback (env, canvas))
+JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDownCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDragCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseUpCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view), handleMovedOrResized())
+JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus), handleFocusChangeCallback (hasFocus))
ComponentPeer* Component::createNewPeer (int styleFlags, void*)
{
@@ -291993,7 +292111,7 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIcon
const String& title, const String& message,
Component* associatedComponent)
{
- android.activity.callVoidMethod (android.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0);
+ android.activity.callVoidMethod (JuceAppActivity.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0);
}
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType,
@@ -292003,7 +292121,7 @@ bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType
{
jassert (callback != 0); // on android, all alerts must be non-modal!!
- android.activity.callVoidMethod (android.showOkCancelBox, javaString (title).get(), javaString (message).get(),
+ android.activity.callVoidMethod (JuceAppActivity.showOkCancelBox, javaString (title).get(), javaString (message).get(),
(jlong) (pointer_sized_int) callback);
return false;
}
@@ -292015,7 +292133,7 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy
{
jassert (callback != 0); // on android, all alerts must be non-modal!!
- android.activity.callVoidMethod (android.showYesNoCancelBox, javaString (title).get(), javaString (message).get(),
+ android.activity.callVoidMethod (JuceAppActivity.showYesNoCancelBox, javaString (title).get(), javaString (message).get(),
(jlong) (pointer_sized_int) callback);
return 0;
}
@@ -292373,6 +292491,30 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback)
// compiled on its own).
#if JUCE_INCLUDED_FILE
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
+ STATICMETHOD (getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \
+ METHOD (constructor, "", "(IIIIII)V") \
+ METHOD (play, "play", "()V") \
+ METHOD (stop, "stop", "()V") \
+ METHOD (release, "release", "()V") \
+ METHOD (flush, "flush", "()V") \
+ METHOD (write, "write", "([SII)I") \
+
+DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
+ METHOD (constructor, "", "(IIIII)V"); \
+ METHOD (startRecording, "startRecording", "()V"); \
+ METHOD (stop, "stop", "()V"); \
+ METHOD (read, "read", "([SII)I"); \
+ METHOD (release, "release", "()V"); \
+
+DECLARE_JNI_CLASS (AudioRecord, "android/media/AudioRecord");
+#undef JNI_CLASS_MEMBERS
+
#define CHANNEL_OUT_STEREO ((jint) 12)
#define CHANNEL_IN_STEREO ((jint) 12)
#define CHANNEL_IN_MONO ((jint) 16)
@@ -292397,14 +292539,14 @@ public:
inputChannelBuffer (1, 1)
{
JNIEnv* env = getEnv();
- sampleRate = env->CallStaticIntMethod (android.audioTrackClass, android.getNativeOutputSampleRate, MODE_STREAM);
+ sampleRate = env->CallStaticIntMethod (AudioTrack, AudioTrack.getNativeOutputSampleRate, MODE_STREAM);
- const jint outMinBuffer = env->CallStaticIntMethod (android.audioTrackClass, android.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT);
+ const jint outMinBuffer = env->CallStaticIntMethod (AudioTrack, AudioTrack.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT);
- jint inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT);
+ jint inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT);
if (inMinBuffer <= 0)
{
- inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT);
+ inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT);
if (inMinBuffer > 0)
numDeviceInputChannelsAvailable = 1;
@@ -292490,7 +292632,7 @@ public:
if (numClientOutputChannels > 0)
{
numDeviceOutputChannels = 2;
- outputDevice = GlobalRef (env->NewObject (android.audioTrackClass, android.audioTrackConstructor,
+ outputDevice = GlobalRef (env->NewObject (AudioTrack, AudioTrack.constructor,
STREAM_MUSIC, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT,
(jint) (actualBufferSize * numDeviceOutputChannels * sizeof (float)), MODE_STREAM));
isRunning = true;
@@ -292499,7 +292641,7 @@ public:
if (numClientInputChannels > 0 && numDeviceInputChannelsAvailable > 0)
{
numDeviceInputChannels = jmin (numClientInputChannels, numDeviceInputChannelsAvailable);
- inputDevice = GlobalRef (env->NewObject (android.audioRecordClass, android.audioRecordConstructor,
+ inputDevice = GlobalRef (env->NewObject (AudioRecord, AudioRecord.constructor,
0 /* (default audio source) */, sampleRate,
numDeviceInputChannelsAvailable > 1 ? CHANNEL_IN_STEREO : CHANNEL_IN_MONO,
ENCODING_PCM_16BIT,
@@ -292510,10 +292652,10 @@ public:
if (isRunning)
{
if (outputDevice != nullptr)
- env->CallVoidMethod (outputDevice, android.audioTrackPlay);
+ env->CallVoidMethod (outputDevice, AudioTrack.play);
if (inputDevice != nullptr)
- env->CallVoidMethod (inputDevice, android.startRecording);
+ env->CallVoidMethod (inputDevice, AudioRecord.startRecording);
startThread (8);
}
@@ -292584,7 +292726,7 @@ public:
{
if (inputDevice != nullptr)
{
- jint numRead = env->CallIntMethod (inputDevice, android.audioRecordRead, audioBuffer, 0, actualBufferSize * numDeviceInputChannels);
+ jint numRead = env->CallIntMethod (inputDevice, AudioRecord.read, audioBuffer, 0, actualBufferSize * numDeviceInputChannels);
if (numRead < actualBufferSize * numDeviceInputChannels)
{
@@ -292636,7 +292778,7 @@ public:
}
env->ReleaseShortArrayElements (audioBuffer, dest, 0);
- jint numWritten = env->CallIntMethod (outputDevice, android.audioTrackWrite, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels);
+ jint numWritten = env->CallIntMethod (outputDevice, AudioTrack.write, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels);
if (numWritten < actualBufferSize * numDeviceOutputChannels)
{
@@ -292664,15 +292806,15 @@ private:
{
if (outputDevice != nullptr)
{
- outputDevice.callVoidMethod (android.audioTrackStop);
- outputDevice.callVoidMethod (android.audioTrackRelease);
+ outputDevice.callVoidMethod (AudioTrack.stop);
+ outputDevice.callVoidMethod (AudioTrack.release);
outputDevice.clear();
}
if (inputDevice != nullptr)
{
- inputDevice.callVoidMethod (android.stopRecording);
- inputDevice.callVoidMethod (android.audioRecordRelease);
+ inputDevice.callVoidMethod (AudioRecord.stop);
+ inputDevice.callVoidMethod (AudioRecord.release);
inputDevice.clear();
}
}
diff --git a/src/native/android/juce_android_Audio.cpp b/src/native/android/juce_android_Audio.cpp
index d7af4bf98a..c85534ded5 100644
--- a/src/native/android/juce_android_Audio.cpp
+++ b/src/native/android/juce_android_Audio.cpp
@@ -27,6 +27,32 @@
// compiled on its own).
#if JUCE_INCLUDED_FILE
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
+ STATICMETHOD (getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \
+ METHOD (constructor, "", "(IIIIII)V") \
+ METHOD (play, "play", "()V") \
+ METHOD (stop, "stop", "()V") \
+ METHOD (release, "release", "()V") \
+ METHOD (flush, "flush", "()V") \
+ METHOD (write, "write", "([SII)I") \
+
+DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
+ METHOD (constructor, "", "(IIIII)V"); \
+ METHOD (startRecording, "startRecording", "()V"); \
+ METHOD (stop, "stop", "()V"); \
+ METHOD (read, "read", "([SII)I"); \
+ METHOD (release, "release", "()V"); \
+
+DECLARE_JNI_CLASS (AudioRecord, "android/media/AudioRecord");
+#undef JNI_CLASS_MEMBERS
+
//==============================================================================
#define CHANNEL_OUT_STEREO ((jint) 12)
#define CHANNEL_IN_STEREO ((jint) 12)
@@ -53,14 +79,14 @@ public:
inputChannelBuffer (1, 1)
{
JNIEnv* env = getEnv();
- sampleRate = env->CallStaticIntMethod (android.audioTrackClass, android.getNativeOutputSampleRate, MODE_STREAM);
+ sampleRate = env->CallStaticIntMethod (AudioTrack, AudioTrack.getNativeOutputSampleRate, MODE_STREAM);
- const jint outMinBuffer = env->CallStaticIntMethod (android.audioTrackClass, android.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT);
+ const jint outMinBuffer = env->CallStaticIntMethod (AudioTrack, AudioTrack.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT);
- jint inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT);
+ jint inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT);
if (inMinBuffer <= 0)
{
- inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT);
+ inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT);
if (inMinBuffer > 0)
numDeviceInputChannelsAvailable = 1;
@@ -146,7 +172,7 @@ public:
if (numClientOutputChannels > 0)
{
numDeviceOutputChannels = 2;
- outputDevice = GlobalRef (env->NewObject (android.audioTrackClass, android.audioTrackConstructor,
+ outputDevice = GlobalRef (env->NewObject (AudioTrack, AudioTrack.constructor,
STREAM_MUSIC, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT,
(jint) (actualBufferSize * numDeviceOutputChannels * sizeof (float)), MODE_STREAM));
isRunning = true;
@@ -155,7 +181,7 @@ public:
if (numClientInputChannels > 0 && numDeviceInputChannelsAvailable > 0)
{
numDeviceInputChannels = jmin (numClientInputChannels, numDeviceInputChannelsAvailable);
- inputDevice = GlobalRef (env->NewObject (android.audioRecordClass, android.audioRecordConstructor,
+ inputDevice = GlobalRef (env->NewObject (AudioRecord, AudioRecord.constructor,
0 /* (default audio source) */, sampleRate,
numDeviceInputChannelsAvailable > 1 ? CHANNEL_IN_STEREO : CHANNEL_IN_MONO,
ENCODING_PCM_16BIT,
@@ -166,10 +192,10 @@ public:
if (isRunning)
{
if (outputDevice != nullptr)
- env->CallVoidMethod (outputDevice, android.audioTrackPlay);
+ env->CallVoidMethod (outputDevice, AudioTrack.play);
if (inputDevice != nullptr)
- env->CallVoidMethod (inputDevice, android.startRecording);
+ env->CallVoidMethod (inputDevice, AudioRecord.startRecording);
startThread (8);
}
@@ -240,7 +266,7 @@ public:
{
if (inputDevice != nullptr)
{
- jint numRead = env->CallIntMethod (inputDevice, android.audioRecordRead, audioBuffer, 0, actualBufferSize * numDeviceInputChannels);
+ jint numRead = env->CallIntMethod (inputDevice, AudioRecord.read, audioBuffer, 0, actualBufferSize * numDeviceInputChannels);
if (numRead < actualBufferSize * numDeviceInputChannels)
{
@@ -292,7 +318,7 @@ public:
}
env->ReleaseShortArrayElements (audioBuffer, dest, 0);
- jint numWritten = env->CallIntMethod (outputDevice, android.audioTrackWrite, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels);
+ jint numWritten = env->CallIntMethod (outputDevice, AudioTrack.write, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels);
if (numWritten < actualBufferSize * numDeviceOutputChannels)
{
@@ -320,15 +346,15 @@ private:
{
if (outputDevice != nullptr)
{
- outputDevice.callVoidMethod (android.audioTrackStop);
- outputDevice.callVoidMethod (android.audioTrackRelease);
+ outputDevice.callVoidMethod (AudioTrack.stop);
+ outputDevice.callVoidMethod (AudioTrack.release);
outputDevice.clear();
}
if (inputDevice != nullptr)
{
- inputDevice.callVoidMethod (android.stopRecording);
- inputDevice.callVoidMethod (android.audioRecordRelease);
+ inputDevice.callVoidMethod (AudioRecord.stop);
+ inputDevice.callVoidMethod (AudioRecord.release);
inputDevice.clear();
}
}
diff --git a/src/native/android/juce_android_Fonts.cpp b/src/native/android/juce_android_Fonts.cpp
index b1781a3c8b..459a7a3e9e 100644
--- a/src/native/android/juce_android_Fonts.cpp
+++ b/src/native/android/juce_android_Fonts.cpp
@@ -27,6 +27,14 @@
// compiled on its own).
#if JUCE_INCLUDED_FILE
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \
+ STATICMETHOD (createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
+
+DECLARE_JNI_CLASS (TypefaceClass, "android/graphics/Typeface");
+#undef JNI_CLASS_MEMBERS
+
//==============================================================================
StringArray Font::findAllTypefaceNames()
@@ -68,21 +76,21 @@ public:
File fontFile (File ("/system/fonts").getChildFile (name).withFileExtension (".ttf"));
if (fontFile.exists())
- typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.createFromFile,
+ typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile,
javaString (fontFile.getFullPathName()).get()));
else
- typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.create,
+ typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create,
javaString (getName()).get(), flags));
- rect = GlobalRef (env->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0));
+ rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
paint = GlobalRef (android.createPaint (Graphics::highResamplingQuality));
- const LocalRef ignored (paint.callObjectMethod (android.setTypeface, typeface.get()));
+ const LocalRef ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get()));
const float standardSize = 256.0f;
- paint.callVoidMethod (android.setTextSize, standardSize);
- ascent = std::abs (paint.callFloatMethod (android.ascent)) / standardSize;
- descent = paint.callFloatMethod (android.descent) / standardSize;
+ paint.callVoidMethod (Paint.setTextSize, standardSize);
+ ascent = std::abs (paint.callFloatMethod (Paint.ascent)) / standardSize;
+ descent = paint.callFloatMethod (Paint.descent) / standardSize;
const float height = ascent + descent;
unitsToHeightScaleFactor = 1.0f / 256.0f;//(height * standardSize);
@@ -97,7 +105,7 @@ public:
const int numChars = text.length();
jfloatArray widths = env->NewFloatArray (numChars);
- const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths);
+ const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
HeapBlock localWidths (numDone);
env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
@@ -116,7 +124,7 @@ public:
const int numChars = text.length();
jfloatArray widths = env->NewFloatArray (numChars);
- const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths);
+ const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths);
HeapBlock localWidths (numDone);
env->GetFloatArrayRegion (widths, 0, numDone, localWidths);
@@ -145,14 +153,14 @@ public:
JNIEnv* env = getEnv();
jobject matrix = android.createMatrix (env, AffineTransform::scale (unitsToHeightScaleFactor, unitsToHeightScaleFactor).followedBy (t));
- jintArray maskData = (jintArray) android.activity.callObjectMethod (android.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
+ jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get());
env->DeleteLocalRef (matrix);
- const int left = env->GetIntField (rect.get(), android.rectLeft);
- const int top = env->GetIntField (rect.get(), android.rectTop);
- const int right = env->GetIntField (rect.get(), android.rectRight);
- const int bottom = env->GetIntField (rect.get(), android.rectBottom);
+ const int left = env->GetIntField (rect.get(), RectClass.left);
+ const int top = env->GetIntField (rect.get(), RectClass.top);
+ const int right = env->GetIntField (rect.get(), RectClass.right);
+ const int bottom = env->GetIntField (rect.get(), RectClass.bottom);
const Rectangle bounds (left, top, right - left, bottom - top);
diff --git a/src/native/android/juce_android_GraphicsContext.cpp b/src/native/android/juce_android_GraphicsContext.cpp
index 73088ecb94..279e142f01 100644
--- a/src/native/android/juce_android_GraphicsContext.cpp
+++ b/src/native/android/juce_android_GraphicsContext.cpp
@@ -28,6 +28,107 @@
#if JUCE_INCLUDED_FILE
#if USE_ANDROID_CANVAS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Landroid/graphics/Bitmap;)V") \
+ METHOD (drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \
+ METHOD (translate, "translate", "(FF)V") \
+ METHOD (clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \
+ METHOD (clipRect, "clipRect", "(FFFF)Z") \
+ METHOD (clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \
+ METHOD (concat, "concat", "(Landroid/graphics/Matrix;)V") \
+ METHOD (drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \
+ METHOD (drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \
+ METHOD (drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
+ METHOD (drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \
+ METHOD (drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \
+ METHOD (drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \
+ METHOD (getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \
+ METHOD (getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \
+ METHOD (getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \
+ METHOD (save, "save", "()I") \
+ METHOD (restore, "restore", "()V") \
+ METHOD (saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I")
+
+DECLARE_JNI_CLASS (Canvas, "android/graphics/Canvas");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V") \
+ METHOD (moveTo, "moveTo", "(FF)V") \
+ METHOD (lineTo, "lineTo", "(FF)V") \
+ METHOD (quadTo, "quadTo", "(FFFF)V") \
+ METHOD (cubicTo, "cubicTo", "(FFFFFF)V") \
+ METHOD (closePath, "close", "()V") \
+ METHOD (computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \
+
+DECLARE_JNI_CLASS (PathClass, "android/graphics/Path");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V"); \
+ METHOD (regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \
+
+DECLARE_JNI_CLASS (RegionClass, "android/graphics/Region");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \
+ METHOD (bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \
+ METHOD (getPixels, "getPixels", "([IIIIIII)V") \
+ METHOD (setPixels, "setPixels", "([IIIIIII)V") \
+ METHOD (recycle, "recycle", "()V") \
+
+DECLARE_JNI_CLASS (BitmapClass, "android/graphics/Bitmap");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICFIELD (ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \
+ STATICFIELD (ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \
+
+DECLARE_JNI_CLASS (BitmapConfig, "android/graphics/Bitmap$Config");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V")
+
+DECLARE_JNI_CLASS (BitmapShader, "android/graphics/BitmapShader");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V")
+
+DECLARE_JNI_CLASS (ShaderClass, "android/graphics/Shader");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICFIELD (CLAMP, "CLAMP", "Landroid/graphics/Shader$TileMode;")
+
+DECLARE_JNI_CLASS (ShaderTileMode, "android/graphics/Shader$TileMode");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \
+
+DECLARE_JNI_CLASS (LinearGradientClass, "android/graphics/LinearGradient");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \
+
+DECLARE_JNI_CLASS (RadialGradientClass, "android/graphics/RadialGradient");
+#undef JNI_CLASS_MEMBERS
+
//==============================================================================
class AndroidImage : public Image::SharedImage
{
@@ -48,7 +149,7 @@ public:
~AndroidImage()
{
if (bitmap != 0)
- bitmap.callVoidMethod (android.recycle);
+ bitmap.callVoidMethod (BitmapClass.recycle);
}
Image::ImageType getType() const { return Image::NativeImage; }
@@ -65,8 +166,8 @@ public:
SharedImage* clone()
{
JNIEnv* env = getEnv();
- jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, android.ARGB_8888);
- GlobalRef newCopy (bitmap.callObjectMethod (android.bitmapCopy, mode, true));
+ jobject mode = env->GetStaticObjectField (BitmapConfig, BitmapConfig.ARGB_8888);
+ GlobalRef newCopy (bitmap.callObjectMethod (BitmapClass.bitmapCopy, mode, true));
env->DeleteLocalRef (mode);
return new AndroidImage (width, height, newCopy);
@@ -75,8 +176,9 @@ public:
static jobject createBitmap (int width, int height, bool asSingleChannel)
{
JNIEnv* env = getEnv();
- jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, asSingleChannel ? android.ALPHA_8 : android.ARGB_8888);
- jobject result = env->CallStaticObjectMethod (android.bitmapClass, android.createBitmap, width, height, mode);
+ jobject mode = env->GetStaticObjectField (BitmapConfig, asSingleChannel ? BitmapConfig.ALPHA_8
+ : BitmapConfig.ARGB_8888);
+ jobject result = env->CallStaticObjectMethod (BitmapClass, BitmapClass.createBitmap, width, height, mode);
env->DeleteLocalRef (mode);
return result;
}
@@ -97,7 +199,7 @@ private:
intArray = env->NewIntArray (bitmapData.width * bitmapData.height);
if (mode != Image::BitmapData::writeOnly)
- owner_.bitmap.callVoidMethod (android.getPixels, intArray, 0, bitmapData.width, x_, y_,
+ owner_.bitmap.callVoidMethod (BitmapClass.getPixels, intArray, 0, bitmapData.width, x_, y_,
bitmapData.width, bitmapData.height);
bitmapData.data = (uint8*) env->GetIntArrayElements (intArray, 0);
@@ -132,7 +234,7 @@ private:
env->ReleaseIntArrayElements (intArray, (jint*) bitmapData.data, 0);
if (mode != Image::BitmapData::readOnly)
- owner.bitmap.callVoidMethod (android.setPixels, intArray, 0, bitmapData.width, x, y,
+ owner.bitmap.callVoidMethod (BitmapClass.setPixels, intArray, 0, bitmapData.width, x, y,
bitmapData.width, bitmapData.height);
env->DeleteLocalRef (intArray);
@@ -187,12 +289,12 @@ public:
//==============================================================================
void setOrigin (int x, int y)
{
- getCanvas().callVoidMethod (android.translate, (float) x, (float) y);
+ getCanvas().callVoidMethod (Canvas.translate, (float) x, (float) y);
}
void addTransform (const AffineTransform& transform)
{
- getCanvas().callVoidMethod (android.concat, createMatrixRef (getEnv(), transform).get());
+ getCanvas().callVoidMethod (Canvas.concat, createMatrixRef (getEnv(), transform).get());
}
float getScaleFactor()
@@ -202,7 +304,7 @@ public:
bool clipToRectangle (const Rectangle& r)
{
- return getCanvas().callBooleanMethod (android.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
+ return getCanvas().callBooleanMethod (Canvas.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
}
bool clipToRectangleList (const RectangleList& clipRegion)
@@ -218,13 +320,13 @@ public:
void excludeClipRectangle (const Rectangle& r)
{
- android.activity.callVoidMethod (android.excludeClipRegion, getCanvas().get(),
+ android.activity.callVoidMethod (JuceAppActivity.excludeClipRegion, getCanvas().get(),
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom());
}
void clipToPath (const Path& path, const AffineTransform& transform)
{
- (void) getCanvas().callBooleanMethod (android.clipPath, createPath (getEnv(), path, transform).get());
+ (void) getCanvas().callBooleanMethod (Canvas.clipPath, createPath (getEnv(), path, transform).get());
}
void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform)
@@ -241,14 +343,14 @@ public:
Rectangle bounds (getClipBounds());
jobject temporaryLayerBitmap = AndroidImage::createBitmap (bounds.getWidth(), bounds.getHeight(), false);
- jobject temporaryCanvas = env->NewObject (android.canvasClass, android.canvasBitmapConstructor, temporaryLayerBitmap);
+ jobject temporaryCanvas = env->NewObject (Canvas, Canvas.constructor, temporaryLayerBitmap);
setFill (Colours::red);
- env->CallVoidMethod (temporaryCanvas, android.drawRect,
+ env->CallVoidMethod (temporaryCanvas, Canvas.drawRect,
(jfloat) 20, (jfloat) 20, (jfloat) 300, (jfloat) 200,
getCurrentPaint());
- env->CallVoidMethod (temporaryCanvas, android.translate,
+ env->CallVoidMethod (temporaryCanvas, Canvas.translate,
(jfloat) -bounds.getX(), (jfloat) -bounds.getY());
Image maskImage (Image::SingleChannel, bounds.getWidth(), bounds.getHeight(), true);
@@ -273,12 +375,12 @@ public:
const Rectangle getClipBounds() const
{
JNIEnv* env = getEnv();
- jobject rect = getCanvas().callObjectMethod (android.getClipBounds2);
+ jobject rect = getCanvas().callObjectMethod (Canvas.getClipBounds2);
- const int left = env->GetIntField (rect, android.rectLeft);
- const int top = env->GetIntField (rect, android.rectTop);
- const int right = env->GetIntField (rect, android.rectRight);
- const int bottom = env->GetIntField (rect, android.rectBottom);
+ const int left = env->GetIntField (rect, RectClass.left);
+ const int top = env->GetIntField (rect, RectClass.top);
+ const int right = env->GetIntField (rect, RectClass.right);
+ const int bottom = env->GetIntField (rect, RectClass.bottom);
env->DeleteLocalRef (rect);
return Rectangle (left, top, right - left, bottom - top);
@@ -286,8 +388,8 @@ public:
bool isClipEmpty() const
{
- LocalRef tempRect (getEnv()->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0));
- return ! getCanvas().callBooleanMethod (android.getClipBounds, tempRect.get());
+ LocalRef tempRect (getEnv()->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0));
+ return ! getCanvas().callBooleanMethod (Canvas.getClipBounds, tempRect.get());
}
//==============================================================================
@@ -309,14 +411,14 @@ public:
//==============================================================================
void fillRect (const Rectangle& r, bool replaceExistingContents)
{
- getCanvas().callVoidMethod (android.drawRect,
+ getCanvas().callVoidMethod (Canvas.drawRect,
(float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(),
getCurrentPaint());
}
void fillPath (const Path& path, const AffineTransform& transform)
{
- getCanvas().callVoidMethod (android.drawPath, createPath (getEnv(), path, transform).get(),
+ getCanvas().callVoidMethod (Canvas.drawPath, createPath (getEnv(), path, transform).get(),
getCurrentPaint());
}
@@ -327,7 +429,7 @@ public:
if (androidImage != 0)
{
JNIEnv* env = getEnv();
- getCanvas().callVoidMethod (android.drawBitmap, androidImage->bitmap.get(),
+ getCanvas().callVoidMethod (Canvas.drawBitmap, androidImage->bitmap.get(),
createMatrixRef (env, transform).get(), getImagePaint());
}
else
@@ -362,7 +464,7 @@ public:
env->ReleaseIntArrayElements (imageData, dest, 0);
- getCanvas().callVoidMethod (android.drawMemoryBitmap, imageData, 0, bm.width,
+ getCanvas().callVoidMethod (Canvas.drawMemoryBitmap, imageData, 0, bm.width,
transform.getTranslationX(), transform.getTranslationY(),
bm.width, bm.height, true, getImagePaint());
env->DeleteLocalRef (imageData);
@@ -380,18 +482,18 @@ public:
void drawLine (const Line & line)
{
- getCanvas().callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(),
+ getCanvas().callVoidMethod (Canvas.drawLine, line.getStartX(), line.getStartY(),
line.getEndX(), line.getEndY(), getCurrentPaint());
}
void drawVerticalLine (int x, float top, float bottom)
{
- getCanvas().callVoidMethod (android.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint());
+ getCanvas().callVoidMethod (Canvas.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint());
}
void drawHorizontalLine (int y, float left, float right)
{
- getCanvas().callVoidMethod (android.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint());
+ getCanvas().callVoidMethod (Canvas.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint());
}
void setFont (const Font& newFont)
@@ -412,7 +514,7 @@ public:
{
if (transform.isOnlyTranslation())
{
- getCanvas().callVoidMethod (android.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(),
+ getCanvas().callVoidMethod (Canvas.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(),
transform.getTranslationX(), transform.getTranslationY(),
currentState->getPaintForTypeface());
}
@@ -428,7 +530,7 @@ public:
//==============================================================================
void saveState()
{
- (void) getCanvas().callIntMethod (android.save);
+ (void) getCanvas().callIntMethod (Canvas.save);
stateStack.add (new SavedState (*currentState));
}
@@ -448,14 +550,14 @@ public:
jassertfalse; // trying to pop with an empty stack!
}
- getCanvas().callVoidMethod (android.restore);
+ getCanvas().callVoidMethod (Canvas.restore);
}
void beginTransparencyLayer (float opacity)
{
Rectangle clip (getClipBounds());
- (void) getCanvas().callIntMethod (android.saveLayerAlpha,
+ (void) getCanvas().callIntMethod (Canvas.saveLayerAlpha,
(float) clip.getX(),
(float) clip.getY(),
(float) clip.getRight(),
@@ -520,8 +622,8 @@ public:
if (fillType.isColour())
{
- env->DeleteLocalRef (paint.callObjectMethod (android.setShader, (jobject) 0));
- paint.callVoidMethod (android.setColor, colourToInt (fillType.colour));
+ env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, (jobject) 0));
+ paint.callVoidMethod (Paint.setColor, colourToInt (fillType.colour));
}
else if (fillType.isGradient())
{
@@ -547,13 +649,13 @@ public:
env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData());
}
- jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode);
+ jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP);
jobject shader;
if (fillType.gradient->isRadial)
{
- shader = env->NewObject (android.radialGradientClass,
- android.radialGradientConstructor,
+ shader = env->NewObject (RadialGradientClass,
+ RadialGradientClass.constructor,
p1.getX(), p1.getY(),
p1.getDistanceFrom (p2),
coloursArray, positionsArray,
@@ -561,8 +663,8 @@ public:
}
else
{
- shader = env->NewObject (android.linearGradientClass,
- android.linearGradientConstructor,
+ shader = env->NewObject (LinearGradientClass,
+ LinearGradientClass.constructor,
p1.getX(), p1.getY(), p2.getX(), p2.getY(),
coloursArray, positionsArray,
tileMode);
@@ -572,8 +674,8 @@ public:
env->DeleteLocalRef (coloursArray);
env->DeleteLocalRef (positionsArray);
- env->CallVoidMethod (shader, android.setLocalMatrix, createMatrixRef (env, fillType.transform).get());
- env->DeleteLocalRef (paint.callObjectMethod (android.setShader, shader));
+ env->CallVoidMethod (shader, ShaderClass.setLocalMatrix, createMatrixRef (env, fillType.transform).get());
+ env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, shader));
env->DeleteLocalRef (shader);
}
@@ -598,17 +700,17 @@ public:
if (atf != 0)
{
- paint.callObjectMethod (android.setTypeface, atf->typeface.get());
- paint.callVoidMethod (android.setTextSize, font.getHeight());
+ paint.callObjectMethod (Paint.setTypeface, atf->typeface.get());
+ paint.callVoidMethod (Paint.setTextSize, font.getHeight());
const float hScale = font.getHorizontalScale();
if (hScale < 0.99f || hScale > 1.01f)
- paint.callVoidMethod (android.setTextScaleX, hScale);
+ paint.callVoidMethod (Paint.setTextScaleX, hScale);
}
fillNeedsUpdate = true;
- paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha());
+ paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha());
}
return p;
@@ -617,7 +719,7 @@ public:
jobject getImagePaint()
{
jobject p = getPaint();
- paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha());
+ paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha());
fillNeedsUpdate = true;
return p;
}
@@ -630,27 +732,27 @@ public:
{
JNIEnv* env = getEnv();
- jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode);
- jobject shader = env->NewObject (android.bitmapShaderClass, android.bitmapShaderConstructor,
+ jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP);
+ jobject shader = env->NewObject (BitmapShader, BitmapShader.constructor,
temporaryLayerBitmap.get(), tileMode, tileMode);
env->DeleteLocalRef (tileMode);
jobject compositingPaint = android.createPaint (quality);
- env->CallObjectMethod (compositingPaint, android.setShader, shader);
+ env->CallObjectMethod (compositingPaint, Paint.setShader, shader);
env->DeleteLocalRef (shader);
LocalRef maskBitmap (createAlphaBitmap (env, maskImage));
maskImage = Image::null;
- env->CallVoidMethod (previousCanvas, android.drawBitmapAt,
+ env->CallVoidMethod (previousCanvas, Canvas.drawBitmapAt,
maskBitmap.get(), (jfloat) maskLayerX, (jfloat) maskLayerY, compositingPaint);
env->DeleteLocalRef (compositingPaint);
canvas = GlobalRef (previousCanvas);
- env->CallVoidMethod (temporaryLayerBitmap.get(), android.recycle);
- env->CallVoidMethod (maskBitmap.get(), android.recycle);
+ env->CallVoidMethod (temporaryLayerBitmap.get(), BitmapClass.recycle);
+ env->CallVoidMethod (maskBitmap.get(), BitmapClass.recycle);
temporaryLayerBitmap.clear();
}
@@ -693,7 +795,7 @@ public:
}
env->ReleaseIntArrayElements (intArray, (jint*) dest, 0);
- env->CallVoidMethod (bitmap, android.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height);
+ env->CallVoidMethod (bitmap, BitmapClass.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height);
env->DeleteLocalRef (intArray);
return bitmap;
}
@@ -720,9 +822,9 @@ private:
jobject getCurrentPaint() const { return currentState->getPaint(); }
jobject getImagePaint() const { return currentState->getImagePaint(); }
- static const LocalRef createPath (JNIEnv* env, const Path& path)
+ static LocalRef createPath (JNIEnv* env, const Path& path)
{
- jobject p = env->NewObject (android.pathClass, android.pathClassConstructor);
+ jobject p = env->NewObject (PathClass, PathClass.constructor);
Path::Iterator i (path);
@@ -730,11 +832,11 @@ private:
{
switch (i.elementType)
{
- case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, android.moveTo, i.x1, i.y1); break;
- case Path::Iterator::lineTo: env->CallVoidMethod (p, android.lineTo, i.x1, i.y1); break;
- case Path::Iterator::quadraticTo: env->CallVoidMethod (p, android.quadTo, i.x1, i.y1, i.x2, i.y2); break;
- case Path::Iterator::cubicTo: env->CallVoidMethod (p, android.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break;
- case Path::Iterator::closePath: env->CallVoidMethod (p, android.closePath); break;
+ case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, PathClass.moveTo, i.x1, i.y1); break;
+ case Path::Iterator::lineTo: env->CallVoidMethod (p, PathClass.lineTo, i.x1, i.y1); break;
+ case Path::Iterator::quadraticTo: env->CallVoidMethod (p, PathClass.quadTo, i.x1, i.y1, i.x2, i.y2); break;
+ case Path::Iterator::cubicTo: env->CallVoidMethod (p, PathClass.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break;
+ case Path::Iterator::closePath: env->CallVoidMethod (p, PathClass.closePath); break;
default: jassertfalse; break;
}
}
@@ -742,7 +844,7 @@ private:
return LocalRef (p);
}
- static const LocalRef createPath (JNIEnv* env, const Path& path, const AffineTransform& transform)
+ static LocalRef createPath (JNIEnv* env, const Path& path, const AffineTransform& transform)
{
if (transform.isIdentity())
return createPath (env, path);
@@ -752,25 +854,25 @@ private:
return createPath (env, tempPath);
}
- static const LocalRef createMatrixRef (JNIEnv* env, const AffineTransform& t)
+ static LocalRef createMatrixRef (JNIEnv* env, const AffineTransform& t)
{
- return LocalRef (android.createMatrix (*env, t));
+ return LocalRef (android.createMatrix (env, t));
}
- static const LocalRef createRect (JNIEnv* env, const Rectangle& r)
+ static LocalRef createRect (JNIEnv* env, const Rectangle& r)
{
- return LocalRef (env->NewObject (android.rectClass, android.rectConstructor,
+ return LocalRef (env->NewObject (RectClass, RectClass.constructor,
r.getX(), r.getY(), r.getRight(), r.getBottom()));
}
- static const LocalRef createRegion (JNIEnv* env, const RectangleList& list)
+ static LocalRef createRegion (JNIEnv* env, const RectangleList& list)
{
- jobject region = env->NewObject (android.regionClass, android.regionConstructor);
+ jobject region = env->NewObject (RegionClass, RegionClass.constructor);
const int numRects = list.getNumRectangles();
for (int i = 0; i < numRects; ++i)
- env->CallBooleanMethod (region, android.regionUnion, createRect (env, list.getRectangle(i)).get());
+ env->CallBooleanMethod (region, RegionClass.regionUnion, createRect (env, list.getRectangle(i)).get());
return LocalRef (region);
}
@@ -795,7 +897,7 @@ private:
LowLevelGraphicsContext* AndroidImage::createLowLevelContext()
{
- jobject canvas = getEnv()->NewObject (android.canvasClass, android.canvasBitmapConstructor, bitmap.get());
+ jobject canvas = getEnv()->NewObject (Canvas, Canvas.constructor, bitmap.get());
return new AndroidLowLevelGraphicsContext (canvas);
}
#endif
diff --git a/src/native/android/juce_android_Messaging.cpp b/src/native/android/juce_android_Messaging.cpp
index 76693268fd..74e7ee39b0 100644
--- a/src/native/android/juce_android_Messaging.cpp
+++ b/src/native/android/juce_android_Messaging.cpp
@@ -45,7 +45,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend
bool MessageManager::postMessageToSystemQueue (Message* message)
{
message->incReferenceCount();
- getEnv()->CallVoidMethod (android.activity, android.postMessage, (jlong) (pointer_sized_uint) message);
+ getEnv()->CallVoidMethod (android.activity, JuceAppActivity.postMessage, (jlong) (pointer_sized_uint) message);
return true;
}
@@ -111,7 +111,7 @@ public:
void messageCallback()
{
- android.activity.callVoidMethod (android.finish);
+ android.activity.callVoidMethod (JuceAppActivity.finish);
}
};
diff --git a/src/native/android/juce_android_Misc.cpp b/src/native/android/juce_android_Misc.cpp
index 41268c00ce..797e908230 100644
--- a/src/native/android/juce_android_Misc.cpp
+++ b/src/native/android/juce_android_Misc.cpp
@@ -51,7 +51,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activit
{
JUCEApplication::appWillTerminateByForce();
- android.shutdown();
+ android.shutdown (env);
}
//==============================================================================
@@ -65,7 +65,7 @@ void Logger::outputDebugString (const String& text)
JNIEnv* const env = getEnv();
if (env != nullptr)
- env->CallStaticVoidMethod (android.activityClass, android.printToConsole,
+ env->CallStaticVoidMethod (JuceAppActivity, JuceAppActivity.printToConsole,
javaString (text).get());
}
@@ -73,14 +73,13 @@ void Logger::outputDebugString (const String& text)
void SystemClipboard::copyTextToClipboard (const String& text)
{
const LocalRef t (javaString (text));
- android.activity.callVoidMethod (android.setClipboardContent, t.get());
+ android.activity.callVoidMethod (JuceAppActivity.setClipboardContent, t.get());
}
String SystemClipboard::getTextFromClipboard()
{
- const LocalRef text ((jstring) android.activity.callObjectMethod (android.getClipboardContent));
+ const LocalRef text ((jstring) android.activity.callObjectMethod (JuceAppActivity.getClipboardContent));
return juceString (text);
}
-
#endif
diff --git a/src/native/android/juce_android_NativeCode.cpp b/src/native/android/juce_android_NativeCode.cpp
index 0fe58e4d91..06d7d4b208 100644
--- a/src/native/android/juce_android_NativeCode.cpp
+++ b/src/native/android/juce_android_NativeCode.cpp
@@ -90,554 +90,14 @@ BEGIN_JUCE_NAMESPACE
#include "../../audio/midi/juce_MidiInput.h"
#include "../../containers/juce_ScopedValueSetter.h"
-#define USE_ANDROID_CANVAS 0
-
-//==============================================================================
-#define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \
- extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params
-
-//==============================================================================
-// List of basic required classes
-#define JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS) \
- JAVACLASS (activityClass, "com/juce/JuceAppActivity") \
- JAVACLASS (httpStreamClass, "com/juce/JuceAppActivity$HTTPStream") \
- JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \
- JAVACLASS (fileClass, "java/io/File") \
- JAVACLASS (systemClass, "java/lang/System") \
- JAVACLASS (stringBufferClass, "java/lang/StringBuffer") \
- JAVACLASS (contextClass, "android/content/Context") \
- JAVACLASS (canvasClass, "android/graphics/Canvas") \
- JAVACLASS (paintClass, "android/graphics/Paint") \
- JAVACLASS (matrixClass, "android/graphics/Matrix") \
- JAVACLASS (rectClass, "android/graphics/Rect") \
- JAVACLASS (typefaceClass, "android/graphics/Typeface") \
- JAVACLASS (audioTrackClass, "android/media/AudioTrack") \
- JAVACLASS (audioRecordClass, "android/media/AudioRecord") \
-
-//==============================================================================
-// List of extra classes needed when USE_ANDROID_CANVAS is enabled
-#if ! USE_ANDROID_CANVAS
-#define JUCE_JNI_CLASSES(JAVACLASS) JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS);
-#else
-#define JUCE_JNI_CLASSES(JAVACLASS) JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS); \
- JAVACLASS (pathClass, "android/graphics/Path") \
- JAVACLASS (regionClass, "android/graphics/Region") \
- JAVACLASS (bitmapClass, "android/graphics/Bitmap") \
- JAVACLASS (bitmapConfigClass, "android/graphics/Bitmap$Config") \
- JAVACLASS (bitmapShaderClass, "android/graphics/BitmapShader") \
- JAVACLASS (shaderClass, "android/graphics/Shader") \
- JAVACLASS (shaderTileModeClass, "android/graphics/Shader$TileMode") \
- JAVACLASS (linearGradientClass, "android/graphics/LinearGradient") \
- JAVACLASS (radialGradientClass, "android/graphics/RadialGradient") \
-
-#endif
-
-
-//==============================================================================
-// List of required methods
-#define JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
-\
- STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \
- METHOD (activityClass, createNewView, "createNewView", "(Z)Lcom/juce/ComponentPeerView;") \
- METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \
- METHOD (activityClass, postMessage, "postMessage", "(J)V") \
- METHOD (activityClass, finish, "finish", "()V") \
- METHOD (activityClass, getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \
- METHOD (activityClass, setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
- METHOD (activityClass, excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
- METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
- STATICMETHOD (activityClass, createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \
- METHOD (activityClass, showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
- METHOD (activityClass, showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
- METHOD (activityClass, showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
-\
- METHOD (stringBufferClass, stringBufferConstructor, "", "()V") \
- METHOD (stringBufferClass, stringBufferToString, "toString", "()Ljava/lang/String;") \
-\
- METHOD (httpStreamClass, httpStreamRelease, "release", "()V") \
- METHOD (httpStreamClass, httpStreamRead, "read", "([BI)I") \
- METHOD (httpStreamClass, getPosition, "getPosition", "()J") \
- METHOD (httpStreamClass, getTotalLength, "getTotalLength", "()J") \
- METHOD (httpStreamClass, isExhausted, "isExhausted", "()Z") \
- METHOD (httpStreamClass, setPosition, "setPosition", "(J)Z") \
-\
- METHOD (fileClass, fileExists, "exists", "()Z") \
- STATICMETHOD (systemClass, getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \
-\
- METHOD (componentPeerViewClass, setViewName, "setViewName", "(Ljava/lang/String;)V") \
- METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \
- METHOD (componentPeerViewClass, getLeft, "getLeft", "()I") \
- METHOD (componentPeerViewClass, getTop, "getTop", "()I") \
- METHOD (componentPeerViewClass, getWidth, "getWidth", "()I") \
- METHOD (componentPeerViewClass, getHeight, "getHeight", "()I") \
- METHOD (componentPeerViewClass, getLocationOnScreen, "getLocationOnScreen", "([I)V") \
- METHOD (componentPeerViewClass, bringToFront, "bringToFront", "()V") \
- METHOD (componentPeerViewClass, requestFocus, "requestFocus", "()Z") \
- METHOD (componentPeerViewClass, setVisible, "setVisible", "(Z)V") \
- METHOD (componentPeerViewClass, isVisible, "isVisible", "()Z") \
- METHOD (componentPeerViewClass, hasFocus, "hasFocus", "()Z") \
- METHOD (componentPeerViewClass, invalidate, "invalidate", "(IIII)V") \
- METHOD (componentPeerViewClass, containsPoint, "containsPoint", "(II)Z") \
-\
- METHOD (canvasClass, drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \
-\
- METHOD (paintClass, paintClassConstructor, "", "(I)V") \
- METHOD (paintClass, setColor, "setColor", "(I)V") \
- METHOD (paintClass, setAlpha, "setAlpha", "(I)V") \
- METHOD (paintClass, setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \
- METHOD (paintClass, ascent, "ascent", "()F") \
- METHOD (paintClass, descent, "descent", "()F") \
- METHOD (paintClass, setTextSize, "setTextSize", "(F)V") \
- METHOD (paintClass, getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \
- METHOD (paintClass, setTextScaleX, "setTextScaleX", "(F)V") \
- METHOD (paintClass, getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \
-\
- METHOD (matrixClass, matrixClassConstructor, "", "()V") \
- METHOD (matrixClass, setValues, "setValues", "([F)V") \
-\
- STATICMETHOD (typefaceClass, create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \
- STATICMETHOD (typefaceClass, createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
-\
- METHOD (rectClass, rectConstructor, "", "(IIII)V") \
- FIELD (rectClass, rectLeft, "left", "I") \
- FIELD (rectClass, rectRight, "right", "I") \
- FIELD (rectClass, rectTop, "top", "I") \
- FIELD (rectClass, rectBottom, "bottom", "I") \
-\
- METHOD (audioTrackClass, audioTrackConstructor, "", "(IIIIII)V") \
- STATICMETHOD (audioTrackClass, getMinBufferSize, "getMinBufferSize", "(III)I") \
- STATICMETHOD (audioTrackClass, getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \
- METHOD (audioTrackClass, audioTrackPlay, "play", "()V") \
- METHOD (audioTrackClass, audioTrackStop, "stop", "()V") \
- METHOD (audioTrackClass, audioTrackRelease, "release", "()V") \
- METHOD (audioTrackClass, audioTrackFlush, "flush", "()V") \
- METHOD (audioTrackClass, audioTrackWrite, "write", "([SII)I") \
-\
- METHOD (audioRecordClass, audioRecordConstructor, "", "(IIIII)V"); \
- STATICMETHOD (audioRecordClass, getMinRecordBufferSize, "getMinBufferSize", "(III)I") \
- METHOD (audioRecordClass, startRecording, "startRecording", "()V"); \
- METHOD (audioRecordClass, stopRecording, "stop", "()V"); \
- METHOD (audioRecordClass, audioRecordRead, "read", "([SII)I"); \
- METHOD (audioRecordClass, audioRecordRelease, "release", "()V"); \
-
-
-//==============================================================================
-// List of extra methods needed when USE_ANDROID_CANVAS is enabled
-#if ! USE_ANDROID_CANVAS
-#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD)
-#else
-#define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- METHOD (pathClass, pathClassConstructor, "", "()V") \
- METHOD (pathClass, moveTo, "moveTo", "(FF)V") \
- METHOD (pathClass, lineTo, "lineTo", "(FF)V") \
- METHOD (pathClass, quadTo, "quadTo", "(FFFF)V") \
- METHOD (pathClass, cubicTo, "cubicTo", "(FFFFFF)V") \
- METHOD (pathClass, closePath, "close", "()V") \
- METHOD (pathClass, computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \
-\
- STATICMETHOD (bitmapClass, createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \
- STATICFIELD (bitmapConfigClass, ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \
- STATICFIELD (bitmapConfigClass, ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \
- METHOD (bitmapClass, bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \
- METHOD (bitmapClass, getPixels, "getPixels", "([IIIIIII)V") \
- METHOD (bitmapClass, setPixels, "setPixels", "([IIIIIII)V") \
- METHOD (bitmapClass, recycle, "recycle", "()V") \
-\
- METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \
- STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \
-\
- METHOD (bitmapShaderClass, bitmapShaderConstructor, "", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \
-\
- METHOD (canvasClass, canvasBitmapConstructor, "", "(Landroid/graphics/Bitmap;)V") \
- METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, translate, "translate", "(FF)V") \
- METHOD (canvasClass, clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \
- METHOD (canvasClass, clipRect, "clipRect", "(FFFF)Z") \
- METHOD (canvasClass, clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \
- METHOD (canvasClass, concat, "concat", "(Landroid/graphics/Matrix;)V") \
- METHOD (canvasClass, drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \
- METHOD (canvasClass, drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \
- METHOD (canvasClass, getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \
- METHOD (canvasClass, getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \
- METHOD (canvasClass, save, "save", "()I") \
- METHOD (canvasClass, restore, "restore", "()V") \
- METHOD (canvasClass, saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I") \
-\
- METHOD (linearGradientClass, linearGradientConstructor, "", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (radialGradientClass, radialGradientConstructor, "", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \
-\
- METHOD (regionClass, regionConstructor, "", "()V"); \
- METHOD (regionClass, regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \
-
-#endif
-
-
-//==============================================================================
-class ThreadLocalJNIEnvHolder
-{
-public:
- ThreadLocalJNIEnvHolder()
- : jvm (0)
- {
- zeromem (threads, sizeof (threads));
- zeromem (envs, sizeof (envs));
- }
-
- void initialise (JNIEnv* env)
- {
- env->GetJavaVM (&jvm);
- addEnv (env);
- }
-
- void attach()
- {
- JNIEnv* env = nullptr;
- jvm->AttachCurrentThread (&env, 0);
-
- if (env != 0)
- addEnv (env);
- }
-
- void detach()
- {
- jvm->DetachCurrentThread();
-
- const pthread_t thisThread = pthread_self();
-
- SpinLock::ScopedLockType sl (addRemoveLock);
- for (int i = 0; i < maxThreads; ++i)
- if (threads[i] == thisThread)
- threads[i] = 0;
- }
-
- JNIEnv* get() const noexcept
- {
- const pthread_t thisThread = pthread_self();
-
- for (int i = 0; i < maxThreads; ++i)
- if (threads[i] == thisThread)
- return envs[i];
-
- return nullptr;
- }
-
- enum { maxThreads = 16 };
-
-private:
- JavaVM* jvm;
- pthread_t threads [maxThreads];
- JNIEnv* envs [maxThreads];
- SpinLock addRemoveLock;
-
- void addEnv (JNIEnv* env)
- {
- SpinLock::ScopedLockType sl (addRemoveLock);
-
- if (get() == 0)
- {
- const pthread_t thisThread = pthread_self();
-
- for (int i = 0; i < maxThreads; ++i)
- {
- if (threads[i] == 0)
- {
- envs[i] = env;
- threads[i] = thisThread;
- return;
- }
- }
- }
-
- jassertfalse; // too many threads!
- }
-};
-
-static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
-
-struct AndroidThreadScope
-{
- AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
- ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
-};
-
-static inline JNIEnv* getEnv() noexcept
-{
- return threadLocalJNIEnvHolder.get();
-}
-
-
-//==============================================================================
-class GlobalRef
-{
-public:
- inline GlobalRef() noexcept
- : obj (0)
- {
- }
-
- inline explicit GlobalRef (jobject obj_)
- : obj (retain (obj_))
- {
- }
-
- inline GlobalRef (const GlobalRef& other)
- : obj (retain (other.obj))
- {
- }
-
- ~GlobalRef()
- {
- clear();
- }
-
- inline void clear()
- {
- if (obj != 0)
- {
- getEnv()->DeleteGlobalRef (obj);
- obj = 0;
- }
- }
-
- inline GlobalRef& operator= (const GlobalRef& other)
- {
- clear();
- obj = retain (other.obj);
- return *this;
- }
-
- //==============================================================================
- inline operator jobject() const noexcept { return obj; }
- inline jobject get() const noexcept { return obj; }
-
- //==============================================================================
- #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \
- returnType call##typeName##Method (jmethodID methodID, ... ) const \
- { \
- va_list args; \
- va_start (args, methodID); \
- returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \
- va_end (args); \
- return result; \
- }
-
- DECLARE_CALL_TYPE_METHOD (jobject, Object)
- DECLARE_CALL_TYPE_METHOD (jboolean, Boolean)
- DECLARE_CALL_TYPE_METHOD (jbyte, Byte)
- DECLARE_CALL_TYPE_METHOD (jchar, Char)
- DECLARE_CALL_TYPE_METHOD (jshort, Short)
- DECLARE_CALL_TYPE_METHOD (jint, Int)
- DECLARE_CALL_TYPE_METHOD (jlong, Long)
- DECLARE_CALL_TYPE_METHOD (jfloat, Float)
- DECLARE_CALL_TYPE_METHOD (jdouble, Double)
- #undef DECLARE_CALL_TYPE_METHOD
-
- void callVoidMethod (jmethodID methodID, ... ) const
- {
- va_list args;
- va_start (args, methodID);
- getEnv()->CallVoidMethodV (obj, methodID, args);
- va_end (args);
- }
-
-private:
- //==============================================================================
- jobject obj;
-
- static inline jobject retain (jobject obj_)
- {
- return obj_ == 0 ? 0 : getEnv()->NewGlobalRef (obj_);
- }
-};
-
-//==============================================================================
-template
-class LocalRef
-{
-public:
- explicit inline LocalRef (JavaType obj_) noexcept
- : obj (obj_)
- {
- }
-
- inline LocalRef (const LocalRef& other) noexcept
- : obj (retain (other.obj))
- {
- }
-
- ~LocalRef()
- {
- if (obj != 0)
- getEnv()->DeleteLocalRef (obj);
- }
-
- LocalRef& operator= (const LocalRef& other)
- {
- if (obj != other.obj)
- {
- if (obj != 0)
- getEnv()->DeleteLocalRef (obj);
-
- obj = retain (other.obj);
- }
-
- return *this;
- }
-
- inline operator JavaType() const noexcept { return obj; }
- inline JavaType get() const noexcept { return obj; }
-
-private:
- JavaType obj;
-
- static JavaType retain (JavaType obj_)
- {
- return obj_ == 0 ? 0 : (JavaType) getEnv()->NewLocalRef (obj_);
- }
-};
-
-//==============================================================================
-static const String juceString (jstring s)
-{
- JNIEnv* env = getEnv();
-
- jboolean isCopy;
- const char* const utf8 = env->GetStringUTFChars (s, &isCopy);
- CharPointer_UTF8 utf8CP (utf8);
- const String result (utf8CP);
- env->ReleaseStringUTFChars (s, utf8);
- return result;
-}
-
-static const LocalRef javaString (const String& s)
-{
- return LocalRef (getEnv()->NewStringUTF (s.toUTF8()));
-}
-
-static const LocalRef javaStringFromChar (const juce_wchar c)
-{
- char utf8[5] = { 0 };
- CharPointer_UTF8 (utf8).write (c);
- return LocalRef (getEnv()->NewStringUTF (utf8));
-}
-
-//==============================================================================
-class AndroidJavaCallbacks
-{
-public:
- AndroidJavaCallbacks() : screenWidth (0), screenHeight (0)
- {
- }
-
- void initialise (JNIEnv* env, jobject activity_,
- jstring appFile_, jstring appDataDir_)
- {
- threadLocalJNIEnvHolder.initialise (env);
- activity = GlobalRef (activity_);
- appFile = juceString (appFile_);
- appDataDir = juceString (appDataDir_);
-
- #define CREATE_JNI_CLASS(className, path) \
- className = (jclass) env->NewGlobalRef (env->FindClass (path)); \
- jassert (className != 0);
- JUCE_JNI_CLASSES (CREATE_JNI_CLASS);
- #undef CREATE_JNI_CLASS
-
- #define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \
- methodID = env->GetMethodID (ownerClass, stringName, params); \
- jassert (methodID != 0);
- #define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \
- methodID = env->GetStaticMethodID (ownerClass, stringName, params); \
- jassert (methodID != 0);
- #define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \
- fieldID = env->GetFieldID (ownerClass, stringName, signature); \
- jassert (fieldID != 0);
- #define CREATE_JNI_STATICFIELD(ownerClass, fieldID, stringName, signature) \
- fieldID = env->GetStaticFieldID (ownerClass, stringName, signature); \
- jassert (fieldID != 0);
- JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD);
- #undef CREATE_JNI_METHOD
- }
-
- void shutdown()
- {
- JNIEnv* env = getEnv();
-
- if (env != 0)
- {
- #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className);
- JUCE_JNI_CLASSES (RELEASE_JNI_CLASS);
- #undef RELEASE_JNI_CLASS
-
- activity.clear();
- }
- }
-
- //==============================================================================
- GlobalRef activity;
- String appFile, appDataDir;
- int screenWidth, screenHeight;
-
- jobject createPaint (Graphics::ResamplingQuality quality)
- {
- jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/
- | 4 /*DITHER_FLAG*/
- | 128 /*SUBPIXEL_TEXT_FLAG*/;
-
- if (quality > Graphics::lowResamplingQuality)
- constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/
-
- return getEnv()->NewObject (paintClass, paintClassConstructor, constructorFlags);
- }
-
- const jobject createMatrix (JNIEnv* env, const AffineTransform& t)
- {
- jobject m = env->NewObject (matrixClass, matrixClassConstructor);
-
- jfloat values[9] = { t.mat00, t.mat01, t.mat02,
- t.mat10, t.mat11, t.mat12,
- 0.0f, 0.0f, 1.0f };
-
- jfloatArray javaArray = env->NewFloatArray (9);
- env->SetFloatArrayRegion (javaArray, 0, 9, values);
-
- env->CallVoidMethod (m, setValues, javaArray);
- env->DeleteLocalRef (javaArray);
-
- return m;
- }
-
- //==============================================================================
- #define DECLARE_JNI_CLASS(className, path) jclass className;
- JUCE_JNI_CLASSES (DECLARE_JNI_CLASS);
- #undef DECLARE_JNI_CLASS
-
- #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID;
- #define DECLARE_JNI_FIELD(ownerClass, fieldID, stringName, signature) jfieldID fieldID;
- JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD);
- #undef DECLARE_JNI_METHOD
-};
-
-static AndroidJavaCallbacks android;
-
-// This is an unsatisfactory workaround for a linker warning that appeared in NDK5c.
-// If anyone actually understands what this symbol is for and why the linker gets confused by it,
-// please let me know!
-extern "C" { void* __dso_handle = 0; }
+#include "juce_android_JNIHelpers.h"
//==============================================================================
#define JUCE_INCLUDED_FILE 1
// Now include the actual code files..
-#include "juce_android_Misc.cpp"
#include "juce_android_SystemStats.cpp"
+#include "juce_android_Misc.cpp"
#include "../common/juce_posix_SharedCode.h"
#include "juce_android_Files.cpp"
#include "../common/juce_posix_NamedPipe.cpp"
diff --git a/src/native/android/juce_android_Network.cpp b/src/native/android/juce_android_Network.cpp
index 5f5aaadb8a..737d5d3977 100644
--- a/src/native/android/juce_android_Network.cpp
+++ b/src/native/android/juce_android_Network.cpp
@@ -27,6 +27,26 @@
// compiled on its own).
#if JUCE_INCLUDED_FILE
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "()V") \
+ METHOD (toString, "toString", "()Ljava/lang/String;") \
+
+DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (release, "release", "()V") \
+ METHOD (read, "read", "([BI)I") \
+ METHOD (getPosition, "getPosition", "()J") \
+ METHOD (getTotalLength, "getTotalLength", "()J") \
+ METHOD (isExhausted, "isExhausted", "()Z") \
+ METHOD (setPosition, "setPosition", "(J)Z") \
+
+DECLARE_JNI_CLASS (HTTPStream, "com/juce/JuceAppActivity$HTTPStream");
+#undef JNI_CLASS_MEMBERS
+
//==============================================================================
void MACAddress::findAllAddresses (Array& result)
@@ -67,10 +87,10 @@ public:
env->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData());
}
- LocalRef responseHeaderBuffer (env->NewObject (android.stringBufferClass, android.stringBufferConstructor));
+ LocalRef responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor));
- stream = GlobalRef (env->CallStaticObjectMethod (android.activityClass,
- android.createHTTPStream,
+ stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
+ JuceAppActivity.createHTTPStream,
javaString (address).get(),
(jboolean) isPost,
postDataArray,
@@ -87,8 +107,8 @@ public:
{
LocalRef headersString ((jstring) env->CallObjectMethod (responseHeaderBuffer.get(),
- android.stringBufferToString));
- headerLines.addLines (juceString (headersString));
+ StringBuffer.toString));
+ headerLines.addLines (juceString (env, headersString));
}
if (responseHeaders != 0)
@@ -109,14 +129,14 @@ public:
~WebInputStream()
{
if (stream != 0)
- stream.callVoidMethod (android.httpStreamRelease);
+ stream.callVoidMethod (HTTPStream.release);
}
//==============================================================================
- bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (android.isExhausted); }
- int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (android.getTotalLength) : 0; }
- int64 getPosition() { return stream != nullptr ? stream.callLongMethod (android.getPosition) : 0; }
- bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (android.setPosition, (jlong) wantedPos); }
+ bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); }
+ int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; }
+ int64 getPosition() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; }
+ bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (HTTPStream.setPosition, (jlong) wantedPos); }
int read (void* buffer, int bytesToRead)
{
@@ -127,7 +147,7 @@ public:
jbyteArray javaArray = env->NewByteArray (bytesToRead);
- int numBytes = stream.callIntMethod (android.httpStreamRead, javaArray, (jint) bytesToRead);
+ int numBytes = stream.callIntMethod (HTTPStream.read, javaArray, (jint) bytesToRead);
if (numBytes > 0)
env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast (buffer));
diff --git a/src/native/android/juce_android_SystemStats.cpp b/src/native/android/juce_android_SystemStats.cpp
index 08bc778a37..9ad1f33fee 100644
--- a/src/native/android/juce_android_SystemStats.cpp
+++ b/src/native/android/juce_android_SystemStats.cpp
@@ -27,13 +27,234 @@
// compiled on its own).
#if JUCE_INCLUDED_FILE
+//==============================================================================
+JNIClassBase::JNIClassBase (const char* classPath_)
+ : classPath (classPath_), classRef (0)
+{
+ getClasses().add (this);
+}
+
+JNIClassBase::~JNIClassBase()
+{
+ getClasses().removeValue (this);
+}
+
+Array& JNIClassBase::getClasses()
+{
+ static Array classes;
+ return classes;
+}
+
+void JNIClassBase::initialise (JNIEnv* env)
+{
+ classRef = (jclass) env->NewGlobalRef (env->FindClass (classPath));
+ jassert (classRef != 0);
+
+ initialiseFields (env);
+}
+
+void JNIClassBase::release (JNIEnv* env)
+{
+ env->DeleteGlobalRef (classRef);
+}
+
+void JNIClassBase::initialiseAllClasses (JNIEnv* env)
+{
+ Array& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->initialise (env);
+}
+
+void JNIClassBase::releaseAllClasses (JNIEnv* env)
+{
+ Array& classes = getClasses();
+ for (int i = classes.size(); --i >= 0;)
+ classes.getUnchecked(i)->release (env);
+}
+
+jmethodID JNIClassBase::resolveMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jmethodID JNIClassBase::resolveStaticMethod (JNIEnv* env, const char* methodName, const char* params)
+{
+ jmethodID m = env->GetStaticMethodID (classRef, methodName, params);
+ jassert (m != 0);
+ return m;
+}
+
+jfieldID JNIClassBase::resolveField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+jfieldID JNIClassBase::resolveStaticField (JNIEnv* env, const char* fieldName, const char* signature)
+{
+ jfieldID f = env->GetStaticFieldID (classRef, fieldName, signature);
+ jassert (f != 0);
+ return f;
+}
+
+//==============================================================================
+class ThreadLocalJNIEnvHolder
+{
+public:
+ ThreadLocalJNIEnvHolder()
+ : jvm (nullptr)
+ {
+ zeromem (threads, sizeof (threads));
+ zeromem (envs, sizeof (envs));
+ }
+
+ void initialise (JNIEnv* env)
+ {
+ env->GetJavaVM (&jvm);
+ addEnv (env);
+ }
+
+ void attach()
+ {
+ JNIEnv* env = nullptr;
+ jvm->AttachCurrentThread (&env, 0);
+
+ if (env != 0)
+ addEnv (env);
+ }
+
+ void detach()
+ {
+ jvm->DetachCurrentThread();
+
+ const pthread_t thisThread = pthread_self();
+
+ SpinLock::ScopedLockType sl (addRemoveLock);
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ threads[i] = 0;
+ }
+
+ JNIEnv* get() const noexcept
+ {
+ const pthread_t thisThread = pthread_self();
+
+ for (int i = 0; i < maxThreads; ++i)
+ if (threads[i] == thisThread)
+ return envs[i];
+
+ return nullptr;
+ }
+
+ enum { maxThreads = 16 };
+
+private:
+ JavaVM* jvm;
+ pthread_t threads [maxThreads];
+ JNIEnv* envs [maxThreads];
+ SpinLock addRemoveLock;
+
+ void addEnv (JNIEnv* env)
+ {
+ SpinLock::ScopedLockType sl (addRemoveLock);
+
+ if (get() == nullptr)
+ {
+ const pthread_t thisThread = pthread_self();
+
+ for (int i = 0; i < maxThreads; ++i)
+ {
+ if (threads[i] == 0)
+ {
+ envs[i] = env;
+ threads[i] = thisThread;
+ return;
+ }
+ }
+ }
+
+ jassertfalse; // too many threads!
+ }
+};
+
+static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
+
+JNIEnv* getEnv() noexcept
+{
+ return threadLocalJNIEnvHolder.get();
+}
+
+//==============================================================================
+AndroidSystem::AndroidSystem() : screenWidth (0), screenHeight (0)
+{
+}
+
+void AndroidSystem::initialise (JNIEnv* env, jobject activity_,
+ jstring appFile_, jstring appDataDir_)
+{
+ JNIClassBase::initialiseAllClasses (env);
+
+ threadLocalJNIEnvHolder.initialise (env);
+ activity = GlobalRef (activity_);
+ appFile = juceString (env, appFile_);
+ appDataDir = juceString (env, appDataDir_);
+}
+
+void AndroidSystem::shutdown (JNIEnv* env)
+{
+ activity.clear();
+ JNIClassBase::releaseAllClasses (env);
+}
+
+jobject AndroidSystem::createPaint (Graphics::ResamplingQuality quality)
+{
+ jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/
+ | 4 /*DITHER_FLAG*/
+ | 128 /*SUBPIXEL_TEXT_FLAG*/;
+
+ if (quality > Graphics::lowResamplingQuality)
+ constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/
+
+ return getEnv()->NewObject (Paint, Paint.constructor, constructorFlags);
+}
+
+const jobject AndroidSystem::createMatrix (JNIEnv* env, const AffineTransform& t)
+{
+ jobject m = env->NewObject (Matrix, Matrix.constructor);
+
+ jfloat values[9] = { t.mat00, t.mat01, t.mat02,
+ t.mat10, t.mat11, t.mat12,
+ 0.0f, 0.0f, 1.0f };
+
+ jfloatArray javaArray = env->NewFloatArray (9);
+ env->SetFloatArrayRegion (javaArray, 0, 9, values);
+
+ env->CallVoidMethod (m, Matrix.setValues, javaArray);
+ env->DeleteLocalRef (javaArray);
+
+ return m;
+}
+
+AndroidSystem android;
+
//==============================================================================
namespace AndroidStatsHelpers
{
+ //==============================================================================
+ #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;")
+
+ DECLARE_JNI_CLASS (SystemClass, "java/lang/System");
+ #undef JNI_CLASS_MEMBERS
+
+ //==============================================================================
String getSystemProperty (const String& name)
{
- return juceString (LocalRef ((jstring) getEnv()->CallStaticObjectMethod (android.systemClass,
- android.getProperty,
+ return juceString (LocalRef ((jstring) getEnv()->CallStaticObjectMethod (SystemClass,
+ SystemClass.getProperty,
javaString (name).get())));
}
}
@@ -51,11 +272,11 @@ String SystemStats::getOperatingSystemName()
bool SystemStats::isOperatingSystem64Bit()
{
- #if JUCE_64BIT
+ #if JUCE_64BIT
return true;
- #else
+ #else
return false;
- #endif
+ #endif
}
String SystemStats::getCpuVendor()
@@ -70,13 +291,11 @@ int SystemStats::getCpuSpeedInMegaherz()
int SystemStats::getMemorySizeInMegabytes()
{
- // xxx they forgot to implement sysinfo in the library, dammit! Should put this stuff back when they fix it.
-/* struct sysinfo sysi;
+ struct sysinfo sysi;
if (sysinfo (&sysi) == 0)
return (sysi.totalram * sysi.mem_unit / (1024 * 1024));
- */
- DBG ("warning! memory size is unavailable due to an Android bug!");
+
return 0;
}
@@ -159,5 +378,10 @@ bool Time::setSystemTimeToThisTime() const
return false;
}
+//==============================================================================
+// This is an unsatisfactory workaround for a linker warning that appeared in NDK5c.
+// If anyone actually understands what this symbol is for and why the linker gets confused by it,
+// please let me know!
+extern "C" { void* __dso_handle = 0; }
#endif
diff --git a/src/native/android/juce_android_Windowing.cpp b/src/native/android/juce_android_Windowing.cpp
index ae7dfae94a..e2f95f702f 100644
--- a/src/native/android/juce_android_Windowing.cpp
+++ b/src/native/android/juce_android_Windowing.cpp
@@ -27,6 +27,34 @@
// compiled on its own).
#if JUCE_INCLUDED_FILE
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (drawBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \
+ METHOD (getClipBounds, "getClipBounds", "()Landroid/graphics/Rect;")
+
+DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \
+ METHOD (layout, "layout", "(IIII)V") \
+ METHOD (getLeft, "getLeft", "()I") \
+ METHOD (getTop, "getTop", "()I") \
+ METHOD (getWidth, "getWidth", "()I") \
+ METHOD (getHeight, "getHeight", "()I") \
+ METHOD (getLocationOnScreen, "getLocationOnScreen", "([I)V") \
+ METHOD (bringToFront, "bringToFront", "()V") \
+ METHOD (requestFocus, "requestFocus", "()Z") \
+ METHOD (setVisible, "setVisible", "(Z)V") \
+ METHOD (isVisible, "isVisible", "()Z") \
+ METHOD (hasFocus, "hasFocus", "()Z") \
+ METHOD (invalidate, "invalidate", "(IIII)V") \
+ METHOD (containsPoint, "containsPoint", "(II)Z") \
+
+DECLARE_JNI_CLASS (ComponentPeerView, "com/juce/ComponentPeerView");
+#undef JNI_CLASS_MEMBERS
+
//==============================================================================
class AndroidComponentPeer : public ComponentPeer
@@ -35,7 +63,7 @@ public:
//==============================================================================
AndroidComponentPeer (Component* const component, const int windowStyleFlags)
: ComponentPeer (component, windowStyleFlags),
- view (android.activity.callObjectMethod (android.createNewView, component->isOpaque())),
+ view (android.activity.callObjectMethod (JuceAppActivity.createNewView, component->isOpaque())),
usingAndroidGraphics (false),
fullScreen (false),
sizeAllocated (0)
@@ -48,7 +76,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- android.activity.callVoidMethod (android.deleteView, view.get());
+ android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get());
}
else
{
@@ -63,7 +91,7 @@ public:
void messageCallback()
{
- android.activity.callVoidMethod (android.deleteView, view.get());
+ android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get());
}
private:
@@ -85,7 +113,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- view.callVoidMethod (android.setVisible, shouldBeVisible);
+ view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
}
else
{
@@ -100,7 +128,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.setVisible, shouldBeVisible);
+ view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
}
private:
@@ -114,7 +142,7 @@ public:
void setTitle (const String& title)
{
- view.callVoidMethod (android.setViewName, javaString (title).get());
+ view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get());
}
void setPosition (int x, int y)
@@ -137,7 +165,7 @@ public:
w = jmax (0, w);
h = jmax (0, h);
- view.callVoidMethod (android.layout, x, y, x + w, y + h);
+ view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h);
}
else
{
@@ -152,7 +180,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.layout, x, y, x + w, y + h);
+ view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h);
}
private:
@@ -166,16 +194,16 @@ public:
const Rectangle getBounds() const
{
- return Rectangle (view.callIntMethod (android.getLeft),
- view.callIntMethod (android.getTop),
- view.callIntMethod (android.getWidth),
- view.callIntMethod (android.getHeight));
+ return Rectangle (view.callIntMethod (ComponentPeerView.getLeft),
+ view.callIntMethod (ComponentPeerView.getTop),
+ view.callIntMethod (ComponentPeerView.getWidth),
+ view.callIntMethod (ComponentPeerView.getHeight));
}
const Point getScreenPosition() const
{
- return Point (view.callIntMethod (android.getLeft),
- view.callIntMethod (android.getTop));
+ return Point (view.callIntMethod (ComponentPeerView.getLeft),
+ view.callIntMethod (ComponentPeerView.getTop));
}
const Point localToGlobal (const Point& relativePosition)
@@ -227,7 +255,8 @@ public:
{
return isPositiveAndBelow (position.getX(), component->getWidth())
&& isPositiveAndBelow (position.getY(), component->getHeight())
- && ((! trueIfInAChildWindow) || view.callBooleanMethod (android.containsPoint, position.getX(), position.getY()));
+ && ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint,
+ position.getX(), position.getY()));
}
const BorderSize getFrameSize() const
@@ -244,7 +273,7 @@ public:
void toFront (bool makeActive)
{
- view.callVoidMethod (android.bringToFront);
+ view.callVoidMethod (ComponentPeerView.bringToFront);
if (makeActive)
grabFocus();
@@ -283,12 +312,12 @@ public:
//==============================================================================
bool isFocused() const
{
- return view.callBooleanMethod (android.hasFocus);
+ return view.callBooleanMethod (ComponentPeerView.hasFocus);
}
void grabFocus()
{
- view.callBooleanMethod (android.requestFocus);
+ view.callBooleanMethod (ComponentPeerView.requestFocus);
}
void handleFocusChangeCallback (bool hasFocus)
@@ -307,20 +336,20 @@ public:
//==============================================================================
void handlePaintCallback (JNIEnv* env, jobject canvas)
{
-#if USE_ANDROID_CANVAS
+ #if USE_ANDROID_CANVAS
if (usingAndroidGraphics)
{
AndroidLowLevelGraphicsContext g (canvas);
handlePaint (g);
}
else
-#endif
+ #endif
{
- jobject rect = env->CallObjectMethod (canvas, android.getClipBounds2);
- const int left = env->GetIntField (rect, android.rectLeft);
- const int top = env->GetIntField (rect, android.rectTop);
- const int right = env->GetIntField (rect, android.rectRight);
- const int bottom = env->GetIntField (rect, android.rectBottom);
+ jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds);
+ const int left = env->GetIntField (rect, RectClass.left);
+ const int top = env->GetIntField (rect, RectClass.top);
+ const int right = env->GetIntField (rect, RectClass.right);
+ const int bottom = env->GetIntField (rect, RectClass.bottom);
env->DeleteLocalRef (rect);
const Rectangle clip (left, top, right - left, bottom - top);
@@ -350,7 +379,7 @@ public:
env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0);
- env->CallVoidMethod (canvas, android.drawMemoryBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),
+ env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),
(jfloat) clip.getX(), (jfloat) clip.getY(),
clip.getWidth(), clip.getHeight(), true, (jobject) 0);
}
@@ -361,7 +390,7 @@ public:
{
if (MessageManager::getInstance()->isThisTheMessageThread())
{
- view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
+ view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
}
else
{
@@ -376,7 +405,7 @@ public:
void messageCallback()
{
- view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
+ view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
}
private:
@@ -511,25 +540,16 @@ Point AndroidComponentPeer::lastMousePos;
JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \
{ \
AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \
- if (peer != 0) \
+ if (peer != nullptr) \
peer->juceMethodInvocation; \
}
-JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas),
- handlePaintCallback (env, canvas))
-
-JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseDownCallback ((float) x, (float) y, (int64) time))
-JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseDragCallback ((float) x, (float) y, (int64) time))
-JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time),
- handleMouseUpCallback ((float) x, (float) y, (int64) time))
-
-JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view),
- handleMovedOrResized())
-
-JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus),
- handleFocusChangeCallback (hasFocus))
+JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), handlePaintCallback (env, canvas))
+JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDownCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDragCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseUpCallback ((float) x, (float) y, (int64) time))
+JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view), handleMovedOrResized())
+JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus), handleFocusChangeCallback (hasFocus))
//==============================================================================
ComponentPeer* Component::createNewPeer (int styleFlags, void*)
@@ -596,7 +616,7 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIcon
const String& title, const String& message,
Component* associatedComponent)
{
- android.activity.callVoidMethod (android.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0);
+ android.activity.callVoidMethod (JuceAppActivity.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0);
}
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType,
@@ -606,7 +626,7 @@ bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType
{
jassert (callback != 0); // on android, all alerts must be non-modal!!
- android.activity.callVoidMethod (android.showOkCancelBox, javaString (title).get(), javaString (message).get(),
+ android.activity.callVoidMethod (JuceAppActivity.showOkCancelBox, javaString (title).get(), javaString (message).get(),
(jlong) (pointer_sized_int) callback);
return false;
}
@@ -618,7 +638,7 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy
{
jassert (callback != 0); // on android, all alerts must be non-modal!!
- android.activity.callVoidMethod (android.showYesNoCancelBox, javaString (title).get(), javaString (message).get(),
+ android.activity.callVoidMethod (JuceAppActivity.showYesNoCancelBox, javaString (title).get(), javaString (message).get(),
(jlong) (pointer_sized_int) callback);
return 0;
}
diff --git a/src/native/common/juce_posix_SharedCode.h b/src/native/common/juce_posix_SharedCode.h
index ec8eac7346..cf7bd95fa4 100644
--- a/src/native/common/juce_posix_SharedCode.h
+++ b/src/native/common/juce_posix_SharedCode.h
@@ -776,6 +776,12 @@ void* threadEntryProc (void* userData)
JUCE_AUTORELEASEPOOL
#if JUCE_ANDROID
+ struct AndroidThreadScope
+ {
+ AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); }
+ ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); }
+ };
+
const AndroidThreadScope androidEnv;
#endif