diff --git a/examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt b/examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt
index f56b85ccb2..adae6fc47f 100644
--- a/examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt
+++ b/examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_analyticscollection_AnalyticsCollection" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/analyticscollection/AnalyticsCollection\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_analyticscollection_AnalyticsCollection" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/analyticscollection/AnalyticsCollection\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_yourcompany_analyticscollection_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/yourcompany/analyticscollection/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -552,6 +552,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -677,9 +679,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -1305,6 +1309,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -1430,9 +1436,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/AnalyticsCollection/Builds/Android/app/src/main/java/com/yourcompany/analyticscollection/SharingContentProvider.java b/examples/AnalyticsCollection/Builds/Android/app/src/main/java/com/yourcompany/analyticscollection/SharingContentProvider.java
new file mode 100644
index 0000000000..709001a997
--- /dev/null
+++ b/examples/AnalyticsCollection/Builds/Android/app/src/main/java/com/yourcompany/analyticscollection/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.yourcompany.analyticscollection;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj b/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj
index 87072634d2..87938bca4d 100644
--- a/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj
+++ b/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj
@@ -902,6 +902,9 @@
true
+
+ true
+
true
@@ -1070,6 +1073,9 @@
true
+
+ true
+
true
@@ -1079,6 +1085,9 @@
true
+
+ true
+
true
@@ -1474,6 +1483,7 @@
+
diff --git a/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters b/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters
index 194bc0d771..1f01761550 100644
--- a/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters
+++ b/examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters
@@ -997,6 +997,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1165,6 +1168,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1174,6 +1180,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2118,6 +2127,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj b/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj
index d17c8ec8ef..106cc9f755 100644
--- a/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj
+++ b/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj
@@ -1284,6 +1284,9 @@
true
+
+ true
+
true
@@ -1452,6 +1455,9 @@
true
+
+ true
+
true
@@ -1461,6 +1467,9 @@
true
+
+ true
+
true
@@ -2167,6 +2176,7 @@
+
diff --git a/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj.filters b/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj.filters
index a68694ac84..5a8515d8c1 100644
--- a/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj.filters
+++ b/examples/AnimationAppExample/Builds/VisualStudio2017/AnimationAppExample_App.vcxproj.filters
@@ -1555,6 +1555,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1723,6 +1726,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1732,6 +1738,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3378,6 +3387,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj b/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj
index 3d4d1c68c4..b9f54db205 100644
--- a/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj
+++ b/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj
@@ -1332,6 +1332,9 @@
true
+
+ true
+
true
@@ -1500,6 +1503,9 @@
true
+
+ true
+
true
@@ -1509,6 +1515,9 @@
true
+
+ true
+
true
@@ -2229,6 +2238,7 @@
+
diff --git a/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj.filters b/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj.filters
index 36fae264b7..8f9a1f3238 100644
--- a/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj.filters
+++ b/examples/AudioAppExample/Builds/VisualStudio2017/AudioAppExample_App.vcxproj.filters
@@ -1633,6 +1633,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1801,6 +1804,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1810,6 +1816,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3498,6 +3507,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj
index 7a42343f95..fd2879c2d1 100644
--- a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj
+++ b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj
@@ -1329,6 +1329,9 @@
true
+
+ true
+
true
@@ -1497,6 +1500,9 @@
true
+
+ true
+
true
@@ -1506,6 +1512,9 @@
true
+
+ true
+
true
@@ -2234,6 +2243,7 @@
+
diff --git a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj.filters b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj.filters
index 75348682ee..e0290cb489 100644
--- a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2015/BlocksDrawing_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3528,6 +3537,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj
index 7935e26b8e..492ab2ac0d 100644
--- a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj
+++ b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj
@@ -1329,6 +1329,9 @@
true
+
+ true
+
true
@@ -1497,6 +1500,9 @@
true
+
+ true
+
true
@@ -1506,6 +1512,9 @@
true
+
+ true
+
true
@@ -2234,6 +2243,7 @@
+
diff --git a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj.filters b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj.filters
index bfeb4c5394..919678de0e 100644
--- a/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksDrawing/Builds/VisualStudio2017/BlocksDrawing_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3528,6 +3537,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj
index e5bea57ae0..89552bd0bc 100644
--- a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj
+++ b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj
@@ -1328,6 +1328,9 @@
true
+
+ true
+
true
@@ -1496,6 +1499,9 @@
true
+
+ true
+
true
@@ -1505,6 +1511,9 @@
true
+
+ true
+
true
@@ -2233,6 +2242,7 @@
+
diff --git a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj.filters b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj.filters
index b8ac687583..8f8cb65df4 100644
--- a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2015/BlocksMonitor_App.vcxproj.filters
@@ -1621,6 +1621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1789,6 +1792,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1798,6 +1804,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3525,6 +3534,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj
index d4a2c7fc51..9cb998670b 100644
--- a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj
+++ b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj
@@ -1328,6 +1328,9 @@
true
+
+ true
+
true
@@ -1496,6 +1499,9 @@
true
+
+ true
+
true
@@ -1505,6 +1511,9 @@
true
+
+ true
+
true
@@ -2233,6 +2242,7 @@
+
diff --git a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj.filters b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj.filters
index d2121d4ab4..a53c020b8a 100644
--- a/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksMonitor/Builds/VisualStudio2017/BlocksMonitor_App.vcxproj.filters
@@ -1621,6 +1621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1789,6 +1792,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1798,6 +1804,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3525,6 +3534,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj
index b01517fead..a16cef39b5 100644
--- a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj
+++ b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj
@@ -1328,6 +1328,9 @@
true
+
+ true
+
true
@@ -1496,6 +1499,9 @@
true
+
+ true
+
true
@@ -1505,6 +1511,9 @@
true
+
+ true
+
true
@@ -2235,6 +2244,7 @@
+
diff --git a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj.filters b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj.filters
index d1773923e6..ab469989fe 100644
--- a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2015/BlocksSynth_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3534,6 +3543,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj
index f4c071ca44..d407904064 100644
--- a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj
+++ b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj
@@ -1328,6 +1328,9 @@
true
+
+ true
+
true
@@ -1496,6 +1499,9 @@
true
+
+ true
+
true
@@ -1505,6 +1511,9 @@
true
+
+ true
+
true
@@ -2235,6 +2244,7 @@
+
diff --git a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj.filters b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj.filters
index d032033814..910fb73af8 100644
--- a/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj.filters
+++ b/examples/BLOCKS/BlocksSynth/Builds/VisualStudio2017/BlocksSynth_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3534,6 +3543,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj
index 0c18b15383..807e58f33b 100644
--- a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj
+++ b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj
@@ -1332,6 +1332,9 @@
true
+
+ true
+
true
@@ -1500,6 +1503,9 @@
true
+
+ true
+
true
@@ -1509,6 +1515,9 @@
true
+
+ true
+
true
@@ -2198,6 +2207,7 @@
+
diff --git a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj.filters b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj.filters
index 47cbb34974..d3461fff0f 100644
--- a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj.filters
+++ b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2013/BouncingBallWavetableDemo_App.vcxproj.filters
@@ -1618,6 +1618,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1786,6 +1789,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1795,6 +1801,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3447,6 +3456,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj
index c337223d3a..1a227839a6 100644
--- a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj
+++ b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj
@@ -1332,6 +1332,9 @@
true
+
+ true
+
true
@@ -1500,6 +1503,9 @@
true
+
+ true
+
true
@@ -1509,6 +1515,9 @@
true
+
+ true
+
true
@@ -2198,6 +2207,7 @@
+
diff --git a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj.filters b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj.filters
index ae0f5ce0d0..ab33835429 100644
--- a/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj.filters
+++ b/examples/BouncingBallWavetableDemo/Builds/VisualStudio2017/BouncingBallWavetableDemo_App.vcxproj.filters
@@ -1618,6 +1618,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1786,6 +1789,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1795,6 +1801,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3447,6 +3456,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj b/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj
index 8bfd13bcc0..8b65e8eac0 100644
--- a/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj
+++ b/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj
@@ -891,6 +891,9 @@
true
+
+ true
+
true
@@ -1059,6 +1062,9 @@
true
+
+ true
+
true
@@ -1068,6 +1074,9 @@
true
+
+ true
+
true
@@ -1546,6 +1555,7 @@
+
diff --git a/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj.filters b/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj.filters
index b6f8c261c5..958d14cd99 100644
--- a/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj.filters
+++ b/examples/ComponentTutorialExample/Builds/VisualStudio2015/ComponentTutorialExample_App.vcxproj.filters
@@ -997,6 +997,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1165,6 +1168,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1174,6 +1180,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2208,6 +2217,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj b/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj
index ccea2b19e5..9fd9aeb8b8 100644
--- a/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj
+++ b/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj
@@ -891,6 +891,9 @@
true
+
+ true
+
true
@@ -1059,6 +1062,9 @@
true
+
+ true
+
true
@@ -1068,6 +1074,9 @@
true
+
+ true
+
true
@@ -1546,6 +1555,7 @@
+
diff --git a/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj.filters b/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj.filters
index d0651a538d..a02b2a5ec6 100644
--- a/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj.filters
+++ b/examples/ComponentTutorialExample/Builds/VisualStudio2017/ComponentTutorialExample_App.vcxproj.filters
@@ -997,6 +997,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1165,6 +1168,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1174,6 +1180,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2208,6 +2217,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj b/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj
index 7312be5c8c..c7099555b7 100644
--- a/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj
+++ b/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj
@@ -1440,6 +1440,9 @@
true
+
+ true
+
true
@@ -1608,6 +1611,9 @@
true
+
+ true
+
true
@@ -1617,6 +1623,9 @@
true
+
+ true
+
true
@@ -2401,6 +2410,7 @@
+
diff --git a/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj.filters b/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj.filters
index 9d9791e739..dedf66a561 100644
--- a/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj.filters
+++ b/examples/DSP module plugin demo/Builds/VisualStudio2015/DSPModulePluginDemo_SharedCode.vcxproj.filters
@@ -1768,6 +1768,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1936,6 +1939,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1945,6 +1951,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3840,6 +3849,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj b/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj
index 4e4b25e1ef..7169ccae16 100644
--- a/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj
+++ b/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj
@@ -1441,6 +1441,9 @@
true
+
+ true
+
true
@@ -1609,6 +1612,9 @@
true
+
+ true
+
true
@@ -1618,6 +1624,9 @@
true
+
+ true
+
true
@@ -2402,6 +2411,7 @@
+
diff --git a/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj.filters b/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj.filters
index 6ee726f7e5..51f585c20a 100644
--- a/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj.filters
+++ b/examples/DSP module plugin demo/Builds/VisualStudio2017/DSPModulePluginDemo_SharedCode.vcxproj.filters
@@ -1768,6 +1768,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1936,6 +1939,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1945,6 +1951,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3840,6 +3849,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj b/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj
index 9086ec4d80..9fa83012c5 100644
--- a/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj
+++ b/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj
@@ -1377,6 +1377,9 @@
true
+
+ true
+
true
@@ -1545,6 +1548,9 @@
true
+
+ true
+
true
@@ -1554,6 +1560,9 @@
true
+
+ true
+
true
@@ -2261,6 +2270,7 @@
+
diff --git a/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj.filters b/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj.filters
index 37d6fcc929..2db4042d33 100644
--- a/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj.filters
+++ b/examples/DSPDemo/Builds/VisualStudio2017/DSPDemo_App.vcxproj.filters
@@ -1687,6 +1687,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1855,6 +1858,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1864,6 +1870,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3585,6 +3594,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/DSPDemo/JuceLibraryCode/BinaryData.cpp b/examples/DSPDemo/JuceLibraryCode/BinaryData.cpp
index 83708c82d6..ae4d7cf2de 100644
--- a/examples/DSPDemo/JuceLibraryCode/BinaryData.cpp
+++ b/examples/DSPDemo/JuceLibraryCode/BinaryData.cpp
@@ -1909,13 +1909,13 @@ static const unsigned char temp_binary_data_7[] =
" {\r\n"
" // No Approximation\r\n"
" {[] (float x) { return std::sin (x); }}, // sine\r\n"
-" {[] (float x) { return x / float_Pi; }}, // saw\r\n"
+" {[] (float x) { return x / MathConstants::pi; }}, // saw\r\n"
" {[] (float x) { return x < 0.0f ? -1.0f : 1.0f; }}, // square\r\n"
"\r\n"
" // Approximated by a wave-table\r\n"
-" {[] (float x) { return std::sin (x); }, 100}, // sine\r\n"
-" {[] (float x) { return x / float_Pi; }, 100}, // saw\r\n"
-" {[] (float x) { return x < 0.0f ? -1.0f : 1.0f; }, 100} // square\r\n"
+" {[] (float x) { return std::sin (x); }, 100}, // sine\r\n"
+" {[] (float x) { return x / MathConstants::pi; }, 100}, // saw\r\n"
+" {[] (float x) { return x < 0.0f ? -1.0f : 1.0f; }, 100} // square\r\n"
" };\r\n"
"\r\n"
" int currentOscillatorIdx = 0;\r\n"
@@ -2329,7 +2329,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw
case 0x14aa0aae: numBytes = 2674; return FIRFilterDemo_cpp;
case 0xab621a06: numBytes = 1809; return GainDemo_cpp;
case 0x06a7a4b1: numBytes = 2819; return IIRFilterDemo_cpp;
- case 0x6fc33e27: numBytes = 3974; return OscillatorDemo_cpp;
+ case 0x6fc33e27: numBytes = 3986; return OscillatorDemo_cpp;
case 0xdfdc547d: numBytes = 3039; return OverdriveDemo_cpp;
case 0x3f21e597: numBytes = 4849; return SIMDRegisterDemo_cpp;
case 0x54e9f84c: numBytes = 2718; return StateVariableFilterDemo_cpp;
diff --git a/examples/DSPDemo/JuceLibraryCode/BinaryData.h b/examples/DSPDemo/JuceLibraryCode/BinaryData.h
index fe5ad62cfd..09d3f2ba07 100644
--- a/examples/DSPDemo/JuceLibraryCode/BinaryData.h
+++ b/examples/DSPDemo/JuceLibraryCode/BinaryData.h
@@ -30,7 +30,7 @@ namespace BinaryData
const int IIRFilterDemo_cppSize = 2819;
extern const char* OscillatorDemo_cpp;
- const int OscillatorDemo_cppSize = 3974;
+ const int OscillatorDemo_cppSize = 3986;
extern const char* OverdriveDemo_cpp;
const int OverdriveDemo_cppSize = 3039;
diff --git a/examples/Demo/Builds/Android/app/CMakeLists.txt b/examples/Demo/Builds/Android/app/CMakeLists.txt
index 25a55143c6..4a4a8bfca6 100644
--- a/examples/Demo/Builds/Android/app/CMakeLists.txt
+++ b/examples/Demo/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_jucedemo_JuceDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/jucedemo/JuceDemo\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=3.0.0" "-DJUCE_APP_VERSION_HEX=0x30000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_roli_jucedemo_JuceDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/roli/jucedemo/JuceDemo\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_roli_jucedemo_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/roli/jucedemo/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=3.0.0" "-DJUCE_APP_VERSION_HEX=0x30000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -1051,6 +1051,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1176,9 +1178,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2379,6 +2383,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2504,9 +2510,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/Demo/Builds/Android/app/src/main/AndroidManifest.xml b/examples/Demo/Builds/Android/app/src/main/AndroidManifest.xml
index 5d5e2b52ba..62ef01f96f 100644
--- a/examples/Demo/Builds/Android/app/src/main/AndroidManifest.xml
+++ b/examples/Demo/Builds/Android/app/src/main/AndroidManifest.xml
@@ -1,7 +1,7 @@
+ package="com.roli.jucedemo">
@@ -20,5 +20,7 @@
+
diff --git a/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/JuceDemo.java b/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/JuceDemo.java
new file mode 100644
index 0000000000..b1e4d94ad2
--- /dev/null
+++ b/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/JuceDemo.java
@@ -0,0 +1,1688 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ The code included in this file is provided under the terms of the ISC license
+ http://www.isc.org/downloads/software-support-policy/isc-license. Permission
+ To use, copy, modify, and/or distribute this software for any purpose with or
+ without fee is hereby granted provided that the above copyright notice and
+ this permission notice appear in all copies.
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+package com.roli.jucedemo;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.http.SslError;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelUuid;
+import android.os.Environment;
+import android.view.*;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.graphics.*;
+import android.text.ClipboardManager;
+import android.text.InputType;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Pair;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import java.lang.Runnable;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.*;
+import java.util.*;
+import java.io.*;
+import java.net.URL;
+import java.net.HttpURLConnection;
+import android.media.AudioManager;
+import android.Manifest;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.Future;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.*;
+
+
+
+//==============================================================================
+public class JuceDemo extends Activity
+{
+ //==============================================================================
+ static
+ {
+ System.loadLibrary ("juce_jni");
+ }
+
+ //==============================================================================
+ public boolean isPermissionDeclaredInManifest (int permissionID)
+ {
+ String permissionToCheck = getAndroidPermissionName(permissionID);
+
+ try
+ {
+ PackageInfo info = getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS);
+
+ if (info.requestedPermissions != null)
+ for (String permission : info.requestedPermissions)
+ if (permission.equals (permissionToCheck))
+ return true;
+ }
+ catch (PackageManager.NameNotFoundException e)
+ {
+ Log.d ("JUCE", "isPermissionDeclaredInManifest: PackageManager.NameNotFoundException = " + e.toString());
+ }
+
+ Log.d ("JUCE", "isPermissionDeclaredInManifest: could not find requested permission " + permissionToCheck);
+ return false;
+ }
+
+ //==============================================================================
+ // these have to match the values of enum PermissionID in C++ class RuntimePermissions:
+ private static final int JUCE_PERMISSIONS_RECORD_AUDIO = 1;
+ private static final int JUCE_PERMISSIONS_BLUETOOTH_MIDI = 2;
+ private static final int JUCE_PERMISSIONS_READ_EXTERNAL_STORAGE = 3;
+ private static final int JUCE_PERMISSIONS_WRITE_EXTERNAL_STORAGE = 4;
+
+ private static String getAndroidPermissionName (int permissionID)
+ {
+ switch (permissionID)
+ {
+ case JUCE_PERMISSIONS_RECORD_AUDIO: return Manifest.permission.RECORD_AUDIO;
+ case JUCE_PERMISSIONS_BLUETOOTH_MIDI: return Manifest.permission.ACCESS_COARSE_LOCATION;
+ // use string value as this is not defined in SDKs < 16
+ case JUCE_PERMISSIONS_READ_EXTERNAL_STORAGE: return "android.permission.READ_EXTERNAL_STORAGE";
+ case JUCE_PERMISSIONS_WRITE_EXTERNAL_STORAGE: return Manifest.permission.WRITE_EXTERNAL_STORAGE;
+ }
+
+ // unknown permission ID!
+ assert false;
+ return new String();
+ }
+
+ public boolean isPermissionGranted (int permissionID)
+ {
+ return getApplicationContext().checkCallingOrSelfPermission (getAndroidPermissionName (permissionID)) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private Map permissionCallbackPtrMap;
+
+ public void requestRuntimePermission (int permissionID, long ptrToCallback)
+ {
+ String permissionName = getAndroidPermissionName (permissionID);
+
+ if (getApplicationContext().checkCallingOrSelfPermission (permissionName) != PackageManager.PERMISSION_GRANTED)
+ {
+ // remember callbackPtr, request permissions, and let onRequestPermissionResult call callback asynchronously
+ permissionCallbackPtrMap.put (permissionID, ptrToCallback);
+ requestPermissionsCompat (new String[]{permissionName}, permissionID);
+ }
+ else
+ {
+ // permissions were already granted before, we can call callback directly
+ androidRuntimePermissionsCallback (true, ptrToCallback);
+ }
+ }
+
+ private native void androidRuntimePermissionsCallback (boolean permissionWasGranted, long ptrToCallback);
+
+
+ //==============================================================================
+ public interface JuceMidiPort
+ {
+ boolean isInputPort();
+
+ // start, stop does nothing on an output port
+ void start();
+ void stop();
+
+ void close();
+
+ // send will do nothing on an input port
+ void sendMidi (byte[] msg, int offset, int count);
+ }
+
+ //==============================================================================
+ //==============================================================================
+ public class BluetoothManager
+ {
+ BluetoothManager()
+ {
+ }
+
+ public String[] getMidiBluetoothAddresses()
+ {
+ String[] bluetoothAddresses = new String[0];
+ return bluetoothAddresses;
+ }
+
+ public String getHumanReadableStringForBluetoothAddress (String address)
+ {
+ return address;
+ }
+
+ public int getBluetoothDeviceStatus (String address)
+ {
+ return 0;
+ }
+
+ public void startStopScan (boolean shouldStart)
+ {
+ }
+
+ public boolean pairBluetoothMidiDevice(String address)
+ {
+ return false;
+ }
+
+ public void unpairBluetoothMidiDevice (String address)
+ {
+ }
+ }
+
+ //==============================================================================
+ public class MidiDeviceManager
+ {
+ public MidiDeviceManager()
+ {
+ }
+
+ public String[] getJuceAndroidMidiInputDevices()
+ {
+ return new String[0];
+ }
+
+ public String[] getJuceAndroidMidiOutputDevices()
+ {
+ return new String[0];
+ }
+
+ public JuceMidiPort openMidiInputPortWithJuceIndex (int index, long host)
+ {
+ return null;
+ }
+
+ public JuceMidiPort openMidiOutputPortWithJuceIndex (int index)
+ {
+ return null;
+ }
+
+ public String getInputPortNameForJuceIndex (int index)
+ {
+ return "";
+ }
+
+ public String getOutputPortNameForJuceIndex (int index)
+ {
+ return "";
+ }
+ }
+
+
+ public MidiDeviceManager getAndroidMidiDeviceManager()
+ {
+ return null;
+ }
+
+ public BluetoothManager getAndroidBluetoothManager()
+ {
+ return null;
+ }
+
+ //==============================================================================
+ @Override
+ public void onCreate (Bundle savedInstanceState)
+ {
+ super.onCreate (savedInstanceState);
+
+ isScreenSaverEnabled = true;
+ hideActionBar();
+ viewHolder = new ViewHolder (this);
+ setContentView (viewHolder);
+
+ setVolumeControlStream (AudioManager.STREAM_MUSIC);
+
+ permissionCallbackPtrMap = new HashMap();
+ }
+
+ @Override
+ protected void onDestroy()
+ {
+ quitApp();
+ super.onDestroy();
+
+ clearDataCache();
+ }
+
+ @Override
+ protected void onPause()
+ {
+ suspendApp();
+
+ try
+ {
+ Thread.sleep (1000); // This is a bit of a hack to avoid some hard-to-track-down
+ // openGL glitches when pausing/resuming apps..
+ } catch (InterruptedException e) {}
+
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume()
+ {
+ super.onResume();
+ resumeApp();
+ }
+
+ @Override
+ public void onConfigurationChanged (Configuration cfg)
+ {
+ super.onConfigurationChanged (cfg);
+ setContentView (viewHolder);
+ }
+
+ private void callAppLauncher()
+ {
+ launchApp (getApplicationInfo().publicSourceDir,
+ getApplicationInfo().dataDir);
+ }
+
+ //==============================================================================
+ private void hideActionBar()
+ {
+ // get "getActionBar" method
+ java.lang.reflect.Method getActionBarMethod = null;
+ try
+ {
+ getActionBarMethod = this.getClass().getMethod ("getActionBar");
+ }
+ catch (SecurityException e) { return; }
+ catch (NoSuchMethodException e) { return; }
+ if (getActionBarMethod == null) return;
+
+ // invoke "getActionBar" method
+ Object actionBar = null;
+ try
+ {
+ actionBar = getActionBarMethod.invoke (this);
+ }
+ catch (java.lang.IllegalArgumentException e) { return; }
+ catch (java.lang.IllegalAccessException e) { return; }
+ catch (java.lang.reflect.InvocationTargetException e) { return; }
+ if (actionBar == null) return;
+
+ // get "hide" method
+ java.lang.reflect.Method actionBarHideMethod = null;
+ try
+ {
+ actionBarHideMethod = actionBar.getClass().getMethod ("hide");
+ }
+ catch (SecurityException e) { return; }
+ catch (NoSuchMethodException e) { return; }
+ if (actionBarHideMethod == null) return;
+
+ // invoke "hide" method
+ try
+ {
+ actionBarHideMethod.invoke (actionBar);
+ }
+ catch (java.lang.IllegalArgumentException e) {}
+ catch (java.lang.IllegalAccessException e) {}
+ catch (java.lang.reflect.InvocationTargetException e) {}
+ }
+
+ void requestPermissionsCompat (String[] permissions, int requestCode)
+ {
+ Method requestPermissionsMethod = null;
+ try
+ {
+ requestPermissionsMethod = this.getClass().getMethod ("requestPermissions",
+ String[].class, int.class);
+ }
+ catch (SecurityException e) { return; }
+ catch (NoSuchMethodException e) { return; }
+ if (requestPermissionsMethod == null) return;
+
+ try
+ {
+ requestPermissionsMethod.invoke (this, permissions, requestCode);
+ }
+ catch (java.lang.IllegalArgumentException e) {}
+ catch (java.lang.IllegalAccessException e) {}
+ catch (java.lang.reflect.InvocationTargetException e) {}
+ }
+
+ //==============================================================================
+ private native void launchApp (String appFile, String appDataDir);
+ private native void quitApp();
+ private native void suspendApp();
+ private native void resumeApp();
+ private native void setScreenSize (int screenWidth, int screenHeight, int dpi);
+ private native void appActivityResult (int requestCode, int resultCode, Intent data);
+ private native void appNewIntent (Intent intent);
+
+ //==============================================================================
+ private ViewHolder viewHolder;
+ private MidiDeviceManager midiDeviceManager = null;
+ private BluetoothManager bluetoothManager = null;
+ private boolean isScreenSaverEnabled;
+ private java.util.Timer keepAliveTimer;
+
+ public final ComponentPeerView createNewView (boolean opaque, long host)
+ {
+ ComponentPeerView v = new ComponentPeerView (this, opaque, host);
+ viewHolder.addView (v);
+ return v;
+ }
+
+ public final void deleteView (ComponentPeerView view)
+ {
+ view.host = 0;
+
+ ViewGroup group = (ViewGroup) (view.getParent());
+
+ if (group != null)
+ group.removeView (view);
+ }
+
+ public final void deleteNativeSurfaceView (NativeSurfaceView view)
+ {
+ ViewGroup group = (ViewGroup) (view.getParent());
+
+ if (group != null)
+ group.removeView (view);
+ }
+
+ final class ViewHolder extends ViewGroup
+ {
+ public ViewHolder (Context context)
+ {
+ super (context);
+ setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ setFocusable (false);
+ }
+
+ protected final void onLayout (boolean changed, int left, int top, int right, int bottom)
+ {
+ setScreenSize (getWidth(), getHeight(), getDPI());
+
+ if (isFirstResize)
+ {
+ isFirstResize = false;
+ callAppLauncher();
+ }
+ }
+
+ private final int getDPI()
+ {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics (metrics);
+ return metrics.densityDpi;
+ }
+
+ private boolean isFirstResize = true;
+ }
+
+ public final void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom)
+ {
+ canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE);
+ }
+
+ //==============================================================================
+ public final void setScreenSaver (boolean enabled)
+ {
+ if (isScreenSaverEnabled != enabled)
+ {
+ isScreenSaverEnabled = enabled;
+
+ if (keepAliveTimer != null)
+ {
+ keepAliveTimer.cancel();
+ keepAliveTimer = null;
+ }
+
+ if (enabled)
+ {
+ getWindow().clearFlags (WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+ else
+ {
+ getWindow().addFlags (WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ // If no user input is received after about 3 seconds, the OS will lower the
+ // task's priority, so this timer forces it to be kept active.
+ keepAliveTimer = new java.util.Timer();
+
+ keepAliveTimer.scheduleAtFixedRate (new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ android.app.Instrumentation instrumentation = new android.app.Instrumentation();
+
+ try
+ {
+ instrumentation.sendKeyDownUpSync (KeyEvent.KEYCODE_UNKNOWN);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ }, 2000, 2000);
+ }
+ }
+ }
+
+ public final boolean getScreenSaver()
+ {
+ return isScreenSaverEnabled;
+ }
+
+ //==============================================================================
+ public final String getClipboardContent()
+ {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
+ return clipboard.getText().toString();
+ }
+
+ public final void setClipboardContent (String newText)
+ {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE);
+ clipboard.setText (newText);
+ }
+
+ //==============================================================================
+ public final void showMessageBox (String title, String message, final long callback)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setOnCancelListener (new DialogInterface.OnCancelListener()
+ {
+ public void onCancel (DialogInterface dialog)
+ {
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ })
+ .setPositiveButton ("OK", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public final void showOkCancelBox (String title, String message, final long callback,
+ String okButtonText, String cancelButtonText)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setOnCancelListener (new DialogInterface.OnCancelListener()
+ {
+ public void onCancel (DialogInterface dialog)
+ {
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ })
+ .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 1);
+ }
+ })
+ .setNegativeButton (cancelButtonText.isEmpty() ? "Cancel" : cancelButtonText, new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public final void showYesNoCancelBox (String title, String message, final long callback)
+ {
+ AlertDialog.Builder builder = new AlertDialog.Builder (this);
+ builder.setTitle (title)
+ .setMessage (message)
+ .setCancelable (true)
+ .setOnCancelListener (new DialogInterface.OnCancelListener()
+ {
+ public void onCancel (DialogInterface dialog)
+ {
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ })
+ .setPositiveButton ("Yes", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 1);
+ }
+ })
+ .setNegativeButton ("No", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 2);
+ }
+ })
+ .setNeutralButton ("Cancel", new DialogInterface.OnClickListener()
+ {
+ public void onClick (DialogInterface dialog, int id)
+ {
+ dialog.dismiss();
+ JuceDemo.this.alertDismissed (callback, 0);
+ }
+ });
+
+ builder.create().show();
+ }
+
+ public native void alertDismissed (long callback, int id);
+
+ //==============================================================================
+ public final class ComponentPeerView extends ViewGroup
+ implements View.OnFocusChangeListener
+ {
+ public ComponentPeerView (Context context, boolean opaque_, long host)
+ {
+ super (context);
+ this.host = host;
+ setWillNotDraw (false);
+ opaque = opaque_;
+
+ setFocusable (true);
+ setFocusableInTouchMode (true);
+ setOnFocusChangeListener (this);
+
+ // swap red and blue colours to match internal opengl texture format
+ ColorMatrix colorMatrix = new ColorMatrix();
+
+ float[] colorTransform = { 0, 0, 1.0f, 0, 0,
+ 0, 1.0f, 0, 0, 0,
+ 1.0f, 0, 0, 0, 0,
+ 0, 0, 0, 1.0f, 0 };
+
+ colorMatrix.set (colorTransform);
+ paint.setColorFilter (new ColorMatrixColorFilter (colorMatrix));
+
+ java.lang.reflect.Method method = null;
+
+ try
+ {
+ method = getClass().getMethod ("setLayerType", int.class, Paint.class);
+ }
+ catch (SecurityException e) {}
+ catch (NoSuchMethodException e) {}
+
+ if (method != null)
+ {
+ try
+ {
+ int layerTypeNone = 0;
+ method.invoke (this, layerTypeNone, null);
+ }
+ catch (java.lang.IllegalArgumentException e) {}
+ catch (java.lang.IllegalAccessException e) {}
+ catch (java.lang.reflect.InvocationTargetException e) {}
+ }
+ }
+
+ //==============================================================================
+ private native void handlePaint (long host, Canvas canvas, Paint paint);
+
+ @Override
+ public void onDraw (Canvas canvas)
+ {
+ if (host == 0)
+ return;
+
+ handlePaint (host, canvas, paint);
+ }
+
+ @Override
+ public boolean isOpaque()
+ {
+ return opaque;
+ }
+
+ private boolean opaque;
+ private long host;
+ private Paint paint = new Paint();
+
+ //==============================================================================
+ private native void handleMouseDown (long host, int index, float x, float y, long time);
+ private native void handleMouseDrag (long host, int index, float x, float y, long time);
+ private native void handleMouseUp (long host, int index, float x, float y, long time);
+
+ @Override
+ public boolean onTouchEvent (MotionEvent event)
+ {
+ if (host == 0)
+ return false;
+
+ int action = event.getAction();
+ long time = event.getEventTime();
+
+ switch (action & MotionEvent.ACTION_MASK)
+ {
+ case MotionEvent.ACTION_DOWN:
+ handleMouseDown (host, event.getPointerId(0), event.getX(), event.getY(), time);
+ return true;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ handleMouseUp (host, event.getPointerId(0), event.getX(), event.getY(), time);
+ return true;
+
+ case MotionEvent.ACTION_MOVE:
+ {
+ int n = event.getPointerCount();
+ for (int i = 0; i < n; ++i)
+ handleMouseDrag (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+
+ return true;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP:
+ {
+ int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ handleMouseUp (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+ return true;
+ }
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ {
+ int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ handleMouseDown (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ //==============================================================================
+ private native void handleKeyDown (long host, int keycode, int textchar);
+ private native void handleKeyUp (long host, int keycode, int textchar);
+ private native void handleBackButton (long host);
+
+ public void showKeyboard (String type)
+ {
+ InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ {
+ if (type.length() > 0)
+ {
+ imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);
+ imm.setInputMethod (getWindowToken(), type);
+ }
+ else
+ {
+ imm.hideSoftInputFromWindow (getWindowToken(), 0);
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown (int keyCode, KeyEvent event)
+ {
+ if (host == 0)
+ return false;
+
+ switch (keyCode)
+ {
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ return super.onKeyDown (keyCode, event);
+ case KeyEvent.KEYCODE_BACK:
+ {
+ handleBackButton (host);
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ handleKeyDown (host, keyCode, event.getUnicodeChar());
+ return true;
+ }
+
+ @Override
+ public boolean onKeyUp (int keyCode, KeyEvent event)
+ {
+ if (host == 0)
+ return false;
+
+ handleKeyUp (host, keyCode, event.getUnicodeChar());
+ return true;
+ }
+
+ @Override
+ public boolean onKeyMultiple (int keyCode, int count, KeyEvent event)
+ {
+ if (host == 0)
+ return false;
+
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction() != KeyEvent.ACTION_MULTIPLE)
+ return super.onKeyMultiple (keyCode, count, event);
+
+ if (event.getCharacters() != null)
+ {
+ int utf8Char = event.getCharacters().codePointAt (0);
+ handleKeyDown (host, utf8Char, utf8Char);
+ return true;
+ }
+
+ return false;
+ }
+
+ // this is here to make keyboard entry work on a Galaxy Tab2 10.1
+ @Override
+ public InputConnection onCreateInputConnection (EditorInfo outAttrs)
+ {
+ outAttrs.actionLabel = "";
+ outAttrs.hintText = "";
+ outAttrs.initialCapsMode = 0;
+ outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
+ outAttrs.label = "";
+ outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI;
+ outAttrs.inputType = InputType.TYPE_NULL;
+
+ return new BaseInputConnection (this, false);
+ }
+
+ //==============================================================================
+ @Override
+ protected void onSizeChanged (int w, int h, int oldw, int oldh)
+ {
+ if (host == 0)
+ return;
+
+ super.onSizeChanged (w, h, oldw, oldh);
+ viewSizeChanged (host);
+ }
+
+ @Override
+ protected void onLayout (boolean changed, int left, int top, int right, int bottom)
+ {
+ for (int i = getChildCount(); --i >= 0;)
+ requestTransparentRegion (getChildAt (i));
+ }
+
+ private native void viewSizeChanged (long host);
+
+ @Override
+ public void onFocusChange (View v, boolean hasFocus)
+ {
+ if (host == 0)
+ return;
+
+ if (v == this)
+ focusChanged (host, hasFocus);
+ }
+
+ private native void focusChanged (long host, boolean hasFocus);
+
+ public void setViewName (String newName) {}
+
+ public void setSystemUiVisibilityCompat (int visibility)
+ {
+ Method systemUIVisibilityMethod = null;
+ try
+ {
+ systemUIVisibilityMethod = this.getClass().getMethod ("setSystemUiVisibility", int.class);
+ }
+ catch (SecurityException e) { return; }
+ catch (NoSuchMethodException e) { return; }
+ if (systemUIVisibilityMethod == null) return;
+
+ try
+ {
+ systemUIVisibilityMethod.invoke (this, visibility);
+ }
+ catch (java.lang.IllegalArgumentException e) {}
+ catch (java.lang.IllegalAccessException e) {}
+ catch (java.lang.reflect.InvocationTargetException e) {}
+ }
+
+ public boolean isVisible() { return getVisibility() == VISIBLE; }
+ public void setVisible (boolean b) { setVisibility (b ? VISIBLE : INVISIBLE); }
+
+ public boolean containsPoint (int x, int y)
+ {
+ return true; //xxx needs to check overlapping views
+ }
+ }
+
+ //==============================================================================
+ public static class NativeSurfaceView extends SurfaceView
+ implements SurfaceHolder.Callback
+ {
+ private long nativeContext = 0;
+
+ NativeSurfaceView (Context context, long nativeContextPtr)
+ {
+ super (context);
+ nativeContext = nativeContextPtr;
+ }
+
+ public Surface getNativeSurface()
+ {
+ Surface retval = null;
+
+ SurfaceHolder holder = getHolder();
+ if (holder != null)
+ retval = holder.getSurface();
+
+ return retval;
+ }
+
+ //==============================================================================
+ @Override
+ public void surfaceChanged (SurfaceHolder holder, int format, int width, int height)
+ {
+ surfaceChangedNative (nativeContext, holder, format, width, height);
+ }
+
+ @Override
+ public void surfaceCreated (SurfaceHolder holder)
+ {
+ surfaceCreatedNative (nativeContext, holder);
+ }
+
+ @Override
+ public void surfaceDestroyed (SurfaceHolder holder)
+ {
+ surfaceDestroyedNative (nativeContext, holder);
+ }
+
+ @Override
+ protected void dispatchDraw (Canvas canvas)
+ {
+ super.dispatchDraw (canvas);
+ dispatchDrawNative (nativeContext, canvas);
+ }
+
+ //==============================================================================
+ @Override
+ protected void onAttachedToWindow ()
+ {
+ super.onAttachedToWindow();
+ getHolder().addCallback (this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow ()
+ {
+ super.onDetachedFromWindow();
+ getHolder().removeCallback (this);
+ }
+
+ //==============================================================================
+ private native void dispatchDrawNative (long nativeContextPtr, Canvas canvas);
+ private native void surfaceCreatedNative (long nativeContextptr, SurfaceHolder holder);
+ private native void surfaceDestroyedNative (long nativeContextptr, SurfaceHolder holder);
+ private native void surfaceChangedNative (long nativeContextptr, SurfaceHolder holder,
+ int format, int width, int height);
+ }
+
+ public NativeSurfaceView createNativeSurfaceView (long nativeSurfacePtr)
+ {
+ return new NativeSurfaceView (this, nativeSurfacePtr);
+ }
+
+ //==============================================================================
+ public final int[] renderGlyph (char glyph1, char glyph2, Paint paint, android.graphics.Matrix matrix, Rect bounds)
+ {
+ Path p = new Path();
+
+ char[] str = { glyph1, glyph2 };
+ paint.getTextPath (str, 0, (glyph2 != 0 ? 2 : 1), 0.0f, 0.0f, p);
+
+ RectF boundsF = new RectF();
+ p.computeBounds (boundsF, true);
+ matrix.mapRect (boundsF);
+
+ boundsF.roundOut (bounds);
+ bounds.left--;
+ bounds.right++;
+
+ final int w = bounds.width();
+ final int h = Math.max (1, bounds.height());
+
+ Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888);
+
+ Canvas c = new Canvas (bm);
+ matrix.postTranslate (-bounds.left, -bounds.top);
+ c.setMatrix (matrix);
+ c.drawPath (p, paint);
+
+ final int sizeNeeded = w * h;
+ if (cachedRenderArray.length < sizeNeeded)
+ cachedRenderArray = new int [sizeNeeded];
+
+ bm.getPixels (cachedRenderArray, 0, w, 0, 0, w, h);
+ bm.recycle();
+ return cachedRenderArray;
+ }
+
+ private int[] cachedRenderArray = new int [256];
+
+ //==============================================================================
+ public static class NativeInvocationHandler implements InvocationHandler
+ {
+ public NativeInvocationHandler (long nativeContextRef)
+ {
+ nativeContext = nativeContextRef;
+ }
+
+ @Override
+ public void finalize()
+ {
+ dispatchFinalize (nativeContext);
+ }
+
+ @Override
+ public Object invoke (Object proxy, Method method, Object[] args) throws Throwable
+ {
+ return dispatchInvoke (nativeContext, proxy, method, args);
+ }
+
+ //==============================================================================
+ private long nativeContext = 0;
+
+ private native void dispatchFinalize (long nativeContextRef);
+ private native Object dispatchInvoke (long nativeContextRef, Object proxy, Method method, Object[] args);
+ }
+
+ public static InvocationHandler createInvocationHandler (long nativeContextRef)
+ {
+ return new NativeInvocationHandler (nativeContextRef);
+ }
+
+ //==============================================================================
+ public static class HTTPStream
+ {
+ public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse,
+ String headersToUse, int timeOutMsToUse,
+ int[] statusCodeToUse, StringBuffer responseHeadersToUse,
+ int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException
+ {
+ isPost = isPostToUse;
+ postData = postDataToUse;
+ headers = headersToUse;
+ timeOutMs = timeOutMsToUse;
+ statusCode = statusCodeToUse;
+ responseHeaders = responseHeadersToUse;
+ totalLength = -1;
+ numRedirectsToFollow = numRedirectsToFollowToUse;
+ httpRequestCmd = httpRequestCmdToUse;
+
+ connection = createConnection (address, isPost, postData, headers, timeOutMs, httpRequestCmd);
+ }
+
+ private final HttpURLConnection createConnection (String address, boolean isPost, byte[] postData,
+ String headers, int timeOutMs, String httpRequestCmdToUse) throws IOException
+ {
+ HttpURLConnection newConnection = (HttpURLConnection) (new URL(address).openConnection());
+
+ try
+ {
+ newConnection.setInstanceFollowRedirects (false);
+ newConnection.setConnectTimeout (timeOutMs);
+ newConnection.setReadTimeout (timeOutMs);
+
+ // headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines.
+ // So convert headers string to an array, with an element for each line
+ String headerLines[] = headers.split("\\n");
+
+ // Set request headers
+ for (int i = 0; i < headerLines.length; ++i)
+ {
+ int pos = headerLines[i].indexOf (":");
+
+ if (pos > 0 && pos < headerLines[i].length())
+ {
+ String field = headerLines[i].substring (0, pos);
+ String value = headerLines[i].substring (pos + 1);
+
+ if (value.length() > 0)
+ newConnection.setRequestProperty (field, value);
+ }
+ }
+
+ newConnection.setRequestMethod (httpRequestCmd);
+
+ if (isPost)
+ {
+ newConnection.setDoOutput (true);
+
+ if (postData != null)
+ {
+ OutputStream out = newConnection.getOutputStream();
+ out.write(postData);
+ out.flush();
+ }
+ }
+
+ return newConnection;
+ }
+ catch (Throwable e)
+ {
+ newConnection.disconnect();
+ throw new IOException ("Connection error");
+ }
+ }
+
+ private final InputStream getCancellableStream (final boolean isInput) throws ExecutionException
+ {
+ synchronized (createFutureLock)
+ {
+ if (hasBeenCancelled.get())
+ return null;
+
+ streamFuture = executor.submit (new Callable()
+ {
+ @Override
+ public BufferedInputStream call() throws IOException
+ {
+ return new BufferedInputStream (isInput ? connection.getInputStream()
+ : connection.getErrorStream());
+ }
+ });
+ }
+
+ try
+ {
+ return streamFuture.get();
+ }
+ catch (InterruptedException e)
+ {
+ return null;
+ }
+ catch (CancellationException e)
+ {
+ return null;
+ }
+ }
+
+ public final boolean connect()
+ {
+ boolean result = false;
+ int numFollowedRedirects = 0;
+
+ while (true)
+ {
+ result = doConnect();
+
+ if (! result)
+ return false;
+
+ if (++numFollowedRedirects > numRedirectsToFollow)
+ break;
+
+ int status = statusCode[0];
+
+ if (status == 301 || status == 302 || status == 303 || status == 307)
+ {
+ // Assumes only one occurrence of "Location"
+ int pos1 = responseHeaders.indexOf ("Location:") + 10;
+ int pos2 = responseHeaders.indexOf ("\n", pos1);
+
+ if (pos2 > pos1)
+ {
+ String currentLocation = connection.getURL().toString();
+ String newLocation = responseHeaders.substring (pos1, pos2);
+
+ try
+ {
+ // Handle newLocation whether it's absolute or relative
+ URL baseUrl = new URL (currentLocation);
+ URL newUrl = new URL (baseUrl, newLocation);
+ String transformedNewLocation = newUrl.toString();
+
+ if (transformedNewLocation != currentLocation)
+ {
+ // Clear responseHeaders before next iteration
+ responseHeaders.delete (0, responseHeaders.length());
+
+ synchronized (createStreamLock)
+ {
+ if (hasBeenCancelled.get())
+ return false;
+
+ connection.disconnect();
+
+ try
+ {
+ connection = createConnection (transformedNewLocation, isPost,
+ postData, headers, timeOutMs,
+ httpRequestCmd);
+ }
+ catch (Throwable e)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ catch (Throwable e)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ private final boolean doConnect()
+ {
+ synchronized (createStreamLock)
+ {
+ if (hasBeenCancelled.get())
+ return false;
+
+ try
+ {
+ try
+ {
+ inputStream = getCancellableStream (true);
+ }
+ catch (ExecutionException e)
+ {
+ if (connection.getResponseCode() < 400)
+ {
+ statusCode[0] = connection.getResponseCode();
+ connection.disconnect();
+ return false;
+ }
+ }
+ finally
+ {
+ statusCode[0] = connection.getResponseCode();
+ }
+
+ try
+ {
+ if (statusCode[0] >= 400)
+ inputStream = getCancellableStream (false);
+ else
+ inputStream = getCancellableStream (true);
+ }
+ catch (ExecutionException e)
+ {}
+
+ for (java.util.Map.Entry> entry : connection.getHeaderFields().entrySet())
+ {
+ if (entry.getKey() != null && entry.getValue() != null)
+ {
+ responseHeaders.append(entry.getKey() + ": "
+ + android.text.TextUtils.join(",", entry.getValue()) + "\n");
+
+ if (entry.getKey().compareTo ("Content-Length") == 0)
+ totalLength = Integer.decode (entry.getValue().get (0));
+ }
+ }
+
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+ }
+
+ static class DisconnectionRunnable implements Runnable
+ {
+ public DisconnectionRunnable (HttpURLConnection theConnection,
+ InputStream theInputStream,
+ ReentrantLock theCreateStreamLock,
+ Object theCreateFutureLock,
+ Future theStreamFuture)
+ {
+ connectionToDisconnect = theConnection;
+ inputStream = theInputStream;
+ createStreamLock = theCreateStreamLock;
+ createFutureLock = theCreateFutureLock;
+ streamFuture = theStreamFuture;
+ }
+
+ public void run()
+ {
+ try
+ {
+ if (! createStreamLock.tryLock())
+ {
+ synchronized (createFutureLock)
+ {
+ if (streamFuture != null)
+ streamFuture.cancel (true);
+ }
+
+ createStreamLock.lock();
+ }
+
+ if (connectionToDisconnect != null)
+ connectionToDisconnect.disconnect();
+
+ if (inputStream != null)
+ inputStream.close();
+ }
+ catch (IOException e)
+ {}
+ finally
+ {
+ createStreamLock.unlock();
+ }
+ }
+
+ private HttpURLConnection connectionToDisconnect;
+ private InputStream inputStream;
+ private ReentrantLock createStreamLock;
+ private Object createFutureLock;
+ Future streamFuture;
+ }
+
+ public final void release()
+ {
+ DisconnectionRunnable disconnectionRunnable = new DisconnectionRunnable (connection,
+ inputStream,
+ createStreamLock,
+ createFutureLock,
+ streamFuture);
+
+ synchronized (createStreamLock)
+ {
+ hasBeenCancelled.set (true);
+
+ connection = null;
+ }
+
+ Thread disconnectionThread = new Thread(disconnectionRunnable);
+ disconnectionThread.start();
+ }
+
+ public final int read (byte[] buffer, int numBytes)
+ {
+ int num = 0;
+
+ try
+ {
+ synchronized (createStreamLock)
+ {
+ if (inputStream != null)
+ num = inputStream.read (buffer, 0, numBytes);
+ }
+ }
+ catch (IOException e)
+ {}
+
+ if (num > 0)
+ position += num;
+
+ return num;
+ }
+
+ public final long getPosition() { return position; }
+ public final long getTotalLength() { return totalLength; }
+ public final boolean isExhausted() { return false; }
+ public final boolean setPosition (long newPos) { return false; }
+
+ private boolean isPost;
+ private byte[] postData;
+ private String headers;
+ private int timeOutMs;
+ String httpRequestCmd;
+ private HttpURLConnection connection;
+ private int[] statusCode;
+ private StringBuffer responseHeaders;
+ private int totalLength;
+ private int numRedirectsToFollow;
+ private InputStream inputStream;
+ private long position;
+ private final ReentrantLock createStreamLock = new ReentrantLock();
+ private final Object createFutureLock = new Object();
+ private AtomicBoolean hasBeenCancelled = new AtomicBoolean();
+
+ private final ExecutorService executor = Executors.newCachedThreadPool (Executors.defaultThreadFactory());
+ Future streamFuture;
+ }
+
+ public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
+ String headers, int timeOutMs, int[] statusCode,
+ StringBuffer responseHeaders, int numRedirectsToFollow,
+ String httpRequestCmd)
+ {
+ // timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL)
+ if (timeOutMs < 0)
+ timeOutMs = 0;
+ else if (timeOutMs == 0)
+ timeOutMs = 30000;
+
+ for (;;)
+ {
+ try
+ {
+ HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers,
+ timeOutMs, statusCode, responseHeaders,
+ numRedirectsToFollow, httpRequestCmd);
+
+ return httpStream;
+ }
+ catch (Throwable e) {}
+
+ return null;
+ }
+ }
+
+ public final void launchURL (String url)
+ {
+ startActivity (new Intent (Intent.ACTION_VIEW, Uri.parse (url)));
+ }
+
+ private native boolean webViewPageLoadStarted (long host, WebView view, String url);
+ private native void webViewPageLoadFinished (long host, WebView view, String url);
+ private native void webViewReceivedSslError (long host, WebView view, SslErrorHandler handler, SslError error);
+ private native void webViewCloseWindowRequest (long host, WebView view);
+ private native void webViewCreateWindowRequest (long host, WebView view);
+
+ //==============================================================================
+ public class JuceWebViewClient extends WebViewClient
+ {
+ public JuceWebViewClient (long hostToUse)
+ {
+ host = hostToUse;
+ }
+
+ public void hostDeleted()
+ {
+ synchronized (hostLock)
+ {
+ host = 0;
+ }
+ }
+
+ @Override
+ public void onPageFinished (WebView view, String url)
+ {
+ if (host == 0)
+ return;
+
+ webViewPageLoadFinished (host, view, url);
+ }
+
+ @Override
+ public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error)
+ {
+ if (host == 0)
+ return;
+
+ webViewReceivedSslError (host, view, handler, error);
+ }
+
+ @Override
+ public void onPageStarted (WebView view, String url, Bitmap favicon)
+ {
+ if (host != 0)
+ webViewPageLoadStarted (host, view, url);
+ }
+
+ private long host;
+ private final Object hostLock = new Object();
+ }
+
+ public class JuceWebChromeClient extends WebChromeClient
+ {
+ public JuceWebChromeClient (long hostToUse)
+ {
+ host = hostToUse;
+ }
+
+ @Override
+ public void onCloseWindow (WebView window)
+ {
+ webViewCloseWindowRequest (host, window);
+ }
+
+ @Override
+ public boolean onCreateWindow (WebView view, boolean isDialog,
+ boolean isUserGesture, Message resultMsg)
+ {
+ webViewCreateWindowRequest (host, view);
+ return false;
+ }
+
+ private long host;
+ private final Object hostLock = new Object();
+ }
+
+ //==============================================================================
+ public static final String getLocaleValue (boolean isRegion)
+ {
+ java.util.Locale locale = java.util.Locale.getDefault();
+
+ return isRegion ? locale.getCountry()
+ : locale.getLanguage();
+ }
+
+ private static final String getFileLocation (String type)
+ {
+ return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath();
+ }
+
+ public static final String getDocumentsFolder()
+ {
+ if (getAndroidSDKVersion() >= 19)
+ return getFileLocation ("Documents");
+
+ return Environment.getDataDirectory().getAbsolutePath();
+ }
+
+ public static final String getPicturesFolder() { return getFileLocation (Environment.DIRECTORY_PICTURES); }
+ public static final String getMusicFolder() { return getFileLocation (Environment.DIRECTORY_MUSIC); }
+ public static final String getMoviesFolder() { return getFileLocation (Environment.DIRECTORY_MOVIES); }
+ public static final String getDownloadsFolder() { return getFileLocation (Environment.DIRECTORY_DOWNLOADS); }
+
+ //==============================================================================
+ @Override
+ protected void onActivityResult (int requestCode, int resultCode, Intent data)
+ {
+ appActivityResult (requestCode, resultCode, data);
+ }
+
+ @Override
+ protected void onNewIntent (Intent intent)
+ {
+ super.onNewIntent(intent);
+ setIntent(intent);
+
+ appNewIntent (intent);
+ }
+
+ //==============================================================================
+ public final Typeface getTypeFaceFromAsset (String assetName)
+ {
+ try
+ {
+ return Typeface.createFromAsset (this.getResources().getAssets(), assetName);
+ }
+ catch (Throwable e) {}
+
+ return null;
+ }
+
+ final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+
+ public static String bytesToHex (byte[] bytes)
+ {
+ char[] hexChars = new char[bytes.length * 2];
+
+ for (int j = 0; j < bytes.length; ++j)
+ {
+ int v = bytes[j] & 0xff;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0f];
+ }
+
+ return new String (hexChars);
+ }
+
+ final private java.util.Map dataCache = new java.util.HashMap();
+
+ synchronized private final File getDataCacheFile (byte[] data)
+ {
+ try
+ {
+ java.security.MessageDigest digest = java.security.MessageDigest.getInstance ("MD5");
+ digest.update (data);
+
+ String key = bytesToHex (digest.digest());
+
+ if (dataCache.containsKey (key))
+ return (File) dataCache.get (key);
+
+ File f = new File (this.getCacheDir(), "bindata_" + key);
+ f.delete();
+ FileOutputStream os = new FileOutputStream (f);
+ os.write (data, 0, data.length);
+ dataCache.put (key, f);
+ return f;
+ }
+ catch (Throwable e) {}
+
+ return null;
+ }
+
+ private final void clearDataCache()
+ {
+ java.util.Iterator it = dataCache.values().iterator();
+
+ while (it.hasNext())
+ {
+ File f = (File) it.next();
+ f.delete();
+ }
+ }
+
+ public final Typeface getTypeFaceFromByteArray (byte[] data)
+ {
+ try
+ {
+ File f = getDataCacheFile (data);
+
+ if (f != null)
+ return Typeface.createFromFile (f);
+ }
+ catch (Exception e)
+ {
+ Log.e ("JUCE", e.toString());
+ }
+
+ return null;
+ }
+
+ public static final int getAndroidSDKVersion()
+ {
+ return android.os.Build.VERSION.SDK_INT;
+ }
+
+ public final String audioManagerGetProperty (String property)
+ {
+ Object obj = getSystemService (AUDIO_SERVICE);
+ if (obj == null)
+ return null;
+
+ java.lang.reflect.Method method;
+
+ try
+ {
+ method = obj.getClass().getMethod ("getProperty", String.class);
+ }
+ catch (SecurityException e) { return null; }
+ catch (NoSuchMethodException e) { return null; }
+
+ if (method == null)
+ return null;
+
+ try
+ {
+ return (String) method.invoke (obj, property);
+ }
+ catch (java.lang.IllegalArgumentException e) {}
+ catch (java.lang.IllegalAccessException e) {}
+ catch (java.lang.reflect.InvocationTargetException e) {}
+
+ return null;
+ }
+
+ public final boolean hasSystemFeature (String property)
+ {
+ return getPackageManager().hasSystemFeature (property);
+ }
+}
diff --git a/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/SharingContentProvider.java b/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/SharingContentProvider.java
new file mode 100644
index 0000000000..ea9cc88632
--- /dev/null
+++ b/examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.roli.jucedemo;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj b/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj
index 865206343d..854802c93b 100644
--- a/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj
+++ b/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj
@@ -1515,6 +1515,9 @@
true
+
+ true
+
true
@@ -1683,6 +1686,9 @@
true
+
+ true
+
true
@@ -1692,6 +1698,9 @@
true
+
+ true
+
true
@@ -2467,6 +2476,7 @@
+
diff --git a/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj.filters b/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj.filters
index eef740e126..e6d4c89c9b 100644
--- a/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj.filters
+++ b/examples/Demo/Builds/VisualStudio2013/JuceDemo_App.vcxproj.filters
@@ -1930,6 +1930,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -2098,6 +2101,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2107,6 +2113,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3960,6 +3969,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj b/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj
index 4f3b31a7e3..477d84abd8 100644
--- a/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj
+++ b/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj
@@ -1515,6 +1515,9 @@
true
+
+ true
+
true
@@ -1683,6 +1686,9 @@
true
+
+ true
+
true
@@ -1692,6 +1698,9 @@
true
+
+ true
+
true
@@ -2467,6 +2476,7 @@
+
diff --git a/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj.filters b/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj.filters
index 6e0939b321..736fde4d3b 100644
--- a/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj.filters
+++ b/examples/Demo/Builds/VisualStudio2015/JuceDemo_App.vcxproj.filters
@@ -1930,6 +1930,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -2098,6 +2101,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2107,6 +2113,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3960,6 +3969,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj b/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj
index c70e920172..518e19773b 100644
--- a/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj
+++ b/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj
@@ -1515,6 +1515,9 @@
true
+
+ true
+
true
@@ -1683,6 +1686,9 @@
true
+
+ true
+
true
@@ -1692,6 +1698,9 @@
true
+
+ true
+
true
@@ -2467,6 +2476,7 @@
+
diff --git a/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj.filters b/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj.filters
index 4ebb644a5b..389ab78257 100644
--- a/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj.filters
+++ b/examples/Demo/Builds/VisualStudio2017/JuceDemo_App.vcxproj.filters
@@ -1930,6 +1930,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -2098,6 +2101,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2107,6 +2113,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3960,6 +3969,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/Demo/JuceDemo.jucer b/examples/Demo/JuceDemo.jucer
index 81076fd380..a36ab04c2b 100644
--- a/examples/Demo/JuceDemo.jucer
+++ b/examples/Demo/JuceDemo.jucer
@@ -148,12 +148,13 @@
-
+ microphonePermissionNeeded="1" extraCompilerFlags="-pedantic -Wall -Wshadow -Wno-missing-field-initializers -Wshadow -Wshorten-64-to-32 -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wconversion -Wsign-compare -Wint-conversion -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wsign-conversion -Wextra-semi"
+ androidEnableContentSharing="1">
diff --git a/examples/Demo/Source/Demos/DialogsDemo.cpp b/examples/Demo/Source/Demos/DialogsDemo.cpp
index 18e6ab6de9..bfd834284c 100644
--- a/examples/Demo/Source/Demos/DialogsDemo.cpp
+++ b/examples/Demo/Source/Demos/DialogsDemo.cpp
@@ -106,6 +106,9 @@ public:
loadWithPreviewChooser,
directoryChooser,
saveChooser,
+ shareText,
+ shareFile,
+ shareImage,
numDialogs
};
@@ -130,7 +133,10 @@ public:
"'Load' File Browser",
"'Load' File Browser With Image Preview",
"'Choose Directory' File Browser",
- "'Save' File Browser"
+ "'Save' File Browser",
+ "Share Text",
+ "Share Files",
+ "Share Images"
};
// warn in case we add any windows
@@ -380,6 +386,68 @@ private:
});
}
}
+ else if (type == shareText)
+ {
+ ContentSharer::getInstance()->shareText ("I love JUCE!",
+ [] (bool success, const String& error)
+ {
+ String resultString = success ? "success" : ("failure\n (error: " + error + ")");
+
+ AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
+ "Sharing Text Result",
+ "Sharing text finished\nwith " + resultString);
+ });
+ }
+ else if (type == shareFile)
+ {
+ File fileToSave = File::createTempFile ("DialogsDemoSharingTest");
+
+ if (fileToSave.createDirectory().wasOk())
+ {
+ fileToSave = fileToSave.getChildFile ("SharingDemoFile.txt");
+ fileToSave.replaceWithText ("Make it fast!");
+
+ Array urls;
+ urls.add (URL (fileToSave));
+
+ ContentSharer::getInstance()->shareFiles (urls,
+ [] (bool success, const String& error)
+ {
+ String resultString = success ? "success" : ("failure\n (error: " + error + ")");
+
+ AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
+ "Sharing Files Result",
+ "Sharing files finished\nwith " + resultString);
+ });
+
+ }
+ }
+ else if (type == shareImage)
+ {
+ Image myImage = ImageCache::getFromMemory (BinaryData::juce_icon_png,
+ BinaryData::juce_icon_pngSize);
+
+ Image myImage2 (Image::RGB, 500, 500, true);
+ Graphics g (myImage2);
+ g.setColour (Colours::green);
+ ColourGradient gradient (Colours::yellow, 170, 170, Colours::cyan, 170, 20, true);
+ g.setGradientFill (gradient);
+ g.fillEllipse (20, 20, 300, 300);
+
+ Array images;
+ images.add (myImage);
+ images.add (myImage2);
+
+ ContentSharer::getInstance()->shareImages (images,
+ [] (bool success, const String& error)
+ {
+ String resultString = success ? "success" : ("failure\n (error: " + error + ")");
+
+ AlertWindow::showMessageBoxAsync (AlertWindow::InfoIcon,
+ "Sharing Images Result",
+ "Sharing images finished\nwith " + resultString);
+ });
+ }
}
void buttonClicked (Button* button) override
diff --git a/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj b/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj
index da74866b02..e45c7601aa 100644
--- a/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj
+++ b/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj
@@ -891,6 +891,9 @@
true
+
+ true
+
true
@@ -1059,6 +1062,9 @@
true
+
+ true
+
true
@@ -1068,6 +1074,9 @@
true
+
+ true
+
true
@@ -1544,6 +1553,7 @@
+
diff --git a/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj.filters b/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj.filters
index 6b3b514aa0..7cf9309362 100644
--- a/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj.filters
+++ b/examples/HelloWorld/Builds/VisualStudio2015/HelloWorld_App.vcxproj.filters
@@ -997,6 +997,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1165,6 +1168,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1174,6 +1180,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2202,6 +2211,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj b/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj
index edad529c8d..edd57148ff 100644
--- a/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj
+++ b/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj
@@ -891,6 +891,9 @@
true
+
+ true
+
true
@@ -1059,6 +1062,9 @@
true
+
+ true
+
true
@@ -1068,6 +1074,9 @@
true
+
+ true
+
true
@@ -1544,6 +1553,7 @@
+
diff --git a/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj.filters b/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj.filters
index d992122b5e..e5e8603810 100644
--- a/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj.filters
+++ b/examples/HelloWorld/Builds/VisualStudio2017/HelloWorld_App.vcxproj.filters
@@ -997,6 +997,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1165,6 +1168,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1174,6 +1180,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2202,6 +2211,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt b/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt
index 26f473ccc3..246eec4ea0 100644
--- a/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt
+++ b/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_roli_juceinapppurchasesample_InAppPurchase" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/roli/juceinapppurchasesample/InAppPurchase\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_IN_APP_PURCHASES=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=0.0.2" "-DJUCE_APP_VERSION_HEX=0x2")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_roli_juceinapppurchasesample_InAppPurchase" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/roli/juceinapppurchasesample/InAppPurchase\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_roli_juceinapppurchasesample_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/roli/juceinapppurchasesample/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_IN_APP_PURCHASES=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=0.0.2" "-DJUCE_APP_VERSION_HEX=0x2")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -926,6 +926,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1051,9 +1053,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2171,6 +2175,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2296,9 +2302,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/SharingContentProvider.java b/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/SharingContentProvider.java
new file mode 100644
index 0000000000..2108bb6976
--- /dev/null
+++ b/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.roli.juceinapppurchasesample;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj b/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj
index f4791c95f7..ab3bc3e210 100644
--- a/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj
+++ b/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj
@@ -1331,6 +1331,9 @@
true
+
+ true
+
true
@@ -1499,6 +1502,9 @@
true
+
+ true
+
true
@@ -1508,6 +1514,9 @@
true
+
+ true
+
true
@@ -2234,6 +2243,7 @@
+
diff --git a/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj.filters b/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj.filters
index 40fc1fcce4..e712cdfbd9 100644
--- a/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj.filters
+++ b/examples/MPETest/Builds/VisualStudio2015/MPETest_App.vcxproj.filters
@@ -1630,6 +1630,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1798,6 +1801,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1807,6 +1813,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3513,6 +3522,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj b/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj
index 2670460b5a..aea5fbb530 100644
--- a/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj
+++ b/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj
@@ -1331,6 +1331,9 @@
true
+
+ true
+
true
@@ -1499,6 +1502,9 @@
true
+
+ true
+
true
@@ -1508,6 +1514,9 @@
true
+
+ true
+
true
@@ -2234,6 +2243,7 @@
+
diff --git a/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj.filters b/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj.filters
index 5c2ba89af9..9d3791a10e 100644
--- a/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj.filters
+++ b/examples/MPETest/Builds/VisualStudio2017/MPETest_App.vcxproj.filters
@@ -1630,6 +1630,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1798,6 +1801,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1807,6 +1813,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3513,6 +3522,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/MidiTest/Builds/Android/app/CMakeLists.txt b/examples/MidiTest/Builds/Android/app/CMakeLists.txt
index 9aec4b729e..1912b1ce1e 100644
--- a/examples/MidiTest/Builds/Android/app/CMakeLists.txt
+++ b/examples/MidiTest/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_miditest_MidiTest" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/miditest/MidiTest\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_miditest_MidiTest" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/miditest/MidiTest\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_yourcompany_miditest_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/yourcompany/miditest/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -887,6 +887,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1012,9 +1014,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2040,6 +2044,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2165,9 +2171,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/SharingContentProvider.java b/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/SharingContentProvider.java
new file mode 100644
index 0000000000..3bbe1d1f72
--- /dev/null
+++ b/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/SharingContentProvider.java
@@ -0,0 +1,138 @@
+package com.yourcompany.miditest;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+ @Override
+ public String[] getStreamTypes (Uri uri, String mimeTypeFilter)
+ {
+ synchronized (lock)
+ {
+ return contentSharerGetStreamTypes (uri, mimeTypeFilter);
+ }
+ }
+
+}
diff --git a/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj b/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj
index 2e7e967a5b..5f997d4916 100644
--- a/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj
+++ b/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj
@@ -1311,6 +1311,9 @@
true
+
+ true
+
true
@@ -1479,6 +1482,9 @@
true
+
+ true
+
true
@@ -1488,6 +1494,9 @@
true
+
+ true
+
true
@@ -2160,6 +2169,7 @@
+
diff --git a/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj.filters b/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj.filters
index 7c573066fa..81de8f24a7 100644
--- a/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj.filters
+++ b/examples/MidiTest/Builds/VisualStudio2015/MidiTest_App.vcxproj.filters
@@ -1573,6 +1573,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1741,6 +1744,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1750,6 +1756,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3366,6 +3375,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj b/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj
index 228f2322e7..de2af78849 100644
--- a/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj
+++ b/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj
@@ -1311,6 +1311,9 @@
true
+
+ true
+
true
@@ -1479,6 +1482,9 @@
true
+
+ true
+
true
@@ -1488,6 +1494,9 @@
true
+
+ true
+
true
@@ -2160,6 +2169,7 @@
+
diff --git a/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj.filters b/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj.filters
index f644d8482b..cb48e572ef 100644
--- a/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj.filters
+++ b/examples/MidiTest/Builds/VisualStudio2017/MidiTest_App.vcxproj.filters
@@ -1573,6 +1573,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1741,6 +1744,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1750,6 +1756,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3366,6 +3375,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/examples/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
index b074be4e2f..a59112a9c0 100644
--- a/examples/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
+++ b/examples/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_networkgraphicsdemo_JUCENetworkGraphicsDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_networkgraphicsdemo_JUCENetworkGraphicsDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_juce_networkgraphicsdemo_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/juce/networkgraphicsdemo/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -905,6 +905,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1030,9 +1032,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2133,6 +2137,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2258,9 +2264,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/SharingContentProvider.java b/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/SharingContentProvider.java
new file mode 100644
index 0000000000..4112f21bb2
--- /dev/null
+++ b/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.juce.networkgraphicsdemo;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj b/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj
index 812aa60880..eec897a245 100644
--- a/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj
+++ b/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj
@@ -1331,6 +1331,9 @@
true
+
+ true
+
true
@@ -1499,6 +1502,9 @@
true
+
+ true
+
true
@@ -1508,6 +1514,9 @@
true
+
+ true
+
true
@@ -2251,6 +2260,7 @@
+
diff --git a/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj.filters b/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj.filters
index b6f76a5f9c..db82b3b991 100644
--- a/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj.filters
+++ b/examples/NetworkGraphicsDemo/Builds/VisualStudio2013/JUCE Network Graphics Demo_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3519,6 +3528,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj b/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj
index 3bcb18c1c9..c72febc998 100644
--- a/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj
+++ b/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj
@@ -1331,6 +1331,9 @@
true
+
+ true
+
true
@@ -1499,6 +1502,9 @@
true
+
+ true
+
true
@@ -1508,6 +1514,9 @@
true
+
+ true
+
true
@@ -2251,6 +2260,7 @@
+
diff --git a/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj.filters b/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj.filters
index 6da3bbd9be..19dd3e5ab5 100644
--- a/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj.filters
+++ b/examples/NetworkGraphicsDemo/Builds/VisualStudio2017/JUCE Network Graphics Demo_App.vcxproj.filters
@@ -1624,6 +1624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1792,6 +1795,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1801,6 +1807,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3519,6 +3528,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj b/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj
index e1a310c672..961e5d44fa 100644
--- a/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj
+++ b/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj
@@ -1283,6 +1283,9 @@
true
+
+ true
+
true
@@ -1451,6 +1454,9 @@
true
+
+ true
+
true
@@ -1460,6 +1466,9 @@
true
+
+ true
+
true
@@ -2196,6 +2205,7 @@
+
diff --git a/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj.filters b/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj.filters
index 99d40086cc..97906ea79d 100644
--- a/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj.filters
+++ b/examples/OSCMonitor/Builds/VisualStudio2015/OSCMonitor_App.vcxproj.filters
@@ -1558,6 +1558,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1726,6 +1729,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1735,6 +1741,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3417,6 +3426,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj b/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj
index f26b49bb75..b3b0b78b6f 100644
--- a/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj
+++ b/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj
@@ -1283,6 +1283,9 @@
true
+
+ true
+
true
@@ -1451,6 +1454,9 @@
true
+
+ true
+
true
@@ -1460,6 +1466,9 @@
true
+
+ true
+
true
@@ -2196,6 +2205,7 @@
+
diff --git a/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj.filters b/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj.filters
index 12ea2b5b55..82cfe457da 100644
--- a/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj.filters
+++ b/examples/OSCMonitor/Builds/VisualStudio2017/OSCMonitor_App.vcxproj.filters
@@ -1558,6 +1558,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1726,6 +1729,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1735,6 +1741,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3417,6 +3426,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCReceiver/Builds/Android/app/CMakeLists.txt b/examples/OSCReceiver/Builds/Android/app/CMakeLists.txt
index d2fcd599ed..8c5cb779a7 100644
--- a/examples/OSCReceiver/Builds/Android/app/CMakeLists.txt
+++ b/examples/OSCReceiver/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_oscreceiver_OSCReceiver" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/oscreceiver/OSCReceiver\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_oscreceiver_OSCReceiver" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/oscreceiver/OSCReceiver\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_yourcompany_oscreceiver_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/yourcompany/oscreceiver/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -557,6 +557,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -682,9 +684,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -1396,6 +1400,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -1521,9 +1527,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/SharingContentProvider.java b/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/SharingContentProvider.java
new file mode 100644
index 0000000000..00eb03df53
--- /dev/null
+++ b/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.yourcompany.oscreceiver;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj b/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj
index 3d149e8113..d64fb4bf92 100644
--- a/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj
+++ b/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj
@@ -911,6 +911,9 @@
true
+
+ true
+
true
@@ -1079,6 +1082,9 @@
true
+
+ true
+
true
@@ -1088,6 +1094,9 @@
true
+
+ true
+
true
@@ -1600,6 +1609,7 @@
+
diff --git a/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj.filters b/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj.filters
index fd8ecc17be..8193bf7257 100644
--- a/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj.filters
+++ b/examples/OSCReceiver/Builds/VisualStudio2015/OSCReceiver_App.vcxproj.filters
@@ -1033,6 +1033,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1201,6 +1204,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1210,6 +1216,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2292,6 +2301,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj b/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj
index 380fbdacd7..e5db246df7 100644
--- a/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj
+++ b/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj
@@ -911,6 +911,9 @@
true
+
+ true
+
true
@@ -1079,6 +1082,9 @@
true
+
+ true
+
true
@@ -1088,6 +1094,9 @@
true
+
+ true
+
true
@@ -1600,6 +1609,7 @@
+
diff --git a/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj.filters b/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj.filters
index 931e6e234c..bc5b26d27e 100644
--- a/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj.filters
+++ b/examples/OSCReceiver/Builds/VisualStudio2017/OSCReceiver_App.vcxproj.filters
@@ -1033,6 +1033,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1201,6 +1204,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1210,6 +1216,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2292,6 +2301,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCSender/Builds/Android/app/CMakeLists.txt b/examples/OSCSender/Builds/Android/app/CMakeLists.txt
index cad5f84140..9c13cf7e47 100644
--- a/examples/OSCSender/Builds/Android/app/CMakeLists.txt
+++ b/examples/OSCSender/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_oscsender_OSCSender" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/oscsender/OSCSender\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=10" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_yourcompany_oscsender_OSCSender" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/yourcompany/oscsender/OSCSender\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_yourcompany_oscsender_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/yourcompany/oscsender/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -542,6 +542,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -667,9 +669,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -1303,6 +1307,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -1428,9 +1434,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/SharingContentProvider.java b/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/SharingContentProvider.java
new file mode 100644
index 0000000000..58918bf931
--- /dev/null
+++ b/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/SharingContentProvider.java
@@ -0,0 +1,129 @@
+package com.yourcompany.oscsender;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+}
diff --git a/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj b/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj
index 8648224a7d..925a1e5b6c 100644
--- a/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj
+++ b/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj
@@ -890,6 +890,9 @@
true
+
+ true
+
true
@@ -1058,6 +1061,9 @@
true
+
+ true
+
true
@@ -1067,6 +1073,9 @@
true
+
+ true
+
true
@@ -1483,6 +1492,7 @@
+
diff --git a/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj.filters b/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj.filters
index ddc41fa2be..02c7197110 100644
--- a/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj.filters
+++ b/examples/OSCSender/Builds/VisualStudio2015/OSCSender_App.vcxproj.filters
@@ -982,6 +982,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1150,6 +1153,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1159,6 +1165,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2112,6 +2121,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj b/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj
index 93f80a8860..28809e5438 100644
--- a/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj
+++ b/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj
@@ -890,6 +890,9 @@
true
+
+ true
+
true
@@ -1058,6 +1061,9 @@
true
+
+ true
+
true
@@ -1067,6 +1073,9 @@
true
+
+ true
+
true
@@ -1483,6 +1492,7 @@
+
diff --git a/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj.filters b/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj.filters
index f2cb34ec3f..46cc23e21f 100644
--- a/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj.filters
+++ b/examples/OSCSender/Builds/VisualStudio2017/OSCSender_App.vcxproj.filters
@@ -982,6 +982,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1150,6 +1153,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1159,6 +1165,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -2112,6 +2121,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj b/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj
index 45e870d045..cee2f0024c 100644
--- a/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj
+++ b/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj
@@ -1284,6 +1284,9 @@
true
+
+ true
+
true
@@ -1452,6 +1455,9 @@
true
+
+ true
+
true
@@ -1461,6 +1467,9 @@
true
+
+ true
+
true
@@ -2169,6 +2178,7 @@
+
diff --git a/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj.filters b/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj.filters
index ae7259d171..a04d5921a1 100644
--- a/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj.filters
+++ b/examples/OpenGLAppExample/Builds/VisualStudio2017/OpenGLAppExample_App.vcxproj.filters
@@ -1558,6 +1558,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1726,6 +1729,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1735,6 +1741,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3387,6 +3396,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj b/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj
index a4adc76eb6..b1e2903d35 100644
--- a/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj
+++ b/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj
@@ -1310,6 +1310,9 @@
true
+
+ true
+
true
@@ -1478,6 +1481,9 @@
true
+
+ true
+
true
@@ -1487,6 +1493,9 @@
true
+
+ true
+
true
@@ -2161,6 +2170,7 @@
+
diff --git a/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj.filters b/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj.filters
index 92de7f0d7e..0f15f5a2d7 100644
--- a/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj.filters
+++ b/examples/PluckedStringsDemo/Builds/VisualStudio2013/PluckedStringsDemo_App.vcxproj.filters
@@ -1570,6 +1570,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1738,6 +1741,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1747,6 +1753,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3369,6 +3378,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj b/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj
index b289ea8765..f87722cc70 100644
--- a/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj
+++ b/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj
@@ -1310,6 +1310,9 @@
true
+
+ true
+
true
@@ -1478,6 +1481,9 @@
true
+
+ true
+
true
@@ -1487,6 +1493,9 @@
true
+
+ true
+
true
@@ -2161,6 +2170,7 @@
+
diff --git a/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj.filters b/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj.filters
index 741bb73698..3fa6d08916 100644
--- a/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj.filters
+++ b/examples/PluckedStringsDemo/Builds/VisualStudio2017/PluckedStringsDemo_App.vcxproj.filters
@@ -1570,6 +1570,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1738,6 +1741,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1747,6 +1753,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3369,6 +3378,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj
index ef83e6b511..960b322fc7 100644
--- a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj
+++ b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj
@@ -1361,6 +1361,9 @@
true
+
+ true
+
true
@@ -1529,6 +1532,9 @@
true
+
+ true
+
true
@@ -1538,6 +1544,9 @@
true
+
+ true
+
true
@@ -2291,6 +2300,7 @@
+
diff --git a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj.filters b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj.filters
index 1eaceb6fc5..cc4d198e3c 100644
--- a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2015/Arpeggiator_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj
index ebd04968ff..6e12efb8ff 100644
--- a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj
+++ b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2285,6 +2294,7 @@
+
diff --git a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj.filters b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj.filters
index 0cf7f4950c..9984920f8c 100644
--- a/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/Arpeggiator/Builds/VisualStudio2017/Arpeggiator_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj
index 83672e2884..9af75f570e 100644
--- a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj
+++ b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj
@@ -1361,6 +1361,9 @@
true
+
+ true
+
true
@@ -1529,6 +1532,9 @@
true
+
+ true
+
true
@@ -1538,6 +1544,9 @@
true
+
+ true
+
true
@@ -2291,6 +2300,7 @@
+
diff --git a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj.filters b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj.filters
index fbd6214084..919c7574d1 100644
--- a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2015/GainPlugIn_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj
index a36eeed394..339ec17d07 100644
--- a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj
+++ b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2285,6 +2294,7 @@
+
diff --git a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj.filters b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj.filters
index a17347e3d8..dd145c1212 100644
--- a/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/GainPlugIn/Builds/VisualStudio2017/GainPlugIn_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj
index 90f2a63039..84a573bd20 100644
--- a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj
+++ b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj
@@ -1361,6 +1361,9 @@
true
+
+ true
+
true
@@ -1529,6 +1532,9 @@
true
+
+ true
+
true
@@ -1538,6 +1544,9 @@
true
+
+ true
+
true
@@ -2292,6 +2301,7 @@
+
diff --git a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj.filters b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj.filters
index 4093f04a70..2cc39c2f7c 100644
--- a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2015/MultiOutSynth_SharedCode.vcxproj.filters
@@ -1651,6 +1651,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1819,6 +1822,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1828,6 +1834,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3618,6 +3627,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj
index 1ab82da8ca..f02733a311 100644
--- a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj
+++ b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2286,6 +2295,7 @@
+
diff --git a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj.filters b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj.filters
index 53aec8cbdc..165ca804d1 100644
--- a/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/MultiOutSynth/Builds/VisualStudio2017/MultiOutSynth_SharedCode.vcxproj.filters
@@ -1651,6 +1651,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1819,6 +1822,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1828,6 +1834,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3618,6 +3627,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj
index 0812f24e0f..f8ef16d632 100644
--- a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj
+++ b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj
@@ -1361,6 +1361,9 @@
true
+
+ true
+
true
@@ -1529,6 +1532,9 @@
true
+
+ true
+
true
@@ -1538,6 +1544,9 @@
true
+
+ true
+
true
@@ -2291,6 +2300,7 @@
+
diff --git a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj.filters b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj.filters
index fbc52ca195..cf50db2f4a 100644
--- a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2015/NoiseGate_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj
index 71e642e580..757414b83b 100644
--- a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj
+++ b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2285,6 +2294,7 @@
+
diff --git a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj.filters b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj.filters
index 0635875ee4..1af481e3d1 100644
--- a/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/NoiseGate/Builds/VisualStudio2017/NoiseGate_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3612,6 +3621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj b/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj
index 50eb1c8bb7..195565fd60 100644
--- a/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj
+++ b/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2286,6 +2295,7 @@
+
diff --git a/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj.filters b/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj.filters
index cb6f27d70f..1b98469341 100644
--- a/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/Surround/Builds/VisualStudio2015/Surround_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3615,6 +3624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj b/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj
index 9713384f20..e3122eebed 100644
--- a/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj
+++ b/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj
@@ -1355,6 +1355,9 @@
true
+
+ true
+
true
@@ -1523,6 +1526,9 @@
true
+
+ true
+
true
@@ -1532,6 +1538,9 @@
true
+
+ true
+
true
@@ -2286,6 +2295,7 @@
+
diff --git a/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj.filters b/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj.filters
index 52f0c6593e..50664ccc0c 100644
--- a/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj.filters
+++ b/examples/PlugInSamples/Surround/Builds/VisualStudio2017/Surround_SharedCode.vcxproj.filters
@@ -1648,6 +1648,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1816,6 +1819,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1825,6 +1831,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3615,6 +3624,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/PushNotificationsDemo/Builds/Android/app/CMakeLists.txt b/examples/PushNotificationsDemo/Builds/Android/app/CMakeLists.txt
index ea2dec0161..e889c77e4a 100644
--- a/examples/PushNotificationsDemo/Builds/Android/app/CMakeLists.txt
+++ b/examples/PushNotificationsDemo/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=26" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_pushnotificationsdemo_PushNotificationsDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/pushnotificationsdemo/PushNotificationsDemo\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME=com_juce_pushnotificationsdemo_JuceFirebaseInstanceIdService" "-DJUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME=com_juce_pushnotificationsdemo_JuceFirebaseMessagingService" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=26" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_pushnotificationsdemo_PushNotificationsDemo" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/pushnotificationsdemo/PushNotificationsDemo\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_juce_pushnotificationsdemo_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/juce/pushnotificationsdemo/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME=com_juce_pushnotificationsdemo_JuceFirebaseInstanceIdService" "-DJUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME=com_juce_pushnotificationsdemo_JuceFirebaseMessagingService" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -888,6 +888,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1013,9 +1015,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2078,6 +2082,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2203,9 +2209,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/PushNotificationsDemo/Builds/Android/app/src/main/java/com/juce/pushnotificationsdemo/SharingContentProvider.java b/examples/PushNotificationsDemo/Builds/Android/app/src/main/java/com/juce/pushnotificationsdemo/SharingContentProvider.java
new file mode 100644
index 0000000000..dceb9b79d1
--- /dev/null
+++ b/examples/PushNotificationsDemo/Builds/Android/app/src/main/java/com/juce/pushnotificationsdemo/SharingContentProvider.java
@@ -0,0 +1,138 @@
+package com.juce.pushnotificationsdemo;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+ @Override
+ public String[] getStreamTypes (Uri uri, String mimeTypeFilter)
+ {
+ synchronized (lock)
+ {
+ return contentSharerGetStreamTypes (uri, mimeTypeFilter);
+ }
+ }
+
+}
diff --git a/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj b/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj
index 5dff5e9d16..71c7123dca 100644
--- a/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj
+++ b/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj
@@ -1284,6 +1284,9 @@
true
+
+ true
+
true
@@ -1452,6 +1455,9 @@
true
+
+ true
+
true
@@ -1461,6 +1467,9 @@
true
+
+ true
+
true
@@ -2159,6 +2168,7 @@
+
diff --git a/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj.filters b/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj.filters
index 1eff083401..02f45737ce 100644
--- a/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj.filters
+++ b/examples/PushNotificationsDemo/Builds/VisualStudio2015/PushNotificationsDemo_App.vcxproj.filters
@@ -1552,6 +1552,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1720,6 +1723,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1729,6 +1735,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3366,6 +3375,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj b/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj
index 865c3e2f50..cc46c46f1c 100644
--- a/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj
+++ b/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj
@@ -1367,6 +1367,9 @@
true
+
+ true
+
true
@@ -1535,6 +1538,9 @@
true
+
+ true
+
true
@@ -1544,6 +1550,9 @@
true
+
+ true
+
true
@@ -2248,6 +2257,7 @@
+
diff --git a/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj.filters b/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj.filters
index 10a8e6fde4..793dde4594 100644
--- a/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj.filters
+++ b/examples/SimpleFFTExample/Builds/VisualStudio2013/SimpleFFTExample_App.vcxproj.filters
@@ -1651,6 +1651,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1819,6 +1822,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1828,6 +1834,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3540,6 +3549,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj b/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj
index fc7322363c..a75fc89e43 100644
--- a/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj
+++ b/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj
@@ -1367,6 +1367,9 @@
true
+
+ true
+
true
@@ -1535,6 +1538,9 @@
true
+
+ true
+
true
@@ -1544,6 +1550,9 @@
true
+
+ true
+
true
@@ -2248,6 +2257,7 @@
+
diff --git a/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj.filters b/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj.filters
index 9aa2783328..e805e4101d 100644
--- a/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj.filters
+++ b/examples/SimpleFFTExample/Builds/VisualStudio2017/SimpleFFTExample_App.vcxproj.filters
@@ -1651,6 +1651,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1819,6 +1822,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1828,6 +1834,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3540,6 +3549,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/audio plugin demo/Builds/Android/app/CMakeLists.txt b/examples/audio plugin demo/Builds/Android/app/CMakeLists.txt
index 109346fecb..9a5b0991e8 100644
--- a/examples/audio plugin demo/Builds/Android/app/CMakeLists.txt
+++ b/examples/audio plugin demo/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemoplugin_JuceDemoPlugin" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemoplugin/JuceDemoPlugin\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_jucedemoplugin_JuceDemoPlugin" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/jucedemoplugin/JuceDemoPlugin\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_juce_jucedemoplugin_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/juce/jucedemoplugin/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -987,6 +987,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1112,9 +1114,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2242,6 +2246,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2367,9 +2373,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/SharingContentProvider.java b/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/SharingContentProvider.java
new file mode 100644
index 0000000000..b4c421dccf
--- /dev/null
+++ b/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/SharingContentProvider.java
@@ -0,0 +1,138 @@
+package com.juce.jucedemoplugin;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+ @Override
+ public String[] getStreamTypes (Uri uri, String mimeTypeFilter)
+ {
+ synchronized (lock)
+ {
+ return contentSharerGetStreamTypes (uri, mimeTypeFilter);
+ }
+ }
+
+}
diff --git a/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj b/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj
index 431c5d6bf7..ebc900fae0 100644
--- a/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj
+++ b/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj
@@ -1383,6 +1383,9 @@
true
+
+ true
+
true
@@ -1551,6 +1554,9 @@
true
+
+ true
+
true
@@ -1560,6 +1566,9 @@
true
+
+ true
+
true
@@ -2281,6 +2290,7 @@
+
diff --git a/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj.filters b/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj.filters
index f350e873bd..fa4565f8bf 100644
--- a/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj.filters
+++ b/examples/audio plugin demo/Builds/VisualStudio2015/JuceDemoPlugin_SharedCode.vcxproj.filters
@@ -1666,6 +1666,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1834,6 +1837,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1843,6 +1849,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3606,6 +3615,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj b/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj
index 846c1ba391..82ac0797b2 100644
--- a/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj
+++ b/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj
@@ -1383,6 +1383,9 @@
true
+
+ true
+
true
@@ -1551,6 +1554,9 @@
true
+
+ true
+
true
@@ -1560,6 +1566,9 @@
true
+
+ true
+
true
@@ -2281,6 +2290,7 @@
+
diff --git a/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj.filters b/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj.filters
index ec92583c04..ed080d62b0 100644
--- a/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj.filters
+++ b/examples/audio plugin demo/Builds/VisualStudio2017/JuceDemoPlugin_SharedCode.vcxproj.filters
@@ -1666,6 +1666,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1834,6 +1837,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1843,6 +1849,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3606,6 +3615,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj b/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj
index 0342e49414..a04657f9e7 100644
--- a/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj
+++ b/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj
@@ -1336,6 +1336,9 @@
true
+
+ true
+
true
@@ -1504,6 +1507,9 @@
true
+
+ true
+
true
@@ -1513,6 +1519,9 @@
true
+
+ true
+
true
@@ -2239,6 +2248,7 @@
+
diff --git a/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj.filters b/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj.filters
index 8dc50e250a..bbc9483614 100644
--- a/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj.filters
+++ b/examples/audio plugin host/Builds/VisualStudio2013/Plugin Host_App.vcxproj.filters
@@ -1642,6 +1642,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1810,6 +1813,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1819,6 +1825,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3525,6 +3534,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj b/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj
index dd2a117b98..bde26a74ac 100644
--- a/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj
+++ b/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj
@@ -1336,6 +1336,9 @@
true
+
+ true
+
true
@@ -1504,6 +1507,9 @@
true
+
+ true
+
true
@@ -1513,6 +1519,9 @@
true
+
+ true
+
true
@@ -2239,6 +2248,7 @@
+
diff --git a/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj.filters b/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj.filters
index f0fc7effa9..1f1e3c6129 100644
--- a/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj.filters
+++ b/examples/audio plugin host/Builds/VisualStudio2015/Plugin Host_App.vcxproj.filters
@@ -1642,6 +1642,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1810,6 +1813,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1819,6 +1825,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3525,6 +3534,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj b/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj
index 577df8be75..bcb759f452 100644
--- a/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj
+++ b/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj
@@ -1336,6 +1336,9 @@
true
+
+ true
+
true
@@ -1504,6 +1507,9 @@
true
+
+ true
+
true
@@ -1513,6 +1519,9 @@
true
+
+ true
+
true
@@ -2239,6 +2248,7 @@
+
diff --git a/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj.filters b/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj.filters
index 44d8abf56f..c147227416 100644
--- a/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj.filters
+++ b/examples/audio plugin host/Builds/VisualStudio2017/Plugin Host_App.vcxproj.filters
@@ -1642,6 +1642,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1810,6 +1813,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1819,6 +1825,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3525,6 +3534,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
index 080546b919..94e1ff5257 100644
--- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
+++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
@@ -8,7 +8,7 @@ SET(BINARY_NAME "juce_jni")
add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
-add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_audioperformancetest_AudioPerformanceTest" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/audioperformancetest/AudioPerformanceTest\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
+add_definitions("-DJUCE_ANDROID=1" "-DJUCE_ANDROID_API_VERSION=23" "-DJUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_audioperformancetest_AudioPerformanceTest" "-DJUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/audioperformancetest/AudioPerformanceTest\"" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME=com_juce_audioperformancetest_SharingContentProvider" "-DJUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH=\"com/juce/audioperformancetest/SharingContentProvider\"" "-DJUCE_PUSH_NOTIFICATIONS=1" "-DJUCE_ANDROID_GL_ES_VERSION_3_0=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000")
include_directories( AFTER
"../../../JuceLibraryCode"
@@ -886,6 +886,8 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp"
"../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h"
"../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp"
+ "../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h"
"../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp"
@@ -1011,9 +1013,11 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"
"../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h"
+ "../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp"
"../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp"
"../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp"
+ "../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp"
"../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm"
"../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm"
@@ -2039,6 +2043,8 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/ju
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_DrawableText.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/drawables/juce_SVGParser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_ContentSharer.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
@@ -2164,9 +2170,11 @@ set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_M
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_SelectedItemSet.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/mouse/juce_TooltipClient.h" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_FileChooser.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_android_Windowing.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_common_MimeTypes.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
+set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_FileChooser.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_gui_basics/native/juce_ios_Windowing.mm" PROPERTIES HEADER_FILE_ONLY TRUE)
diff --git a/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/SharingContentProvider.java b/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/SharingContentProvider.java
new file mode 100644
index 0000000000..5b7d4d4ac8
--- /dev/null
+++ b/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/SharingContentProvider.java
@@ -0,0 +1,138 @@
+package com.juce.audioperformancetest;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+
+ @Override
+ public String[] getStreamTypes (Uri uri, String mimeTypeFilter)
+ {
+ synchronized (lock)
+ {
+ return contentSharerGetStreamTypes (uri, mimeTypeFilter);
+ }
+ }
+
+}
diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj
index 9d6f071527..647fa39c43 100644
--- a/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj
+++ b/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj
@@ -1310,6 +1310,9 @@
true
+
+ true
+
true
@@ -1478,6 +1481,9 @@
true
+
+ true
+
true
@@ -1487,6 +1493,9 @@
true
+
+ true
+
true
@@ -2159,6 +2168,7 @@
+
diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj.filters
index e1354184f5..02a4c9b961 100644
--- a/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj.filters
+++ b/extras/AudioPerformanceTest/Builds/VisualStudio2015/AudioPerformanceTest_App.vcxproj.filters
@@ -1570,6 +1570,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1738,6 +1741,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1747,6 +1753,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3363,6 +3372,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
index 2e43207beb..c3e65bd37e 100644
--- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj
@@ -1006,6 +1006,9 @@
true
+
+ true
+
true
@@ -1174,6 +1177,9 @@
true
+
+ true
+
true
@@ -1183,6 +1189,9 @@
true
+
+ true
+
true
@@ -1841,6 +1850,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
index 59e48461de..b56cc60d4d 100644
--- a/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2013/Projucer_App.vcxproj.filters
@@ -1297,6 +1297,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1465,6 +1468,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1474,6 +1480,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3048,6 +3057,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
index 172ae90cc7..3e62cabc47 100644
--- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj
@@ -1006,6 +1006,9 @@
true
+
+ true
+
true
@@ -1174,6 +1177,9 @@
true
+
+ true
+
true
@@ -1183,6 +1189,9 @@
true
+
+ true
+
true
@@ -1841,6 +1850,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
index 8d8237ad6b..4993ed9351 100644
--- a/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2015/Projucer_App.vcxproj.filters
@@ -1297,6 +1297,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1465,6 +1468,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1474,6 +1480,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3048,6 +3057,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
index fcf6cd1a87..5e154522c4 100644
--- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
@@ -1006,6 +1006,9 @@
true
+
+ true
+
true
@@ -1174,6 +1177,9 @@
true
+
+ true
+
true
@@ -1183,6 +1189,9 @@
true
+
+ true
+
true
@@ -1841,6 +1850,7 @@
+
diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
index c112c03bda..81a4b43910 100644
--- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
@@ -1297,6 +1297,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1465,6 +1468,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1474,6 +1480,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3048,6 +3057,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
index daffb547ed..72a7a6def6 100644
--- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
+++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
@@ -113,6 +113,8 @@ public:
CachedValue androidEnableRemoteNotifications;
CachedValue androidRemoteNotificationsConfigFile;
+ CachedValue androidEnableContentSharing;
+
CachedValue androidKeyStore, androidKeyStorePass, androidKeyAlias, androidKeyAliasPass;
CachedValue gradleVersion, androidPluginVersion, gradleToolchain, buildToolsVersion;
@@ -142,6 +144,7 @@ public:
androidOtherPermissions (settings, Ids::androidOtherPermissions, nullptr),
androidEnableRemoteNotifications (settings, Ids::androidEnableRemoteNotifications, nullptr, false),
androidRemoteNotificationsConfigFile (settings, Ids::androidRemoteNotificationsConfigFile, nullptr, ""),
+ androidEnableContentSharing (settings, Ids::androidEnableContentSharing, nullptr, false),
androidKeyStore (settings, Ids::androidKeyStore, nullptr, "${user.home}/.android/debug.keystore"),
androidKeyStorePass (settings, Ids::androidKeyStorePass, nullptr, "android"),
androidKeyAlias (settings, Ids::androidKeyAlias, nullptr, "androiddebugkey"),
@@ -905,6 +908,9 @@ private:
"Enable to be able to send remote notifications to devices running your app (min API level 14). Provide Remote Notifications Config File, "
"configure your app in Firebase Console and ensure you have the latest Google Repository in Android Studio's SDK Manager.");
+ props.add (new BooleanPropertyComponent (androidEnableContentSharing.getPropertyAsValue(), "Content Sharing", "Enabled"),
+ "If enabled, your app will be able to share content with other apps.");
+
props.add (new TextPropertyComponent (androidRemoteNotificationsConfigFile.getPropertyAsValue(), "Remote Notifications Config File", 2048, false),
"Path to google-services.json file. This will be the file provided by Firebase when creating a new app in Firebase console.");
@@ -974,6 +980,7 @@ private:
copyActivityJavaFiles (javaSourceFolder, javaTarget, package);
copyServicesJavaFiles (javaSourceFolder, javaTarget, package);
+ copyProviderJavaFile (javaSourceFolder, javaTarget, package);
copyAdditionalJavaFiles (javaSourceFolder, javaInAppBillingTarget);
}
}
@@ -1140,6 +1147,31 @@ private:
}
}
+ void copyProviderJavaFile (const File& javaSourceFolder, const File& targetFolder, const String& package) const
+ {
+ File providerFile (javaSourceFolder.getChildFile ("AndroidSharingContentProvider.java"));
+
+ jassert (providerFile.existsAsFile());
+
+ auto targetFile = targetFolder.getChildFile ("SharingContentProvider.java");
+
+ auto fileContent = providerFile.loadFileAsString()
+ .replace ("package com.juce;", "package " + package + ";");
+
+ auto commonStart = fileContent.upToFirstOccurrenceOf ("$$ContentProviderApi11", false, false);
+ auto commonEnd = fileContent.fromFirstOccurrenceOf ("ContentProviderApi11$$", false, false);
+
+ auto middleContent = androidMinimumSDK.get().getIntValue() >= 11
+ ? fileContent.fromFirstOccurrenceOf ("$$ContentProviderApi11", false, false)
+ .upToFirstOccurrenceOf ("ContentProviderApi11$$", false, false)
+ : String();
+
+ auto newContent = commonStart;
+ newContent << middleContent << commonEnd;
+
+ overwriteFileIfDifferentOrThrow (targetFile, newContent);
+ }
+
void copyExtraResourceFiles() const
{
for (ConstConfigIterator config (*this); config.next();)
@@ -1405,6 +1437,8 @@ private:
defines.set ("JUCE_ANDROID_API_VERSION", androidMinimumSDK.get());
defines.set ("JUCE_ANDROID_ACTIVITY_CLASSNAME", getJNIActivityClassName().replaceCharacter ('/', '_'));
defines.set ("JUCE_ANDROID_ACTIVITY_CLASSPATH", "\"" + getJNIActivityClassName() + "\"");
+ defines.set ("JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME", getSharingContentProviderClassName().replaceCharacter('.', '_'));
+ defines.set ("JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH", "\"" + getSharingContentProviderClassName().replaceCharacter('.', '/') + "\"");
defines.set ("JUCE_PUSH_NOTIFICATIONS", "1");
if (androidInAppBillingPermission.get())
@@ -1424,6 +1458,11 @@ private:
return defines;
}
+ String getSharingContentProviderClassName() const
+ {
+ return getActivityClassPackage() + ".SharingContentProvider";
+ }
+
StringPairArray getProjectPreprocessorDefs() const
{
StringPairArray defines (getAndroidPreprocessorDefs());
@@ -1530,6 +1569,29 @@ private:
//==============================================================================
XmlElement* createManifestXML() const
+ {
+ XmlElement* manifest = createManifestElement();
+
+ createSupportsScreensElement (*manifest);
+ createUsesSdkElement (*manifest);
+ createPermissionElements (*manifest);
+ createOpenGlFeatureElement (*manifest);
+
+ if (! isLibrary())
+ {
+ auto* app = createApplicationElement (*manifest);
+
+ auto* act = createActivityElement (*app);
+ createIntentElement (*act);
+
+ createServiceElements (*app);
+ createProviderElement (*app);
+ }
+
+ return manifest;
+ }
+
+ XmlElement* createManifestElement() const
{
XmlElement* manifest = XmlDocument::parse (androidManifestCustomXmlElements.get());
@@ -1541,39 +1603,51 @@ private:
setAttributeIfNotPresent (*manifest, "android:versionName", project.getVersionString());
setAttributeIfNotPresent (*manifest, "package", getActivityClassPackage());
+ return manifest;
+ }
+
+ void createSupportsScreensElement (XmlElement& manifest) const
+ {
if (! isLibrary())
{
- if (manifest->getChildByName ("supports-screens") == nullptr)
+ if (manifest.getChildByName ("supports-screens") == nullptr)
{
- XmlElement* screens = manifest->createNewChildElement ("supports-screens");
+ XmlElement* screens = manifest.createNewChildElement ("supports-screens");
screens->setAttribute ("android:smallScreens", "true");
screens->setAttribute ("android:normalScreens", "true");
screens->setAttribute ("android:largeScreens", "true");
screens->setAttribute ("android:anyDensity", "true");
}
}
+ }
- auto* sdk = getOrCreateChildWithName (*manifest, "uses-sdk");
+ void createUsesSdkElement (XmlElement& manifest) const
+ {
+ auto* sdk = getOrCreateChildWithName (manifest, "uses-sdk");
setAttributeIfNotPresent (*sdk, "android:minSdkVersion", androidMinimumSDK.get());
setAttributeIfNotPresent (*sdk, "android:targetSdkVersion", androidMinimumSDK.get());
+ }
- {
- StringArray permissions (getPermissionsRequired());
-
- forEachXmlChildElementWithTagName (*manifest, child, "uses-permission")
- {
- permissions.removeString (child->getStringAttribute ("android:name"), false);
- }
+ void createPermissionElements (XmlElement& manifest) const
+ {
+ StringArray permissions (getPermissionsRequired());
- for (int i = permissions.size(); --i >= 0;)
- manifest->createNewChildElement ("uses-permission")->setAttribute ("android:name", permissions[i]);
+ forEachXmlChildElementWithTagName (manifest, child, "uses-permission")
+ {
+ permissions.removeString (child->getStringAttribute ("android:name"), false);
}
+ for (int i = permissions.size(); --i >= 0;)
+ manifest.createNewChildElement ("uses-permission")->setAttribute ("android:name", permissions[i]);
+ }
+
+ void createOpenGlFeatureElement (XmlElement& manifest) const
+ {
if (project.getModules().isModuleEnabled ("juce_opengl"))
{
XmlElement* glVersion = nullptr;
- forEachXmlChildElementWithTagName (*manifest, child, "uses-feature")
+ forEachXmlChildElementWithTagName (manifest, child, "uses-feature")
{
if (child->getStringAttribute ("android:glEsVersion").isNotEmpty())
{
@@ -1583,120 +1657,143 @@ private:
}
if (glVersion == nullptr)
- glVersion = manifest->createNewChildElement ("uses-feature");
+ glVersion = manifest.createNewChildElement ("uses-feature");
setAttributeIfNotPresent (*glVersion, "android:glEsVersion", (androidMinimumSDK.get().getIntValue() >= 18 ? "0x00030000" : "0x00020000"));
setAttributeIfNotPresent (*glVersion, "android:required", "true");
}
+ }
- if (! isLibrary())
+ XmlElement* createApplicationElement (XmlElement& manifest) const
+ {
+ auto* app = getOrCreateChildWithName (manifest, "application");
+ setAttributeIfNotPresent (*app, "android:label", "@string/app_name");
+
+ if (androidTheme.get().isNotEmpty())
+ setAttributeIfNotPresent (*app, "android:theme", androidTheme.get());
+
+ if (! app->hasAttribute ("android:icon"))
{
- auto* app = getOrCreateChildWithName (*manifest, "application");
- setAttributeIfNotPresent (*app, "android:label", "@string/app_name");
+ ScopedPointer bigIcon (getBigIcon()), smallIcon (getSmallIcon());
- if (androidTheme.get().isNotEmpty())
- setAttributeIfNotPresent (*app, "android:theme", androidTheme.get());
+ if (bigIcon != nullptr || smallIcon != nullptr)
+ app->setAttribute ("android:icon", "@drawable/icon");
+ }
- if (! app->hasAttribute ("android:icon"))
- {
- ScopedPointer bigIcon (getBigIcon()), smallIcon (getSmallIcon());
+ if (androidMinimumSDK.get().getIntValue() >= 11)
+ {
+ if (! app->hasAttribute ("android:hardwareAccelerated"))
+ app->setAttribute ("android:hardwareAccelerated", "false"); // (using the 2D acceleration slows down openGL)
+ }
+ else
+ {
+ app->removeAttribute ("android:hardwareAccelerated");
+ }
- if (bigIcon != nullptr || smallIcon != nullptr)
- app->setAttribute ("android:icon", "@drawable/icon");
- }
+ return app;
+ }
- if (androidMinimumSDK.get().getIntValue() >= 11)
- {
- if (! app->hasAttribute ("android:hardwareAccelerated"))
- app->setAttribute ("android:hardwareAccelerated", "false"); // (using the 2D acceleration slows down openGL)
- }
- else
- {
- app->removeAttribute ("android:hardwareAccelerated");
- }
+ XmlElement* createActivityElement (XmlElement& application) const
+ {
+ auto* act = getOrCreateChildWithName (application, "activity");
- auto* act = getOrCreateChildWithName (*app, "activity");
+ setAttributeIfNotPresent (*act, "android:name", getActivitySubClassName());
+ setAttributeIfNotPresent (*act, "android:label", "@string/app_name");
+
+ if (! act->hasAttribute ("android:configChanges"))
+ {
+ String configChanges ("keyboardHidden|orientation");
+ if (androidMinimumSDK.get().getIntValue() >= 13)
+ configChanges += "|screenSize";
- setAttributeIfNotPresent (*act, "android:name", getActivitySubClassName());
- setAttributeIfNotPresent (*act, "android:label", "@string/app_name");
+ act->setAttribute ("android:configChanges", configChanges);
+ }
+ else
+ {
+ auto configChanges = act->getStringAttribute ("android:configChanges");
- if (! act->hasAttribute ("android:configChanges"))
+ if (androidMinimumSDK.get().getIntValue() < 13 && configChanges.contains ("screenSize"))
{
- String configChanges ("keyboardHidden|orientation");
- if (androidMinimumSDK.get().getIntValue() >= 13)
- configChanges += "|screenSize";
+ configChanges = configChanges.replace ("|screenSize", "")
+ .replace ("screenSize|", "")
+ .replace ("screenSize", "");
act->setAttribute ("android:configChanges", configChanges);
}
- else
- {
- auto configChanges = act->getStringAttribute ("android:configChanges");
+ }
- if (androidMinimumSDK.get().getIntValue() < 13 && configChanges.contains ("screenSize"))
- {
- configChanges = configChanges.replace ("|screenSize", "")
- .replace ("screenSize|", "")
- .replace ("screenSize", "");
+ if (androidScreenOrientation.get() == "landscape")
+ {
+ String landscapeString = androidMinimumSDK.get().getIntValue() < 9
+ ? "landscape"
+ : (androidMinimumSDK.get().getIntValue() < 18 ? "sensorLandscape" : "userLandscape");
- act->setAttribute ("android:configChanges", configChanges);
- }
- }
+ setAttributeIfNotPresent (*act, "android:screenOrientation", landscapeString);
+ }
+ else
+ {
+ setAttributeIfNotPresent (*act, "android:screenOrientation", androidScreenOrientation.get());
+ }
- if (androidScreenOrientation.get() == "landscape")
- {
- String landscapeString = androidMinimumSDK.get().getIntValue() < 9
- ? "landscape"
- : (androidMinimumSDK.get().getIntValue() < 18 ? "sensorLandscape" : "userLandscape");
+ setAttributeIfNotPresent (*act, "android:launchMode", "singleTask");
- setAttributeIfNotPresent (*act, "android:screenOrientation", landscapeString);
- }
- else
- {
- setAttributeIfNotPresent (*act, "android:screenOrientation", androidScreenOrientation.get());
- }
-
- setAttributeIfNotPresent (*act, "android:launchMode", "singleTask");
+ // Using the 2D acceleration slows down OpenGL. We *do* enable it here for the activity though, and we disable it
+ // in each ComponentPeerView instead. This way any embedded native views, which are not children of ComponentPeerView,
+ // can still use hardware acceleration if needed (e.g. web view).
+ if (androidMinimumSDK.get().getIntValue() >= 11)
+ {
+ if (! act->hasAttribute ("android:hardwareAccelerated"))
+ act->setAttribute ("android:hardwareAccelerated", "true"); // (using the 2D acceleration slows down openGL)
+ }
+ else
+ {
+ act->removeAttribute ("android:hardwareAccelerated");
+ }
- // Using the 2D acceleration slows down OpenGL. We *do* enable it here for the activity though, and we disable it
- // in each ComponentPeerView instead. This way any embedded native views, which are not children of ComponentPeerView,
- // can still use hardware acceleration if needed (e.g. web view).
- if (androidMinimumSDK.get().getIntValue() >= 11)
- {
- if (! act->hasAttribute ("android:hardwareAccelerated"))
- act->setAttribute ("android:hardwareAccelerated", "true"); // (using the 2D acceleration slows down openGL)
- }
- else
- {
- act->removeAttribute ("android:hardwareAccelerated");
- }
+ return act;
+ }
- auto* intent = getOrCreateChildWithName (*act, "intent-filter");
+ void createIntentElement (XmlElement& application) const
+ {
+ auto* intent = getOrCreateChildWithName (application, "intent-filter");
- auto* action = getOrCreateChildWithName (*intent, "action");
- setAttributeIfNotPresent (*action, "android:name", "android.intent.action.MAIN");
+ auto* action = getOrCreateChildWithName (*intent, "action");
+ setAttributeIfNotPresent (*action, "android:name", "android.intent.action.MAIN");
- auto* category = getOrCreateChildWithName (*intent, "category");
- setAttributeIfNotPresent (*category, "android:name", "android.intent.category.LAUNCHER");
+ auto* category = getOrCreateChildWithName (*intent, "category");
+ setAttributeIfNotPresent (*category, "android:name", "android.intent.category.LAUNCHER");
+ }
- if (androidEnableRemoteNotifications.get())
- {
- auto* service = app->createNewChildElement ("service");
- service->setAttribute ("android:name", ".JuceFirebaseMessagingService");
- auto* intentFilter = service->createNewChildElement ("intent-filter");
- intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.MESSAGING_EVENT");
-
- service = app->createNewChildElement ("service");
- service->setAttribute ("android:name", ".JuceFirebaseInstanceIdService");
- intentFilter = service->createNewChildElement ("intent-filter");
- intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.INSTANCE_ID_EVENT");
-
- auto* metaData = app->createNewChildElement ("meta-data");
- metaData->setAttribute ("android:name", "firebase_analytics_collection_deactivated");
- metaData->setAttribute ("android:value", "true");
- }
+ void createServiceElements (XmlElement& application) const
+ {
+ if (androidEnableRemoteNotifications.get())
+ {
+ auto* service = application.createNewChildElement ("service");
+ service->setAttribute ("android:name", ".JuceFirebaseMessagingService");
+ auto* intentFilter = service->createNewChildElement ("intent-filter");
+ intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.MESSAGING_EVENT");
+
+ service = application.createNewChildElement ("service");
+ service->setAttribute ("android:name", ".JuceFirebaseInstanceIdService");
+ intentFilter = service->createNewChildElement ("intent-filter");
+ intentFilter->createNewChildElement ("action")->setAttribute ("android:name", "com.google.firebase.INSTANCE_ID_EVENT");
+
+ auto* metaData = application.createNewChildElement ("meta-data");
+ metaData->setAttribute ("android:name", "firebase_analytics_collection_deactivated");
+ metaData->setAttribute ("android:value", "true");
}
+ }
- return manifest;
+ void createProviderElement (XmlElement& application) const
+ {
+ if (androidEnableContentSharing.get())
+ {
+ auto* provider = application.createNewChildElement ("provider");
+ provider->setAttribute ("android:name", getSharingContentProviderClassName());
+ provider->setAttribute ("android:authorities", getSharingContentProviderClassName().toLowerCase());
+ provider->setAttribute ("android:grantUriPermissions", "true");
+ provider->setAttribute ("android:exported", "false");
+ }
}
static XmlElement* getOrCreateChildWithName (XmlElement& element, const String& name)
diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
index de0a47888e..abf74df466 100644
--- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
+++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
@@ -189,6 +189,7 @@ namespace Ids
DECLARE_ID (androidVibratePermissionNeeded);
DECLARE_ID (androidEnableRemoteNotifications);
DECLARE_ID (androidRemoteNotificationsConfigFile);
+ DECLARE_ID (androidEnableContentSharing);
DECLARE_ID (androidMinimumSDK);
DECLARE_ID (androidOtherPermissions);
DECLARE_ID (androidKeyStore);
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj
index fa0c047631..236402206c 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj
+++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj
@@ -1420,6 +1420,9 @@
true
+
+ true
+
true
@@ -1588,6 +1591,9 @@
true
+
+ true
+
true
@@ -1597,6 +1603,9 @@
true
+
+ true
+
true
@@ -2429,6 +2438,7 @@
+
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters
index 348e5d0910..86ae9e9c1d 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters
+++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters
@@ -1786,6 +1786,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1954,6 +1957,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1963,6 +1969,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3894,6 +3903,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj b/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj
index ebb0e2a769..6b99a81e27 100644
--- a/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj
+++ b/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj
@@ -1330,6 +1330,9 @@
true
+
+ true
+
true
@@ -1498,6 +1501,9 @@
true
+
+ true
+
true
@@ -1507,6 +1513,9 @@
true
+
+ true
+
true
@@ -2227,6 +2236,7 @@
+
diff --git a/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj.filters b/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj.filters
index e2807eae37..8cfced4c4a 100644
--- a/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj.filters
+++ b/extras/windows dll/Builds/VisualStudio2017/juce_dll_StaticLibrary.vcxproj.filters
@@ -1621,6 +1621,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
@@ -1789,6 +1792,9 @@
JUCE Modules\juce_gui_basics\mouse
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -1798,6 +1804,9 @@
JUCE Modules\juce_gui_basics\native
+
+ JUCE Modules\juce_gui_basics\native
+
JUCE Modules\juce_gui_basics\native
@@ -3486,6 +3495,9 @@
JUCE Modules\juce_gui_basics\drawables
+
+ JUCE Modules\juce_gui_basics\filebrowser
+
JUCE Modules\juce_gui_basics\filebrowser
diff --git a/modules/juce_core/native/java/AndroidSharingContentProvider.java b/modules/juce_core/native/java/AndroidSharingContentProvider.java
new file mode 100644
index 0000000000..97f7f99409
--- /dev/null
+++ b/modules/juce_core/native/java/AndroidSharingContentProvider.java
@@ -0,0 +1,138 @@
+package com.juce;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.FileObserver;
+import android.os.ParcelFileDescriptor;
+import java.lang.String;
+
+public final class SharingContentProvider extends ContentProvider
+{
+ private Object lock = new Object();
+
+ private native void contentSharerFileObserverEvent (long host, int event, String path);
+
+ private native Cursor contentSharerQuery (Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder);
+
+ private native void contentSharerCursorClosed (long host);
+
+ private native AssetFileDescriptor contentSharerOpenFile (Uri uri, String mode);
+ private native String[] contentSharerGetStreamTypes (Uri uri, String mimeTypeFilter);
+
+ public final class ProviderFileObserver extends FileObserver
+ {
+ public ProviderFileObserver (long hostToUse, String path, int mask)
+ {
+ super (path, mask);
+
+ host = hostToUse;
+ }
+
+ public void onEvent (int event, String path)
+ {
+ contentSharerFileObserverEvent (host, event, path);
+ }
+
+ private long host;
+ }
+
+ public final class ProviderCursor extends MatrixCursor
+ {
+ ProviderCursor (long hostToUse, String[] columnNames)
+ {
+ super (columnNames);
+
+ host = hostToUse;
+ }
+
+ @Override
+ public void close()
+ {
+ super.close();
+
+ contentSharerCursorClosed (host);
+ }
+
+ private long host;
+ }
+
+ @Override
+ public boolean onCreate()
+ {
+ return true;
+ }
+
+ @Override
+ public Cursor query (Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder)
+ {
+ synchronized (lock)
+ {
+ return contentSharerQuery (url, projection, selection, selectionArgs, sortOrder);
+ }
+ }
+
+ @Override
+ public Uri insert (Uri uri, ContentValues values)
+ {
+ return null;
+ }
+
+ @Override
+ public int update (Uri uri, ContentValues values, String selection,
+ String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public int delete (Uri uri, String selection, String[] selectionArgs)
+ {
+ return 0;
+ }
+
+ @Override
+ public String getType (Uri uri)
+ {
+ return null;
+ }
+
+ @Override
+ public AssetFileDescriptor openAssetFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ return contentSharerOpenFile (uri, mode);
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile (Uri uri, String mode)
+ {
+ synchronized (lock)
+ {
+ AssetFileDescriptor result = contentSharerOpenFile (uri, mode);
+
+ if (result != null)
+ return result.getParcelFileDescriptor();
+
+ return null;
+ }
+ }
+$$ContentProviderApi11
+ @Override
+ public String[] getStreamTypes (Uri uri, String mimeTypeFilter)
+ {
+ synchronized (lock)
+ {
+ return contentSharerGetStreamTypes (uri, mimeTypeFilter);
+ }
+ }
+ContentProviderApi11$$
+}
diff --git a/modules/juce_core/native/juce_android_Files.cpp b/modules/juce_core/native/juce_android_Files.cpp
index 5ef671f982..75c52a18d1 100644
--- a/modules/juce_core/native/juce_android_Files.cpp
+++ b/modules/juce_core/native/juce_android_Files.cpp
@@ -56,12 +56,6 @@ DECLARE_JNI_CLASS (AndroidCursor, "android/database/Cursor");
DECLARE_JNI_CLASS (AndroidEnvironment, "android/os/Environment");
#undef JNI_CLASS_MEMBERS
-#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- METHOD (getAbsolutePath, "getAbsolutePath", "()Ljava/lang/String;") \
-
-DECLARE_JNI_CLASS (AndroidFile, "java/io/File");
-#undef JNI_CLASS_MEMBERS
-
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (close, "close", "()V") \
METHOD (flush, "flush", "()V") \
@@ -70,12 +64,6 @@ DECLARE_JNI_CLASS (AndroidFile, "java/io/File");
DECLARE_JNI_CLASS (AndroidOutputStream, "java/io/OutputStream");
#undef JNI_CLASS_MEMBERS
-#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- STATICMETHOD (withAppendedId, "withAppendedId", "(Landroid/net/Uri;J)Landroid/net/Uri;") \
-
-DECLARE_JNI_CLASS (ContentUris, "android/content/ContentUris");
-#undef JNI_CLASS_MEMBERS
-
//==============================================================================
struct AndroidContentUriResolver
{
@@ -167,7 +155,7 @@ private:
if (selection.isNotEmpty())
{
- args = LocalRef (env->NewObjectArray (selectionArgs.size(), JavaString, javaString("").get()));
+ args = LocalRef (env->NewObjectArray (selectionArgs.size(), JavaString, javaString ("").get()));
for (int i = 0; i < selectionArgs.size(); ++i)
env->SetObjectArrayElement (args.get(), i, javaString (selectionArgs[i]).get());
@@ -335,9 +323,9 @@ private:
{
auto* env = getEnv();
- if (env->IsInstanceOf (obj.get(), AndroidFile) != 0)
- return File (safeString (LocalRef (env->CallObjectMethod (obj.get(),
- AndroidFile.getAbsolutePath))));
+ if (env->IsInstanceOf (obj.get(), JavaFile) != 0)
+ return File (juceString (LocalRef ((jstring) env->CallObjectMethod (obj.get(),
+ JavaFile.getAbsolutePath))));
return {};
}
@@ -354,15 +342,8 @@ private:
static LocalRef urlToUri (const URL& url)
{
- return LocalRef (getEnv()->CallStaticObjectMethod (Uri, Uri.parse, javaString (url.toString (true)).get()));
- }
-
- static String safeString (LocalRef str)
- {
- if (str)
- return juceString ((jstring) str.get());
-
- return {};
+ return LocalRef (getEnv()->CallStaticObjectMethod (AndroidUri, AndroidUri.parse,
+ javaString (url.toString (true)).get()));
}
};
@@ -576,7 +557,7 @@ void FileOutputStream::flushInternal()
status = getResultForErrno();
// This stuff tells the OS to asynchronously update the metadata
- // that the OS has cached aboud the file - this metadata is used
+ // that the OS has cached about the file - this metadata is used
// when the device is acting as a USB drive, and unless it's explicitly
// refreshed, it'll get out of step with the real file.
new SingleMediaScanner (file.getFullPathName());
diff --git a/modules/juce_core/native/juce_android_JNIHelpers.h b/modules/juce_core/native/juce_android_JNIHelpers.h
index c965f58809..c0a2b2ad7f 100644
--- a/modules/juce_core/native/juce_android_JNIHelpers.h
+++ b/modules/juce_core/native/juce_android_JNIHelpers.h
@@ -283,49 +283,51 @@ extern AndroidSystem android;
//==============================================================================
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
- METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \
- METHOD (createNativeSurfaceView, "createNativeSurfaceView", "(J)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$NativeSurfaceView;") \
- METHOD (finish, "finish", "()V") \
- METHOD (setRequestedOrientation,"setRequestedOrientation", "(I)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", "(CCLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
- STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;ILjava/lang/String;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
- METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
- METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
- METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V") \
- METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
- STATICMETHOD (getLocaleValue, "getLocaleValue", "(Z)Ljava/lang/String;") \
- STATICMETHOD (getDocumentsFolder, "getDocumentsFolder", "()Ljava/lang/String;") \
- STATICMETHOD (getPicturesFolder, "getPicturesFolder", "()Ljava/lang/String;") \
- STATICMETHOD (getMusicFolder, "getMusicFolder", "()Ljava/lang/String;") \
- STATICMETHOD (getDownloadsFolder, "getDownloadsFolder", "()Ljava/lang/String;") \
- STATICMETHOD (getMoviesFolder, "getMoviesFolder", "()Ljava/lang/String;") \
- METHOD (getTypeFaceFromAsset, "getTypeFaceFromAsset", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
- METHOD (getTypeFaceFromByteArray,"getTypeFaceFromByteArray","([B)Landroid/graphics/Typeface;") \
- METHOD (setScreenSaver, "setScreenSaver", "(Z)V") \
- METHOD (getScreenSaver, "getScreenSaver", "()Z") \
- METHOD (getAndroidMidiDeviceManager, "getAndroidMidiDeviceManager", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$MidiDeviceManager;") \
- METHOD (getAndroidBluetoothManager, "getAndroidBluetoothManager", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$BluetoothManager;") \
- STATICMETHOD (getAndroidSDKVersion, "getAndroidSDKVersion", "()I") \
- METHOD (audioManagerGetProperty, "audioManagerGetProperty", "(Ljava/lang/String;)Ljava/lang/String;") \
- METHOD (hasSystemFeature, "hasSystemFeature", "(Ljava/lang/String;)Z" ) \
- METHOD (requestRuntimePermission, "requestRuntimePermission", "(IJ)V" ) \
- METHOD (isPermissionGranted, "isPermissionGranted", "(I)Z" ) \
+ METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
+ METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \
+ METHOD (createNativeSurfaceView, "createNativeSurfaceView", "(J)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$NativeSurfaceView;") \
+ METHOD (finish, "finish", "()V") \
+ METHOD (setRequestedOrientation, "setRequestedOrientation", "(I)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", "(CCLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
+ STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;ILjava/lang/String;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
+ METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
+ METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V") \
+ METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
+ STATICMETHOD (getLocaleValue, "getLocaleValue", "(Z)Ljava/lang/String;") \
+ STATICMETHOD (getDocumentsFolder, "getDocumentsFolder", "()Ljava/lang/String;") \
+ STATICMETHOD (getPicturesFolder, "getPicturesFolder", "()Ljava/lang/String;") \
+ STATICMETHOD (getMusicFolder, "getMusicFolder", "()Ljava/lang/String;") \
+ STATICMETHOD (getDownloadsFolder, "getDownloadsFolder", "()Ljava/lang/String;") \
+ STATICMETHOD (getMoviesFolder, "getMoviesFolder", "()Ljava/lang/String;") \
+ METHOD (getTypeFaceFromAsset, "getTypeFaceFromAsset", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \
+ METHOD (getTypeFaceFromByteArray, "getTypeFaceFromByteArray", "([B)Landroid/graphics/Typeface;") \
+ METHOD (setScreenSaver, "setScreenSaver", "(Z)V") \
+ METHOD (getScreenSaver, "getScreenSaver", "()Z") \
+ METHOD (getAndroidMidiDeviceManager, "getAndroidMidiDeviceManager", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$MidiDeviceManager;") \
+ METHOD (getAndroidBluetoothManager, "getAndroidBluetoothManager", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$BluetoothManager;") \
+ STATICMETHOD (getAndroidSDKVersion, "getAndroidSDKVersion", "()I") \
+ METHOD (audioManagerGetProperty, "audioManagerGetProperty", "(Ljava/lang/String;)Ljava/lang/String;") \
+ METHOD (hasSystemFeature, "hasSystemFeature", "(Ljava/lang/String;)Z" ) \
+ METHOD (requestRuntimePermission, "requestRuntimePermission", "(IJ)V" ) \
+ METHOD (isPermissionGranted, "isPermissionGranted", "(I)Z" ) \
METHOD (isPermissionDeclaredInManifest, "isPermissionDeclaredInManifest", "(I)Z" ) \
- METHOD (getSystemService, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;") \
- METHOD (getPackageName, "getPackageName", "()Ljava/lang/String;") \
- METHOD (getResources, "getResources", "()Landroid/content/res/Resources;") \
- STATICMETHOD (createInvocationHandler, "createInvocationHandler", "(J)Ljava/lang/reflect/InvocationHandler;") \
- METHOD (bindService, "bindService", "(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z") \
- METHOD (unbindService, "unbindService", "(Landroid/content/ServiceConnection;)V") \
- METHOD (startIntentSenderForResult, "startIntentSenderForResult", "(Landroid/content/IntentSender;ILandroid/content/Intent;III)V") \
- METHOD (moveTaskToBack, "moveTaskToBack", "(Z)Z") \
- METHOD (startActivity, "startActivity", "(Landroid/content/Intent;)V") \
- METHOD (startActivityForResult, "startActivityForResult", "(Landroid/content/Intent;I)V") \
- METHOD (getContentResolver, "getContentResolver", "()Landroid/content/ContentResolver;") \
+ METHOD (getAssets, "getAssets", "()Landroid/content/res/AssetManager;") \
+ METHOD (getSystemService, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;") \
+ METHOD (getPackageManager, "getPackageManager", "()Landroid/content/pm/PackageManager;") \
+ METHOD (getPackageName, "getPackageName", "()Ljava/lang/String;") \
+ METHOD (getResources, "getResources", "()Landroid/content/res/Resources;") \
+ STATICMETHOD (createInvocationHandler, "createInvocationHandler", "(J)Ljava/lang/reflect/InvocationHandler;") \
+ METHOD (bindService, "bindService", "(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z") \
+ METHOD (unbindService, "unbindService", "(Landroid/content/ServiceConnection;)V") \
+ METHOD (startIntentSenderForResult, "startIntentSenderForResult", "(Landroid/content/IntentSender;ILandroid/content/Intent;III)V") \
+ METHOD (moveTaskToBack, "moveTaskToBack", "(Z)Z") \
+ METHOD (startActivity, "startActivity", "(Landroid/content/Intent;)V") \
+ METHOD (startActivityForResult, "startActivityForResult", "(Landroid/content/Intent;I)V") \
+ METHOD (getContentResolver, "getContentResolver", "()Landroid/content/ContentResolver;") \
DECLARE_JNI_CLASS (JuceAppActivity, JUCE_ANDROID_ACTIVITY_CLASSPATH);
#undef JNI_CLASS_MEMBERS
@@ -345,6 +347,7 @@ DECLARE_JNI_CLASS (AndroidBitmapConfig, "android/graphics/Bitmap$Config");
#undef JNI_CLASS_MEMBERS
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (createChooser, "createChooser", "(Landroid/content/Intent;Ljava/lang/CharSequence;)Landroid/content/Intent;") \
METHOD (addCategory, "addCategory", "(Ljava/lang/String;)Landroid/content/Intent;") \
METHOD (constructor, "", "()V") \
METHOD (constructorWithContextAndClass, "", "(Landroid/content/Context;Ljava/lang/Class;)V") \
@@ -355,11 +358,14 @@ DECLARE_JNI_CLASS (AndroidBitmapConfig, "android/graphics/Bitmap$Config");
METHOD (getExtras, "getExtras", "()Landroid/os/Bundle;") \
METHOD (getIntExtra, "getIntExtra", "(Ljava/lang/String;I)I") \
METHOD (getStringExtra, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;") \
+ METHOD (putExtra, "putExtra", "(Ljava/lang/String;Ljava/lang/CharSequence;)Landroid/content/Intent;") \
METHOD (putExtras, "putExtras", "(Landroid/os/Bundle;)Landroid/content/Intent;") \
METHOD (putExtraString, "putExtra", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;") \
METHOD (putExtraStrings, "putExtra", "(Ljava/lang/String;[Ljava/lang/String;)Landroid/content/Intent;") \
METHOD (putExtraParcelable, "putExtra", "(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;") \
+ METHOD (putParcelableArrayListExtra, "putParcelableArrayListExtra", "(Ljava/lang/String;Ljava/util/ArrayList;)Landroid/content/Intent;") \
METHOD (setAction, "setAction", "(Ljava/lang/String;)Landroid/content/Intent;") \
+ METHOD (setFlags, "setFlags", "(I)Landroid/content/Intent;") \
METHOD (setPackage, "setPackage", "(Ljava/lang/String;)Landroid/content/Intent;") \
METHOD (setType, "setType", "(Ljava/lang/String;)Landroid/content/Intent;") \
@@ -373,6 +379,12 @@ DECLARE_JNI_CLASS (AndroidIntent, "android/content/Intent");
DECLARE_JNI_CLASS (AndroidMatrix, "android/graphics/Matrix");
#undef JNI_CLASS_MEMBERS
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (getPackageInfo, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;")
+
+DECLARE_JNI_CLASS (AndroidPackageManager, "android/content/pm/PackageManager");
+#undef JNI_CLASS_MEMBERS
+
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (constructor, "", "(I)V") \
METHOD (setColor, "setColor", "(I)V") \
@@ -407,7 +419,8 @@ DECLARE_JNI_CLASS (AndroidRectClass, "android/graphics/Rect");
#undef JNI_CLASS_MEMBERS
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- METHOD (getIdentifier, "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I")
+ METHOD (getIdentifier, "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I") \
+ METHOD (openRawResourceFd, "openRawResourceFd", "(I)Landroid/content/res/AssetFileDescriptor;")
DECLARE_JNI_CLASS (AndroidResources, "android/content/res/Resources")
#undef JNI_CLASS_MEMBERS
@@ -504,6 +517,30 @@ DECLARE_JNI_CLASS (JavaCharSequence, "java/lang/CharSequence");
DECLARE_JNI_CLASS (JavaClass, "java/lang/Class");
#undef JNI_CLASS_MEMBERS
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Ljava/lang/String;)V") \
+ METHOD (getAbsolutePath, "getAbsolutePath", "()Ljava/lang/String;") \
+ METHOD (length, "length", "()J")
+
+DECLARE_JNI_CLASS (JavaFile, "java/io/File");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Ljava/lang/String;)V") \
+ METHOD (close, "close", "()V") \
+ METHOD (read, "read", "([B)I")
+
+DECLARE_JNI_CLASS (JavaFileInputStream, "java/io/FileInputStream");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Ljava/lang/String;)V") \
+ METHOD (close, "close", "()V") \
+ METHOD (write, "write", "([BII)V")
+
+DECLARE_JNI_CLASS (JavaFileOutputStream, "java/io/FileOutputStream");
+#undef JNI_CLASS_MEMBERS
+
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (constructor, "", "()V") \
METHOD (constructorWithCapacity, "", "(I)V")
@@ -524,6 +561,12 @@ DECLARE_JNI_CLASS (JavaInteger, "java/lang/Integer");
DECLARE_JNI_CLASS (JavaIterator, "java/util/Iterator");
#undef JNI_CLASS_MEMBERS
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(J)V")
+
+DECLARE_JNI_CLASS (JavaLong, "java/lang/Long");
+#undef JNI_CLASS_MEMBERS
+
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (get, "get", "(Ljava/lang/Object;)Ljava/lang/Object;") \
METHOD (keySet, "keySet", "()Ljava/util/Set;") \
@@ -568,13 +611,6 @@ DECLARE_JNI_CLASS (JavaSet, "java/util/Set");
DECLARE_JNI_CLASS (JavaString, "java/lang/String");
#undef JNI_CLASS_MEMBERS
-#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
- STATICMETHOD (parse, "parse", "(Ljava/lang/String;)Landroid/net/Uri;") \
- METHOD (getAuthority, "getAuthority", "()Ljava/lang/String;") \
-
-DECLARE_JNI_CLASS (Uri, "android/net/Uri");
-#undef JNI_CLASS_MEMBERS
-
//==============================================================================
class AndroidInterfaceImplementer;
diff --git a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp
new file mode 100644
index 0000000000..82c7bd8221
--- /dev/null
+++ b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp
@@ -0,0 +1,281 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ By using JUCE, you agree to the terms of both the JUCE 5 End-User License
+ Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
+ 27th April 2017).
+
+ End User License Agreement: www.juce.com/juce-5-licence
+ Privacy Policy: www.juce.com/juce-5-privacy-policy
+
+ Or: You may also use this code under the terms of the GPL v3 (see
+ www.gnu.org/licenses).
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+namespace juce
+{
+
+#if JUCE_IOS || JUCE_ANDROID
+//==============================================================================
+class ContentSharer::PrepareImagesThread : private Thread
+{
+public:
+ PrepareImagesThread (ContentSharer& cs, const Array& imagesToUse,
+ ImageFileFormat* imageFileFormatToUse)
+ : Thread ("ContentSharer::PrepareImagesThread"),
+ owner (cs),
+ images (imagesToUse),
+ imageFileFormat (imageFileFormatToUse == nullptr ? new PNGImageFormat()
+ : imageFileFormatToUse),
+ extension (imageFileFormat->getFormatName().toLowerCase())
+ {
+ startThread();
+ }
+
+ ~PrepareImagesThread()
+ {
+ signalThreadShouldExit();
+ waitForThreadToExit (10000);
+ }
+
+private:
+ void run() override
+ {
+ for (const auto& image : images)
+ {
+ if (threadShouldExit())
+ return;
+
+ File tempFile = File::createTempFile (extension);
+
+ if (! tempFile.create().wasOk())
+ break;
+
+ ScopedPointer outputStream = tempFile.createOutputStream();
+
+ if (outputStream == nullptr)
+ break;
+
+ if (imageFileFormat->writeImageToStream (image, *outputStream))
+ owner.temporaryFiles.add (tempFile);
+ }
+
+ finish();
+ }
+
+ void finish()
+ {
+ MessageManager::callAsync ([this] () { owner.filesToSharePrepared(); });
+ }
+
+ ContentSharer& owner;
+ const Array images;
+ ScopedPointer imageFileFormat;
+ String extension;
+};
+
+//==============================================================================
+class ContentSharer::PrepareDataThread : private Thread
+{
+public:
+ PrepareDataThread (ContentSharer& cs, const MemoryBlock& mb)
+ : Thread ("ContentSharer::PrepareDataThread"),
+ owner (cs),
+ data (mb)
+ {
+ startThread();
+ }
+
+ ~PrepareDataThread()
+ {
+ signalThreadShouldExit();
+ waitForThreadToExit (10000);
+ }
+
+private:
+ void run() override
+ {
+ File tempFile = File::createTempFile ("data");
+
+ if (tempFile.create().wasOk())
+ {
+ ScopedPointer outputStream = tempFile.createOutputStream();
+
+ if (outputStream != nullptr)
+ {
+ size_t pos = 0;
+ size_t totalSize = data.getSize();
+
+ while (pos < totalSize)
+ {
+ if (threadShouldExit())
+ return;
+
+ size_t numToWrite = std::min ((size_t) 8192, totalSize - pos);
+
+ outputStream->write (data.begin() + pos, numToWrite);
+
+ pos += numToWrite;
+ }
+
+ owner.temporaryFiles.add (tempFile);
+ }
+ }
+
+ finish();
+ }
+
+ void finish()
+ {
+ MessageManager::callAsync ([this] () { owner.filesToSharePrepared(); });
+ }
+
+ ContentSharer& owner;
+ const MemoryBlock data;
+};
+#endif
+
+//==============================================================================
+juce_ImplementSingleton (ContentSharer)
+
+ContentSharer::ContentSharer() {}
+ContentSharer::~ContentSharer() { clearSingletonInstance(); }
+
+void ContentSharer::shareFiles (const Array& files,
+ std::function callbackToUse)
+{
+ #if JUCE_IOS || JUCE_ANDROID
+ startNewShare (callbackToUse);
+ pimpl->shareFiles (files);
+ #else
+ ignoreUnused (files);
+
+ // Content sharing is not available on this platform!
+ jassertfalse;
+
+ if (callbackToUse)
+ callbackToUse (false, "Content sharing is not available on this platform!");
+ #endif
+}
+
+#if JUCE_IOS || JUCE_ANDROID
+void ContentSharer::startNewShare (std::function callbackToUse)
+{
+ // You should not start another sharing operation before the previous one is finished.
+ // Forcibly stopping a previous sharing operation is rarely a good idea!
+ jassert (pimpl == nullptr);
+ pimpl = nullptr;
+
+ prepareDataThread = nullptr;
+ prepareImagesThread = nullptr;
+
+ deleteTemporaryFiles();
+
+ // You need to pass a valid callback.
+ jassert (callbackToUse);
+ callback = static_cast&&> (callbackToUse);
+
+ pimpl = createPimpl();
+}
+#endif
+
+void ContentSharer::shareText (const String& text,
+ std::function callbackToUse)
+{
+ #if JUCE_IOS || JUCE_ANDROID
+ startNewShare (callbackToUse);
+ pimpl->shareText (text);
+ #else
+ ignoreUnused (text);
+
+ // Content sharing is not available on this platform!
+ jassertfalse;
+
+ if (callbackToUse)
+ callbackToUse (false, "Content sharing is not available on this platform!");
+ #endif
+}
+
+void ContentSharer::shareImages (const Array& images,
+ std::function callbackToUse,
+ ImageFileFormat* imageFileFormatToUse)
+{
+ #if JUCE_IOS || JUCE_ANDROID
+ startNewShare (callbackToUse);
+ prepareImagesThread = new PrepareImagesThread (*this, images, imageFileFormatToUse);
+ #else
+ ignoreUnused (images, imageFileFormatToUse);
+
+ // Content sharing is not available on this platform!
+ jassertfalse;
+
+ if (callbackToUse)
+ callbackToUse (false, "Content sharing is not available on this platform!");
+ #endif
+}
+
+#if JUCE_IOS || JUCE_ANDROID
+void ContentSharer::filesToSharePrepared()
+{
+ Array urls;
+
+ for (const auto& tempFile : temporaryFiles)
+ urls.add (URL (tempFile));
+
+ prepareImagesThread = nullptr;
+ prepareDataThread = nullptr;
+
+ pimpl->shareFiles (urls);
+}
+#endif
+
+void ContentSharer::shareData (const MemoryBlock& mb,
+ std::function callbackToUse)
+{
+ #if JUCE_IOS || JUCE_ANDROID
+ startNewShare (callbackToUse);
+ prepareDataThread = new PrepareDataThread (*this, mb);
+ #else
+ ignoreUnused (mb);
+
+ if (callbackToUse)
+ callbackToUse (false, "Content sharing not available on this platform!");
+ #endif
+}
+
+void ContentSharer::sharingFinished (bool succeeded, const String& errorDescription)
+{
+ deleteTemporaryFiles();
+
+ std::function cb;
+ std::swap (cb, callback);
+
+ #if JUCE_IOS || JUCE_ANDROID
+ pimpl = nullptr;
+ #endif
+
+ if (cb)
+ cb (succeeded, errorDescription);
+}
+
+void ContentSharer::deleteTemporaryFiles()
+{
+ for (auto& f : temporaryFiles)
+ f.deleteFile();
+
+ temporaryFiles.clear();
+}
+
+} // namespace juce
diff --git a/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h
new file mode 100644
index 0000000000..091268b08e
--- /dev/null
+++ b/modules/juce_gui_basics/filebrowser/juce_ContentSharer.h
@@ -0,0 +1,149 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ By using JUCE, you agree to the terms of both the JUCE 5 End-User License
+ Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
+ 27th April 2017).
+
+ End User License Agreement: www.juce.com/juce-5-licence
+ Privacy Policy: www.juce.com/juce-5-privacy-policy
+
+ Or: You may also use this code under the terms of the GPL v3 (see
+ www.gnu.org/licenses).
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+#pragma once
+
+namespace juce
+{
+
+/** A singleton class responsible for sharing content between apps and devices.
+
+ You can share text, images, files or an arbitrary data block.
+*/
+class JUCE_API ContentSharer
+{
+public:
+ juce_DeclareSingleton (ContentSharer, false)
+
+ /** Shares the given files. Each URL should be either a full file path
+ or it should point to a resource within the application bundle. For
+ resources on iOS it should be something like "content/image.png" if you
+ want to specify a file from application bundle located in "content"
+ directory. On Android you should specify only a filename, without an
+ extension.
+
+ Upon completion you will receive a callback with a sharing result. Note:
+ Sadly on Android the returned success flag may be wrong as there is no
+ standard way the sharing targets report if the sharing operation
+ succeeded. Also, the optional error message is always empty on Android.
+ */
+ void shareFiles (const Array& files,
+ std::function callback);
+
+ /** Shares the given text.
+
+ Upon completion you will receive a callback with a sharing result. Note:
+ Sadly on Android the returned success flag may be wrong as there is no
+ standard way the sharing targets report if the sharing operation
+ succeeded. Also, the optional error message is always empty on Android.
+ */
+ void shareText (const String& text,
+ std::function callback);
+
+ /** A convenience function to share an image. This is useful when you have images
+ loaded in memory. The images will be written to temporary files first, so if
+ you have the images in question stored on disk already call shareFiles() instead.
+ By default, images will be saved to PNG files, but you can supply a custom
+ ImageFileFormat to override this. The custom file format will be owned and
+ deleted by the sharer. e.g.
+
+ @code
+ Graphics g (myImage);
+ g.setColour (Colours::green);
+ g.fillEllipse (20, 20, 300, 200);
+ Array images;
+ images.add (myImage);
+ ContentSharer::getInstance()->shareImages (images);
+ @endcode
+
+ Upon completion you will receive a callback with a sharing result. Note:
+ Sadly on Android the returned success flag may be wrong as there is no
+ standard way the sharing targets report if the sharing operation
+ succeeded. Also, the optional error message is always empty on Android.
+ */
+ void shareImages (const Array& images,
+ std::function callback,
+ ImageFileFormat* imageFileFormatToUse = nullptr);
+
+ /** A convenience function to share arbitrary data. The data will be written
+ to a temporary file and then that file will be shared. If you have
+ your data stored on disk already, call shareFiles() instead.
+
+ Upon completion you will receive a callback with a sharing result. Note:
+ Sadly on Android the returned success flag may be wrong as there is no
+ standard way the sharing targets report if the sharing operation
+ succeeded. Also, the optional error message is always empty on Android.
+ */
+ void shareData (const MemoryBlock& mb,
+ std::function callback);
+
+private:
+ ContentSharer();
+ ~ContentSharer();
+
+ Array temporaryFiles;
+
+ std::function callback;
+
+ #if JUCE_IOS || JUCE_ANDROID
+ struct Pimpl
+ {
+ virtual ~Pimpl() {}
+ virtual void shareFiles (const Array& files) = 0;
+ virtual void shareText (const String& text) = 0;
+ };
+
+ ScopedPointer pimpl;
+ Pimpl* createPimpl();
+
+ void startNewShare (std::function);
+
+ class ContentSharerNativeImpl;
+ friend class ContentSharerNativeImpl;
+
+ class PrepareImagesThread;
+ friend class PrepareImagesThread;
+ ScopedPointer prepareImagesThread;
+
+ class PrepareDataThread;
+ friend class PrepareDataThread;
+ ScopedPointer prepareDataThread;
+
+ void filesToSharePrepared();
+ #endif
+
+ void deleteTemporaryFiles();
+ void sharingFinished (bool, const String&);
+
+ #if JUCE_ANDROID
+ friend void* juce_contentSharerOpenFile (void*, void*, void*);
+ friend void* juce_contentSharerQuery (void*, void*, void*, void*, void*, void*);
+ friend void* juce_contentSharerGetStreamTypes (void*, void*);
+ friend void juce_contentSharingCompleted (int);
+ #endif
+};
+
+} // namespace juce
diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp
index 11684107d5..3645f52222 100644
--- a/modules/juce_gui_basics/juce_gui_basics.cpp
+++ b/modules/juce_gui_basics/juce_gui_basics.cpp
@@ -58,6 +58,8 @@
#import
#endif
+ #import
+
//==============================================================================
#elif JUCE_WINDOWS
#include
@@ -191,6 +193,7 @@ namespace juce
#include "filebrowser/juce_FileSearchPathListComponent.cpp"
#include "filebrowser/juce_FileTreeComponent.cpp"
#include "filebrowser/juce_ImagePreviewComponent.cpp"
+#include "filebrowser/juce_ContentSharer.cpp"
#include "layout/juce_ComponentAnimator.cpp"
#include "layout/juce_ComponentBoundsConstrainer.cpp"
#include "layout/juce_ComponentBuilder.cpp"
@@ -290,6 +293,7 @@ namespace juce
#include "native/juce_ios_UIViewComponentPeer.mm"
#include "native/juce_ios_Windowing.mm"
#include "native/juce_ios_FileChooser.mm"
+ #include "native/juce_ios_ContentSharer.cpp"
#else
#include "native/juce_mac_NSViewComponentPeer.mm"
#include "native/juce_mac_Windowing.mm"
@@ -318,5 +322,6 @@ namespace juce
#include "native/juce_android_Windowing.cpp"
#include "native/juce_common_MimeTypes.cpp"
#include "native/juce_android_FileChooser.cpp"
+ #include "native/juce_android_ContentSharer.cpp"
#endif
diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h
index 90f34e35a1..bc1240224d 100644
--- a/modules/juce_gui_basics/juce_gui_basics.h
+++ b/modules/juce_gui_basics/juce_gui_basics.h
@@ -279,6 +279,7 @@ namespace juce
#include "filebrowser/juce_FileSearchPathListComponent.h"
#include "filebrowser/juce_FileTreeComponent.h"
#include "filebrowser/juce_ImagePreviewComponent.h"
+#include "filebrowser/juce_ContentSharer.h"
#include "properties/juce_PropertyComponent.h"
#include "properties/juce_BooleanPropertyComponent.h"
#include "properties/juce_ButtonPropertyComponent.h"
diff --git a/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp b/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp
new file mode 100644
index 0000000000..c0223c5255
--- /dev/null
+++ b/modules/juce_gui_basics/native/juce_android_ContentSharer.cpp
@@ -0,0 +1,862 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ By using JUCE, you agree to the terms of both the JUCE 5 End-User License
+ Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
+ 27th April 2017).
+
+ End User License Agreement: www.juce.com/juce-5-licence
+ Privacy Policy: www.juce.com/juce-5-privacy-policy
+
+ Or: You may also use this code under the terms of the GPL v3 (see
+ www.gnu.org/licenses).
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+namespace juce
+{
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ FIELD (providers, "providers", "[Landroid/content/pm/ProviderInfo;")
+
+DECLARE_JNI_CLASS (AndroidPackageInfo, "android/content/pm/PackageInfo");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ FIELD (authority, "authority", "Ljava/lang/String;")
+
+DECLARE_JNI_CLASS (AndroidProviderInfo, "android/content/pm/ProviderInfo");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(Landroid/os/ParcelFileDescriptor;JJ)V") \
+ METHOD (createInputStream, "createInputStream", "()Ljava/io/FileInputStream;") \
+ METHOD (getLength, "getLength", "()J")
+
+DECLARE_JNI_CLASS (AssetFileDescriptor, "android/content/res/AssetFileDescriptor");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (close, "close", "()V")
+
+DECLARE_JNI_CLASS (JavaCloseable, "java/io/Closeable");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (constructor, "", "(L" JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH ";JLjava/lang/String;I)V") \
+ METHOD (startWatching, "startWatching", "()V") \
+ METHOD (stopWatching, "stopWatching", "()V")
+
+DECLARE_JNI_CLASS (JuceContentProviderFileObserver, JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH "$ProviderFileObserver");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ METHOD (addRow, "addRow", "([Ljava/lang/Object;)V") \
+ METHOD (constructor, "", "(L" JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH ";J[Ljava/lang/String;)V")
+
+DECLARE_JNI_CLASS (JuceContentProviderFileObserverCursor, JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSPATH "$ProviderCursor");
+#undef JNI_CLASS_MEMBERS
+
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
+ STATICMETHOD (open, "open", "(Ljava/io/File;I)Landroid/os/ParcelFileDescriptor;")
+
+DECLARE_JNI_CLASS (ParcelFileDescriptor, "android/os/ParcelFileDescriptor");
+#undef JNI_CLASS_MEMBERS
+
+//==============================================================================
+class AndroidContentSharerCursor
+{
+public:
+ class Owner
+ {
+ public:
+ virtual ~Owner() {}
+
+ virtual void cursorClosed (const AndroidContentSharerCursor&) = 0;
+ };
+
+ AndroidContentSharerCursor (Owner& ownerToUse, JNIEnv* env,
+ const LocalRef& contentProvider,
+ const LocalRef& resultColumns)
+ : owner (ownerToUse),
+ cursor (GlobalRef (LocalRef (env->NewObject (JuceContentProviderFileObserverCursor,
+ JuceContentProviderFileObserverCursor.constructor,
+ contentProvider.get(),
+ reinterpret_cast (this),
+ resultColumns.get()))))
+ {
+ // the content provider must be created first
+ jassert (contentProvider.get() != 0);
+ }
+
+ jobject getNativeCursor() { return cursor.get(); }
+
+ void cursorClosed()
+ {
+ MessageManager::callAsync ([this] { owner.cursorClosed (*this); });
+ }
+
+private:
+ Owner& owner;
+ GlobalRef cursor;
+};
+
+//==============================================================================
+class AndroidContentSharerFileObserver
+{
+public:
+ class Owner
+ {
+ public:
+ virtual ~Owner() {}
+
+ virtual void fileHandleClosed (const AndroidContentSharerFileObserver&) = 0;
+ };
+
+ AndroidContentSharerFileObserver (Owner& ownerToUse, JNIEnv* env,
+ const LocalRef& contentProvider,
+ const String& filepathToUse)
+ : owner (ownerToUse),
+ filepath (filepathToUse),
+ fileObserver (GlobalRef (LocalRef (env->NewObject (JuceContentProviderFileObserver,
+ JuceContentProviderFileObserver.constructor,
+ contentProvider.get(),
+ reinterpret_cast (this),
+ javaString (filepath).get(),
+ open | access | closeWrite | closeNoWrite))))
+ {
+ // the content provider must be created first
+ jassert (contentProvider.get() != 0);
+
+ env->CallVoidMethod (fileObserver, JuceContentProviderFileObserver.startWatching);
+ }
+
+ void onFileEvent (int event, const LocalRef& path)
+ {
+ ignoreUnused (path);
+
+ if (event == open)
+ {
+ ++numOpenedHandles;
+ }
+ else if (event == access)
+ {
+ fileWasRead = true;
+ }
+ else if (event == closeNoWrite || event == closeWrite)
+ {
+ --numOpenedHandles;
+
+ if (fileWasRead && numOpenedHandles == 0)
+ {
+ MessageManager::callAsync ([this]
+ {
+ getEnv()->CallVoidMethod (fileObserver, JuceContentProviderFileObserver.stopWatching);
+ owner.fileHandleClosed (*this);
+ });
+ }
+ }
+ }
+
+private:
+ static constexpr int open = 32;
+ static constexpr int access = 1;
+ static constexpr int closeWrite = 8;
+ static constexpr int closeNoWrite = 16;
+
+ bool fileWasRead = false;
+ int numOpenedHandles = 0;
+
+ Owner& owner;
+ String filepath;
+ GlobalRef fileObserver;
+};
+
+//==============================================================================
+class AndroidContentSharerPrepareFilesThread : private Thread
+{
+public:
+ AndroidContentSharerPrepareFilesThread (AsyncUpdater& ownerToUse,
+ const Array& fileUrlsToUse,
+ const String& packageNameToUse,
+ const String& uriBaseToUse)
+ : Thread ("AndroidContentSharerPrepareFilesThread"),
+ owner (ownerToUse),
+ fileUrls (fileUrlsToUse),
+ resultFileUris (GlobalRef (LocalRef (getEnv()->NewObject (JavaArrayList,
+ JavaArrayList.constructor,
+ fileUrls.size())))),
+ packageName (packageNameToUse),
+ uriBase (uriBaseToUse)
+ {
+ startThread();
+ }
+
+ ~AndroidContentSharerPrepareFilesThread()
+ {
+ signalThreadShouldExit();
+ waitForThreadToExit (10000);
+
+ for (auto& f : temporaryFilesFromAssetFiles)
+ f.deleteFile();
+ }
+
+ jobject getResultFileUris() { return resultFileUris.get(); }
+ const StringArray& getMimeTypes() const { return mimeTypes; }
+ const StringArray& getFilePaths() const { return filePaths; }
+
+private:
+ struct StreamCloser
+ {
+ StreamCloser (jobject streamToUse)
+ : stream (GlobalRef (streamToUse))
+ {
+ }
+
+ ~StreamCloser()
+ {
+ if (stream.get() != 0)
+ getEnv()->CallVoidMethod (stream, JavaCloseable.close);
+ }
+
+ GlobalRef stream;
+ };
+
+ void run() override
+ {
+ auto* env = getEnv();
+
+ bool canSpecifyMimeTypes = true;
+
+ for (auto f : fileUrls)
+ {
+ auto scheme = f.getScheme();
+
+ // Only "file://" scheme or no scheme (for files in app bundle) are allowed!
+ jassert (scheme.isEmpty() || scheme == "file");
+
+ if (scheme.isEmpty())
+ {
+ // Raw resource names need to be all lower case
+ jassert (f.toString (true).toLowerCase() == f.toString (true));
+
+ // This will get us a file with file:// URI
+ f = copyAssetFileToTemporaryFile (env, f.toString (true));
+
+ if (f.isEmpty())
+ continue;
+ }
+
+ if (threadShouldExit())
+ return;
+
+ auto filepath = f.toString (true).fromFirstOccurrenceOf ("file://", false, false);
+
+ filePaths.add (filepath);
+
+ auto filename = filepath.fromLastOccurrenceOf ("/", false, true);
+ auto fileExtension = filename.fromLastOccurrenceOf (".", false, true);
+ auto contentString = uriBase + String (filePaths.size() - 1) + "/" + filename;
+
+ auto uri = LocalRef (env->CallStaticObjectMethod (AndroidUri, AndroidUri.parse,
+ javaString (contentString).get()));
+
+ if (canSpecifyMimeTypes)
+ canSpecifyMimeTypes = fileExtension.isNotEmpty();
+
+ if (canSpecifyMimeTypes)
+ mimeTypes.addArray (getMimeTypesForFileExtension (fileExtension));
+ else
+ mimeTypes.clear();
+
+ env->CallBooleanMethod (resultFileUris, JavaArrayList.add, uri.get());
+ }
+
+ owner.triggerAsyncUpdate();
+ }
+
+ URL copyAssetFileToTemporaryFile (JNIEnv* env, const String& filename)
+ {
+ auto resources = LocalRef (env->CallObjectMethod (android.activity, JuceAppActivity.getResources));
+ int fileId = env->CallIntMethod (resources, AndroidResources.getIdentifier, javaString (filename).get(),
+ javaString ("raw").get(), javaString (packageName).get());
+
+ // Raw resource not found. Please make sure that you include your file as a raw resource
+ // and that you specify just the file name, without an extention.
+ jassert (fileId != 0);
+
+ if (fileId == 0)
+ return {};
+
+ auto assetFd = LocalRef (env->CallObjectMethod (resources,
+ AndroidResources.openRawResourceFd,
+ fileId));
+
+ auto inputStream = StreamCloser (LocalRef (env->CallObjectMethod (assetFd,
+ AssetFileDescriptor.createInputStream)));
+
+ auto exception = LocalRef (env->ExceptionOccurred());
+
+ if (exception != 0)
+ {
+ // Failed to open file stream for resource
+ jassertfalse;
+
+ env->ExceptionClear();
+ return {};
+ }
+
+ auto tempFile = File::createTempFile ({});
+ tempFile.createDirectory();
+ tempFile = tempFile.getChildFile (filename);
+
+ auto outputStream = StreamCloser (LocalRef (env->NewObject (JavaFileOutputStream,
+ JavaFileOutputStream.constructor,
+ javaString (tempFile.getFullPathName()).get())));
+
+ exception = LocalRef (env->ExceptionOccurred());
+
+ if (exception != 0)
+ {
+ // Failed to open file stream for temporary file
+ jassertfalse;
+
+ env->ExceptionClear();
+ return {};
+ }
+
+ auto buffer = LocalRef (env->NewByteArray (1024));
+ int bytesRead = 0;
+
+ while (true)
+ {
+ if (threadShouldExit())
+ return {};
+
+ bytesRead = env->CallIntMethod (inputStream.stream, JavaFileInputStream.read, buffer.get());
+
+ exception = LocalRef (env->ExceptionOccurred());
+
+ if (exception != 0)
+ {
+ // Failed to read from resource file.
+ jassertfalse;
+
+ env->ExceptionClear();
+ return {};
+ }
+
+ if (bytesRead < 0)
+ break;
+
+ env->CallVoidMethod (outputStream.stream, JavaFileOutputStream.write, buffer.get(), 0, bytesRead);
+
+ if (exception != 0)
+ {
+ // Failed to write to temporary file.
+ jassertfalse;
+
+ env->ExceptionClear();
+ return {};
+ }
+ }
+
+ temporaryFilesFromAssetFiles.add (tempFile);
+
+ return URL (tempFile);
+ }
+
+ AsyncUpdater& owner;
+ Array fileUrls;
+
+ GlobalRef resultFileUris;
+ String packageName;
+ String uriBase;
+
+ StringArray filePaths;
+ Array temporaryFilesFromAssetFiles;
+ StringArray mimeTypes;
+};
+
+//==============================================================================
+class ContentSharer::ContentSharerNativeImpl : public ContentSharer::Pimpl,
+ public AndroidContentSharerFileObserver::Owner,
+ public AndroidContentSharerCursor::Owner,
+ public AsyncUpdater,
+ private Timer
+{
+public:
+ ContentSharerNativeImpl (ContentSharer& cs)
+ : owner (cs),
+ packageName (juceString (LocalRef ((jstring) getEnv()->CallObjectMethod (android.activity,
+ JuceAppActivity.getPackageName)))),
+ uriBase ("content://" + packageName + ".sharingcontentprovider/")
+ {
+ }
+
+ ~ContentSharerNativeImpl()
+ {
+ masterReference.clear();
+ }
+
+ void shareFiles (const Array& files) override
+ {
+ if (! isContentSharingEnabled())
+ {
+ // You need to enable "Content Sharing" in Projucer's Android exporter.
+ jassertfalse;
+ owner.sharingFinished (false, {});
+ }
+
+ prepareFilesThread = new AndroidContentSharerPrepareFilesThread (*this, files, packageName, uriBase);
+ }
+
+ void shareText (const String& text) override
+ {
+ if (! isContentSharingEnabled())
+ {
+ // You need to enable "Content Sharing" in Projucer's Android exporter.
+ jassertfalse;
+ owner.sharingFinished (false, {});
+ }
+
+ auto* env = getEnv();
+
+ auto intent = LocalRef (env->NewObject (AndroidIntent, AndroidIntent.constructor));
+ env->CallObjectMethod (intent, AndroidIntent.setAction,
+ javaString ("android.intent.action.SEND").get());
+ env->CallObjectMethod (intent, AndroidIntent.putExtra,
+ javaString ("android.intent.extra.TEXT").get(),
+ javaString (text).get());
+ env->CallObjectMethod (intent, AndroidIntent.setType, javaString ("text/plain").get());
+
+ auto chooserIntent = LocalRef (env->CallStaticObjectMethod (AndroidIntent, AndroidIntent.createChooser,
+ intent.get(), javaString ("Choose share target").get()));
+
+ env->CallVoidMethod (android.activity, JuceAppActivity.startActivityForResult, chooserIntent.get(), 1003);
+ }
+
+ //==============================================================================
+ void cursorClosed (const AndroidContentSharerCursor& cursor) override
+ {
+ cursors.removeObject (&cursor);
+ }
+
+ void fileHandleClosed (const AndroidContentSharerFileObserver&) override
+ {
+ decrementPendingFileCountAndNotifyOwnerIfReady();
+ }
+
+ //==============================================================================
+ void* openFile (const LocalRef& contentProvider,
+ const LocalRef& uri, const LocalRef& mode)
+ {
+ ignoreUnused (mode);
+
+ WeakReference weakRef (this);
+
+ if (weakRef == nullptr)
+ return nullptr;
+
+ auto* env = getEnv();
+
+ auto uriElements = getContentUriElements (env, uri);
+
+ if (uriElements.filepath.isEmpty())
+ return nullptr;
+
+ return getAssetFileDescriptor (env, contentProvider, uriElements.filepath);
+ }
+
+ void* query (const LocalRef& contentProvider, const LocalRef& uri,
+ const LocalRef& projection, const LocalRef& selection,
+ const LocalRef& selectionArgs, const LocalRef& sortOrder)
+ {
+ ignoreUnused (selection, selectionArgs, sortOrder);
+
+ StringArray requestedColumns = javaStringArrayToJuceStringArray (projection);
+ StringArray supportedColumns = getSupportedColumns();
+
+ StringArray resultColumns;
+
+ for (const auto& col : supportedColumns)
+ {
+ if (requestedColumns.contains (col))
+ resultColumns.add (col);
+ }
+
+ // Unsupported columns were queried, file sharing may fail.
+ if (resultColumns.isEmpty())
+ return nullptr;
+
+ auto resultJavaColumns = juceStringArrayToJavaStringArray (resultColumns);
+
+ auto* env = getEnv();
+
+ auto cursor = cursors.add (new AndroidContentSharerCursor (*this, env, contentProvider,
+ resultJavaColumns));
+
+ auto uriElements = getContentUriElements (env, uri);
+
+ if (uriElements.filepath.isEmpty())
+ return cursor->getNativeCursor();
+
+ auto values = LocalRef (env->NewObjectArray ((jsize) resultColumns.size(),
+ JavaObject, 0));
+
+ for (int i = 0; i < resultColumns.size(); ++i)
+ {
+ if (resultColumns.getReference (i) == "_display_name")
+ {
+ env->SetObjectArrayElement (values, i, javaString (uriElements.filename).get());
+ }
+ else if (resultColumns.getReference (i) == "_size")
+ {
+ auto javaFile = LocalRef (env->NewObject (JavaFile, JavaFile.constructor,
+ javaString (uriElements.filepath).get()));
+
+ jlong fileLength = env->CallLongMethod (javaFile, JavaFile.length);
+
+ env->SetObjectArrayElement (values, i, env->NewObject (JavaLong,
+ JavaLong.constructor,
+ fileLength));
+ }
+ }
+
+ auto nativeCursor = cursor->getNativeCursor();
+ env->CallVoidMethod (nativeCursor, JuceContentProviderFileObserverCursor.addRow, values.get());
+
+ return nativeCursor;
+ }
+
+ void* getStreamTypes (const LocalRef& uri, const LocalRef& mimeTypeFilter)
+ {
+ auto* env = getEnv();
+
+ auto extension = getContentUriElements (env, uri).filename.fromLastOccurrenceOf (".", false, true);
+
+ if (extension.isEmpty())
+ return nullptr;
+
+ return juceStringArrayToJavaStringArray (filterMimeTypes (getMimeTypesForFileExtension (extension),
+ juceString (mimeTypeFilter.get())));
+ }
+
+ void sharingFinished (int resultCode)
+ {
+ sharingActivityDidFinish = true;
+
+ succeeded = resultCode == -1;
+
+ // Give content sharer a chance to request file access.
+ if (nonAssetFilesPendingShare.get() == 0)
+ startTimer (2000);
+ else
+ notifyOwnerIfReady();
+ }
+
+private:
+ bool isContentSharingEnabled() const
+ {
+ auto* env = getEnv();
+
+ auto packageManager = LocalRef (env->CallObjectMethod (android.activity,
+ JuceAppActivity.getPackageManager));
+
+ constexpr int getProviders = 8;
+ auto packageInfo = LocalRef (env->CallObjectMethod (packageManager,
+ AndroidPackageManager.getPackageInfo,
+ javaString (packageName).get(),
+ getProviders));
+ auto providers = LocalRef ((jobjectArray) env->GetObjectField (packageInfo,
+ AndroidPackageInfo.providers));
+
+ if (providers == nullptr)
+ return false;
+
+ auto sharingContentProviderAuthority = packageName + ".sharingcontentprovider";
+ const int numProviders = env->GetArrayLength (providers.get());
+
+ for (int i = 0; i < numProviders; ++i)
+ {
+ auto providerInfo = LocalRef (env->GetObjectArrayElement (providers, i));
+ auto authority = LocalRef ((jstring) env->GetObjectField (providerInfo,
+ AndroidProviderInfo.authority));
+
+ if (juceString (authority) == sharingContentProviderAuthority)
+ return true;
+ }
+
+ return false;
+ }
+
+ void handleAsyncUpdate() override
+ {
+ jassert (prepareFilesThread != nullptr);
+
+ if (prepareFilesThread == nullptr)
+ return;
+
+ filesPrepared (prepareFilesThread->getResultFileUris(), prepareFilesThread->getMimeTypes());
+ }
+
+ void filesPrepared (jobject fileUris, const StringArray& mimeTypes)
+ {
+ auto env = getEnv();
+
+ auto intent = LocalRef (env->NewObject (AndroidIntent, AndroidIntent.constructor));
+ env->CallObjectMethod (intent, AndroidIntent.setAction,
+ javaString ("android.intent.action.SEND_MULTIPLE").get());
+
+ env->CallObjectMethod (intent, AndroidIntent.setType,
+ javaString (getCommonMimeType (mimeTypes)).get());
+
+ constexpr int grantReadPermission = 1;
+ env->CallObjectMethod (intent, AndroidIntent.setFlags, grantReadPermission);
+
+ env->CallObjectMethod (intent, AndroidIntent.putParcelableArrayListExtra,
+ javaString ("android.intent.extra.STREAM").get(),
+ fileUris);
+
+ auto chooserIntent = LocalRef (env->CallStaticObjectMethod (AndroidIntent,
+ AndroidIntent.createChooser,
+ intent.get(),
+ javaString ("Choose share target").get()));
+
+ env->CallVoidMethod (android.activity, JuceAppActivity.startActivityForResult, chooserIntent.get(), 1003);
+ }
+
+ void decrementPendingFileCountAndNotifyOwnerIfReady()
+ {
+ --nonAssetFilesPendingShare;
+
+ notifyOwnerIfReady();
+ }
+
+ void notifyOwnerIfReady()
+ {
+ if (sharingActivityDidFinish && nonAssetFilesPendingShare.get() == 0)
+ owner.sharingFinished (succeeded, {});
+ }
+
+ void timerCallback() override
+ {
+ stopTimer();
+
+ notifyOwnerIfReady();
+ }
+
+ //==============================================================================
+ struct ContentUriElements
+ {
+ String index;
+ String filename;
+ String filepath;
+ };
+
+ ContentUriElements getContentUriElements (JNIEnv* env, const LocalRef& uri) const
+ {
+ jassert (prepareFilesThread != nullptr);
+
+ if (prepareFilesThread == nullptr)
+ return {};
+
+ auto fullUri = juceString ((jstring) env->CallObjectMethod (uri.get(), AndroidUri.toString));
+
+ auto index = fullUri.fromFirstOccurrenceOf (uriBase, false, false)
+ .upToFirstOccurrenceOf ("/", false, true);
+
+ auto filename = fullUri.fromLastOccurrenceOf ("/", false, true);
+
+ return { index, filename, prepareFilesThread->getFilePaths()[index.getIntValue()] };
+ }
+
+ static LocalRef juceStringArrayToJavaStringArray (const StringArray& juceArray)
+ {
+ auto* env = getEnv();
+
+ auto javaArray = LocalRef (env->NewObjectArray ((jsize) juceArray.size(),
+ JavaString,
+ javaString ("").get()));
+
+ for (int i = 0; i < juceArray.size(); ++i)
+ env->SetObjectArrayElement (javaArray, i, javaString (juceArray [i]).get());
+
+ return javaArray;
+ }
+
+ static StringArray javaStringArrayToJuceStringArray (const LocalRef& javaArray)
+ {
+ auto* env = getEnv();
+
+ const int size = env->GetArrayLength (javaArray.get());
+
+ StringArray juceArray;
+
+ for (int i = 0; i < size; ++i)
+ {
+ auto javaString = LocalRef ((jstring) env->GetObjectArrayElement (javaArray.get(), i));
+ juceArray.add (juceString (javaString.get()));
+ }
+
+ return juceArray;
+ }
+
+ static StringArray getSupportedColumns()
+ {
+ return StringArray ("_display_name", "_size");
+ }
+
+ void* getAssetFileDescriptor (JNIEnv* env, const LocalRef& contentProvider,
+ const String& filepath)
+ {
+ // This function can be called from multiple threads.
+ {
+ const ScopedLock sl (nonAssetFileOpenLock);
+
+ if (! nonAssetFilePathsPendingShare.contains (filepath))
+ {
+ nonAssetFilePathsPendingShare.add (filepath);
+ ++nonAssetFilesPendingShare;
+
+ nonAssetFileObservers.add (new AndroidContentSharerFileObserver (*this, env,
+ contentProvider,
+ filepath));
+ }
+ }
+
+ auto javaFile = LocalRef (env->NewObject (JavaFile, JavaFile.constructor,
+ javaString (filepath).get()));
+
+ constexpr int modeReadOnly = 268435456;
+ auto parcelFileDescriptor = LocalRef (env->CallStaticObjectMethod (ParcelFileDescriptor,
+ ParcelFileDescriptor.open,
+ javaFile.get(), modeReadOnly));
+
+ assetFileDescriptors.add (GlobalRef (LocalRef (env->NewObject (AssetFileDescriptor,
+ AssetFileDescriptor.constructor,
+ parcelFileDescriptor.get(),
+ 0, 0))));
+
+ return assetFileDescriptors.getReference (assetFileDescriptors.size() - 1).get();
+ }
+
+ ContentSharer& owner;
+ String packageName;
+ String uriBase;
+
+ ScopedPointer prepareFilesThread;
+
+ bool succeeded = false;
+ String errorDescription;
+
+ bool sharingActivityDidFinish = false;
+
+ OwnedArray cursors;
+
+ Array assetFileDescriptors;
+
+ CriticalSection nonAssetFileOpenLock;
+ StringArray nonAssetFilePathsPendingShare;
+ Atomic nonAssetFilesPendingShare { 0 };
+ OwnedArray nonAssetFileObservers;
+
+ WeakReference::Master masterReference;
+ friend class WeakReference;
+};
+
+//==============================================================================
+ContentSharer::Pimpl* ContentSharer::createPimpl()
+{
+ return new ContentSharerNativeImpl (*this);
+}
+
+//==============================================================================
+void* juce_contentSharerQuery (void* contentProvider, void* uri, void* projection,
+ void* selection, void* selectionArgs, void* sortOrder)
+{
+ auto* pimpl = (ContentSharer::ContentSharerNativeImpl*) ContentSharer::getInstance()->pimpl.get();
+ return pimpl->query (LocalRef (static_cast (contentProvider)),
+ LocalRef (static_cast (uri)),
+ LocalRef (static_cast (projection)),
+ LocalRef (static_cast (selection)),
+ LocalRef (static_cast (selectionArgs)),
+ LocalRef (static_cast (sortOrder)));
+}
+
+void* juce_contentSharerOpenFile (void* contentProvider, void* uri, void* mode)
+{
+ auto* pimpl = (ContentSharer::ContentSharerNativeImpl*) ContentSharer::getInstance()->pimpl.get();
+ return pimpl->openFile (LocalRef (static_cast (contentProvider)),
+ LocalRef (static_cast (uri)),
+ LocalRef (static_cast (mode)));
+}
+
+void juce_contentSharingCompleted (int resultCode)
+{
+ auto* pimpl = (ContentSharer::ContentSharerNativeImpl*) ContentSharer::getInstance()->pimpl.get();
+ return pimpl->sharingFinished (resultCode);
+}
+
+void* juce_contentSharerGetStreamTypes (void* uri, void* mimeTypeFilter)
+{
+ auto* pimpl = (ContentSharer::ContentSharerNativeImpl*) ContentSharer::getInstance()->pimpl.get();
+ return pimpl->getStreamTypes (LocalRef (static_cast (uri)),
+ LocalRef (static_cast (mimeTypeFilter)));
+}
+
+//==============================================================================
+JUCE_JNI_CALLBACK (JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME, contentSharerFileObserverEvent, void,
+ (JNIEnv* env, jobject /*fileObserver*/, jlong host, int event, jstring path))
+{
+ setEnv (env);
+
+ reinterpret_cast (host)->onFileEvent (event, LocalRef (path));
+}
+
+//==============================================================================
+JUCE_JNI_CALLBACK (JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME, contentSharerQuery, jobject,
+ (JNIEnv* env, jobject contentProvider, jobject uri, jobjectArray projection,
+ jobject selection, jobjectArray selectionArgs, jobject sortOrder))
+{
+ setEnv (env);
+
+ return (jobject) juce_contentSharerQuery (contentProvider, uri, projection, selection, selectionArgs, sortOrder);
+}
+
+JUCE_JNI_CALLBACK (JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME, contentSharerCursorClosed, void,
+ (JNIEnv* env, jobject /*cursor*/, jlong host))
+{
+ setEnv (env);
+
+ reinterpret_cast (host)->cursorClosed();
+}
+
+JUCE_JNI_CALLBACK (JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME, contentSharerOpenFile, jobject,
+ (JNIEnv* env, jobject contentProvider, jobject uri, jstring mode))
+{
+ setEnv (env);
+
+ return (jobject) juce_contentSharerOpenFile ((void*) contentProvider, (void*) uri, (void*) mode);
+}
+
+JUCE_JNI_CALLBACK (JUCE_ANDROID_SHARING_CONTENT_PROVIDER_CLASSNAME, contentSharerGetStreamTypes, jobject,
+ (JNIEnv* env, jobject /*contentProvider*/, jobject uri, jstring mimeTypeFilter))
+{
+ setEnv (env);
+
+ return (jobject) juce_contentSharerGetStreamTypes ((void*) uri, (void*) mimeTypeFilter);
+}
+
+} // namespace juce
diff --git a/modules/juce_gui_basics/native/juce_android_FileChooser.cpp b/modules/juce_gui_basics/native/juce_android_FileChooser.cpp
index 00db85b453..72a5d05c4e 100644
--- a/modules/juce_gui_basics/native/juce_android_FileChooser.cpp
+++ b/modules/juce_gui_basics/native/juce_android_FileChooser.cpp
@@ -41,19 +41,19 @@ public:
auto saveMode = ((flags & FileBrowserComponent::saveMode) != 0);
auto selectsDirectories = ((flags & FileBrowserComponent::canSelectDirectories) != 0);
- // You cannot have try to save a direcrtory
+ // You cannot save a directory
jassert (! (saveMode && selectsDirectories));
if (sdkVersion < 19)
{
- // native save dialogs are only supported in Android versions > 19
+ // native save dialogs are only supported in Android versions >= 19
jassert (! saveMode);
saveMode = false;
}
if (sdkVersion < 21)
{
- // native directory chooser dialogs are only supported in Android versions > 21
+ // native directory chooser dialogs are only supported in Android versions >= 21
jassert (! selectsDirectories);
selectsDirectories = false;
}
@@ -64,7 +64,8 @@ public:
: "android.intent.action.GET_CONTENT")));
- intent = GlobalRef (env->NewObject (AndroidIntent, AndroidIntent.constructWithString, javaString (action).get()));
+ intent = GlobalRef (env->NewObject (AndroidIntent, AndroidIntent.constructWithString,
+ javaString (action).get()));
if (owner.startingFile != File())
{
@@ -75,7 +76,8 @@ public:
URL url (owner.startingFile);
- LocalRef uri (env->CallStaticObjectMethod (Uri, Uri.parse, javaString (url.toString (true)).get()));
+ LocalRef uri (env->CallStaticObjectMethod (AndroidUri, AndroidUri.parse,
+ javaString (url.toString (true)).get()));
if (uri)
env->CallObjectMethod (intent.get(), AndroidIntent.putExtraParcelable,
@@ -86,7 +88,8 @@ public:
if (! selectsDirectories)
{
- env->CallObjectMethod (intent.get(), AndroidIntent.addCategory, javaString ("android.intent.category.OPENABLE").get());
+ env->CallObjectMethod (intent.get(), AndroidIntent.addCategory,
+ javaString ("android.intent.category.OPENABLE").get());
auto mimeTypes = convertFiltersToMimeTypes (owner.filters);
@@ -103,7 +106,8 @@ public:
mimeGroup = mimeTypes[0].upToFirstOccurrenceOf ("/", false, false);
auto allMimeTypesHaveSameGroup = true;
- LocalRef jMimeTypes (env->NewObjectArray (mimeTypes.size(), JavaString, javaString("").get()));
+ LocalRef jMimeTypes (env->NewObjectArray (mimeTypes.size(), JavaString,
+ javaString("").get()));
for (int i = 0; i < mimeTypes.size(); ++i)
{
diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp
index 664e99bddf..086ad15473 100644
--- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp
+++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp
@@ -48,6 +48,8 @@ namespace juce
extern void juce_fileChooserCompleted (int, void*);
#endif
+extern void juce_contentSharingCompleted (int);
+
//==============================================================================
JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* env, jobject activity,
jstring appFile, jstring appDataDir))
@@ -113,6 +115,10 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, appActivityResult, void, (JN
if (requestCode == /*READ_REQUEST_CODE*/42)
juce_fileChooserCompleted (resultCode, intentData);
#endif
+
+ if (requestCode == 1003)
+ juce_contentSharingCompleted (resultCode);
+
ignoreUnused (intentData, requestCode);
}
diff --git a/modules/juce_gui_basics/native/juce_common_MimeTypes.cpp b/modules/juce_gui_basics/native/juce_common_MimeTypes.cpp
index ea3df43a67..32f1d8e73f 100644
--- a/modules/juce_gui_basics/native/juce_common_MimeTypes.cpp
+++ b/modules/juce_gui_basics/native/juce_common_MimeTypes.cpp
@@ -45,6 +45,48 @@ static StringArray getMimeTypesForFileExtension (const String& fileExtension)
return result;
}
+static StringArray filterMimeTypes (const StringArray& mimeTypes, const String& filter)
+{
+ String filterToUse (filter.removeCharacters ("*"));
+
+ if (filterToUse.isEmpty() || filterToUse == "/")
+ return mimeTypes;
+
+ StringArray result;
+
+ for (const auto& type : mimeTypes)
+ if (String (type).contains (filterToUse))
+ result.add (type);
+
+ return result;
+}
+
+static String getCommonMimeType (const StringArray& mimeTypes)
+{
+ if (mimeTypes.isEmpty())
+ return "*/*";
+
+ auto commonMime = mimeTypes[0];
+ bool lookForCommonGroup = false;
+
+ for (int i = 1; i < mimeTypes.size(); ++i)
+ {
+ if (mimeTypes[i] == commonMime)
+ continue;
+
+ if (! lookForCommonGroup)
+ {
+ lookForCommonGroup = true;
+ commonMime = commonMime.upToFirstOccurrenceOf ("/", true, false);
+ }
+
+ if (! mimeTypes[i].startsWith (commonMime))
+ return "*/*";
+ }
+
+ return lookForCommonGroup ? commonMime + "*" : commonMime;
+}
+
//==============================================================================
MimeTypeTableEntry MimeTypeTableEntry::table[640] =
{
diff --git a/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp b/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp
new file mode 100644
index 0000000000..c626835a42
--- /dev/null
+++ b/modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp
@@ -0,0 +1,214 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE library.
+ Copyright (c) 2017 - ROLI Ltd.
+
+ JUCE is an open source library subject to commercial or open-source
+ licensing.
+
+ By using JUCE, you agree to the terms of both the JUCE 5 End-User License
+ Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
+ 27th April 2017).
+
+ End User License Agreement: www.juce.com/juce-5-licence
+ Privacy Policy: www.juce.com/juce-5-privacy-policy
+
+ Or: You may also use this code under the terms of the GPL v3 (see
+ www.gnu.org/licenses).
+
+ JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+namespace juce
+{
+
+template <> struct ContainerDeletePolicy { static void destroy (NSObject* o) { [o release]; } };
+template <> struct ContainerDeletePolicy> { static void destroy (NSObject* o) { [o release]; } };
+
+//==============================================================================
+class ContentSharer::ContentSharerNativeImpl : public ContentSharer::Pimpl,
+ private Component
+{
+public:
+ ContentSharerNativeImpl (ContentSharer& cs)
+ : owner (cs)
+ {
+ static PopoverDelegateClass cls;
+ popoverDelegate = [cls.createInstance() init];
+ }
+
+ ~ContentSharerNativeImpl()
+ {
+ exitModalState (0);
+ }
+
+ void shareFiles (const Array& files) override
+ {
+ auto* urls = [NSMutableArray arrayWithCapacity: (NSUInteger) files.size()];
+
+ for (const auto& f : files)
+ {
+ NSString* nativeFilePath = nil;
+
+ if (f.isLocalFile())
+ {
+ nativeFilePath = juceStringToNS (f.getLocalFile().getFullPathName());
+ }
+ else
+ {
+ auto filePath = f.toString (false);
+
+ auto* fileDirectory = filePath.contains ("/")
+ ? juceStringToNS (filePath.upToLastOccurrenceOf ("/", false, false))
+ : [NSString string];
+
+ auto fileName = juceStringToNS (filePath.fromLastOccurrenceOf ("/", false, false)
+ .upToLastOccurrenceOf (".", false, false));
+
+ auto fileExt = juceStringToNS (filePath.fromLastOccurrenceOf (".", false, false));
+
+ if ([fileDirectory length] == NSUInteger (0))
+ nativeFilePath = [[NSBundle mainBundle] pathForResource: fileName
+ ofType: fileExt];
+ else
+ nativeFilePath = [[NSBundle mainBundle] pathForResource: fileName
+ ofType: fileExt
+ inDirectory: fileDirectory];
+ }
+
+ if (nativeFilePath != nil)
+ [urls addObject: [NSURL fileURLWithPath: nativeFilePath]];
+ }
+
+ share (urls);
+ }
+
+ void shareText (const String& text) override
+ {
+ auto* array = [NSArray arrayWithObject: juceStringToNS (text)];
+ share (array);
+ }
+
+private:
+ void share (NSArray* items)
+ {
+ if ([items count] == 0)
+ {
+ jassertfalse;
+ owner.sharingFinished (false, "No valid items found for sharing.");
+ return;
+ }
+
+ controller = [[UIActivityViewController alloc] initWithActivityItems: items
+ applicationActivities: nil];
+
+ controller.get().excludedActivityTypes = nil;
+
+ controller.get().completionWithItemsHandler = ^ (UIActivityType type, BOOL completed,
+ NSArray* returnedItems, NSError* error)
+ {
+ ignoreUnused (type);
+ ignoreUnused (returnedItems);
+
+ succeeded = completed;
+
+ if (error != nil)
+ errorDescription = nsStringToJuce ([error localizedDescription]);
+
+ exitModalState (0);
+ };
+
+ controller.get().modalTransitionStyle = UIModalTransitionStyleCoverVertical;
+
+ auto bounds = Desktop::getInstance().getDisplays().getMainDisplay().userArea;
+ setBounds (bounds);
+
+ setAlwaysOnTop (true);
+ addToDesktop (0);
+
+ enterModalState (true,
+ ModalCallbackFunction::create ([this] (int)
+ {
+ owner.sharingFinished (succeeded, errorDescription);
+ }),
+ false);
+ }
+
+ static bool isIPad()
+ {
+ return [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad;
+ }
+
+ //==============================================================================
+ void parentHierarchyChanged() override
+ {
+ auto* newPeer = dynamic_cast (getPeer());
+
+ if (peer != newPeer)
+ {
+ peer = newPeer;
+
+ if (isIPad())
+ {
+ controller.get().preferredContentSize = peer->view.frame.size;
+
+ auto screenBounds = [UIScreen mainScreen].bounds;
+
+ auto* popoverController = controller.get().popoverPresentationController;
+ popoverController.sourceView = peer->view;
+ popoverController.sourceRect = CGRectMake (0.f, screenBounds.size.height - 10.f, screenBounds.size.width, 10.f);
+ popoverController.canOverlapSourceViewRect = YES;
+ popoverController.delegate = popoverDelegate.get();
+ }
+
+ if (auto* parentController = peer->controller)
+ [parentController showViewController: controller sender: parentController];
+
+ if (peer->view.window != nil)
+ peer->view.window.autoresizesSubviews = YES;
+ }
+ }
+
+ //==============================================================================
+ struct PopoverDelegateClass : public ObjCClass>
+ {
+ PopoverDelegateClass() : ObjCClass> ("PopoverDelegateClass_")
+ {
+ addMethod (@selector (popoverPresentationController:willRepositionPopoverToRect:inView:), willRepositionPopover, "v@:@@@");
+
+ registerClass();
+ }
+
+ //==============================================================================
+ static void willRepositionPopover (id, SEL, UIPopoverPresentationController*, CGRect* rect, UIView*)
+ {
+ auto screenBounds = [UIScreen mainScreen].bounds;
+
+ rect->origin.x = 0.f;
+ rect->origin.y = screenBounds.size.height - 10.f;
+ rect->size.width = screenBounds.size.width;
+ rect->size.height = 10.f;
+ }
+ };
+
+ ContentSharer& owner;
+ UIViewComponentPeer* peer = nullptr;
+ ScopedPointer controller;
+ ScopedPointer> popoverDelegate;
+
+ bool succeeded = false;
+ String errorDescription;
+};
+
+//==============================================================================
+ContentSharer::Pimpl* ContentSharer::createPimpl()
+{
+ return new ContentSharerNativeImpl (*this);
+}
+
+} // namespace juce
diff --git a/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp b/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp
index e0d16a01a7..241391fc82 100644
--- a/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp
+++ b/modules/juce_gui_extra/native/juce_android_PushNotifications.cpp
@@ -1419,7 +1419,7 @@ struct PushNotifications::Pimpl
propertiesDynamicObject->setProperty ("titleLocalizationKey", juceString (titleLocalizationKey.get()));
propertiesDynamicObject->setProperty ("bodyLocalizationArgs", jobjectArrayToStringArray (bodyLocalizationArgs));
propertiesDynamicObject->setProperty ("titleLocalizationArgs", jobjectArrayToStringArray (titleLocalizationArgs));
- propertiesDynamicObject->setProperty ("link", link.get() != 0 ? juceString ((jstring) env->CallObjectMethod (link, Uri.toString)) : String());
+ propertiesDynamicObject->setProperty ("link", link.get() != 0 ? juceString ((jstring) env->CallObjectMethod (link, AndroidUri.toString)) : String());
}
n.properties = var (propertiesDynamicObject);