From 36da4cde05e2316ff1cbfbd378e972c7cc9a92c2 Mon Sep 17 00:00:00 2001 From: Lukasz Kozakiewicz Date: Mon, 20 Nov 2017 12:56:02 +0100 Subject: [PATCH] Add native content sharing support for iOS and Android --- .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 129 ++ .../AnalyticsCollection_App.vcxproj | 10 + .../AnalyticsCollection_App.vcxproj.filters | 12 + .../AnimationAppExample_App.vcxproj | 10 + .../AnimationAppExample_App.vcxproj.filters | 12 + .../AudioAppExample_App.vcxproj | 10 + .../AudioAppExample_App.vcxproj.filters | 12 + .../BlocksDrawing_App.vcxproj | 10 + .../BlocksDrawing_App.vcxproj.filters | 12 + .../BlocksDrawing_App.vcxproj | 10 + .../BlocksDrawing_App.vcxproj.filters | 12 + .../BlocksMonitor_App.vcxproj | 10 + .../BlocksMonitor_App.vcxproj.filters | 12 + .../BlocksMonitor_App.vcxproj | 10 + .../BlocksMonitor_App.vcxproj.filters | 12 + .../VisualStudio2015/BlocksSynth_App.vcxproj | 10 + .../BlocksSynth_App.vcxproj.filters | 12 + .../VisualStudio2017/BlocksSynth_App.vcxproj | 10 + .../BlocksSynth_App.vcxproj.filters | 12 + .../BouncingBallWavetableDemo_App.vcxproj | 10 + ...ncingBallWavetableDemo_App.vcxproj.filters | 12 + .../BouncingBallWavetableDemo_App.vcxproj | 10 + ...ncingBallWavetableDemo_App.vcxproj.filters | 12 + .../ComponentTutorialExample_App.vcxproj | 10 + ...mponentTutorialExample_App.vcxproj.filters | 12 + .../ComponentTutorialExample_App.vcxproj | 10 + ...mponentTutorialExample_App.vcxproj.filters | 12 + .../DSPModulePluginDemo_SharedCode.vcxproj | 10 + ...odulePluginDemo_SharedCode.vcxproj.filters | 12 + .../DSPModulePluginDemo_SharedCode.vcxproj | 10 + ...odulePluginDemo_SharedCode.vcxproj.filters | 12 + .../VisualStudio2017/DSPDemo_App.vcxproj | 10 + .../DSPDemo_App.vcxproj.filters | 12 + .../DSPDemo/JuceLibraryCode/BinaryData.cpp | 10 +- examples/DSPDemo/JuceLibraryCode/BinaryData.h | 2 +- .../Demo/Builds/Android/app/CMakeLists.txt | 10 +- .../Android/app/src/main/AndroidManifest.xml | 4 +- .../main/java/com/roli/jucedemo/JuceDemo.java | 1688 +++++++++++++++++ .../roli/jucedemo/SharingContentProvider.java | 129 ++ .../VisualStudio2013/JuceDemo_App.vcxproj | 10 + .../JuceDemo_App.vcxproj.filters | 12 + .../VisualStudio2015/JuceDemo_App.vcxproj | 10 + .../JuceDemo_App.vcxproj.filters | 12 + .../VisualStudio2017/JuceDemo_App.vcxproj | 10 + .../JuceDemo_App.vcxproj.filters | 12 + examples/Demo/JuceDemo.jucer | 5 +- examples/Demo/Source/Demos/DialogsDemo.cpp | 70 +- .../VisualStudio2015/HelloWorld_App.vcxproj | 10 + .../HelloWorld_App.vcxproj.filters | 12 + .../VisualStudio2017/HelloWorld_App.vcxproj | 10 + .../HelloWorld_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 129 ++ .../VisualStudio2015/MPETest_App.vcxproj | 10 + .../MPETest_App.vcxproj.filters | 12 + .../VisualStudio2017/MPETest_App.vcxproj | 10 + .../MPETest_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../miditest/SharingContentProvider.java | 138 ++ .../VisualStudio2015/MidiTest_App.vcxproj | 10 + .../MidiTest_App.vcxproj.filters | 12 + .../VisualStudio2017/MidiTest_App.vcxproj | 10 + .../MidiTest_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 129 ++ .../JUCE Network Graphics Demo_App.vcxproj | 10 + ... Network Graphics Demo_App.vcxproj.filters | 12 + .../JUCE Network Graphics Demo_App.vcxproj | 10 + ... Network Graphics Demo_App.vcxproj.filters | 12 + .../VisualStudio2015/OSCMonitor_App.vcxproj | 10 + .../OSCMonitor_App.vcxproj.filters | 12 + .../VisualStudio2017/OSCMonitor_App.vcxproj | 10 + .../OSCMonitor_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../oscreceiver/SharingContentProvider.java | 129 ++ .../VisualStudio2015/OSCReceiver_App.vcxproj | 10 + .../OSCReceiver_App.vcxproj.filters | 12 + .../VisualStudio2017/OSCReceiver_App.vcxproj | 10 + .../OSCReceiver_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../oscsender/SharingContentProvider.java | 129 ++ .../VisualStudio2015/OSCSender_App.vcxproj | 10 + .../OSCSender_App.vcxproj.filters | 12 + .../VisualStudio2017/OSCSender_App.vcxproj | 10 + .../OSCSender_App.vcxproj.filters | 12 + .../OpenGLAppExample_App.vcxproj | 10 + .../OpenGLAppExample_App.vcxproj.filters | 12 + .../PluckedStringsDemo_App.vcxproj | 10 + .../PluckedStringsDemo_App.vcxproj.filters | 12 + .../PluckedStringsDemo_App.vcxproj | 10 + .../PluckedStringsDemo_App.vcxproj.filters | 12 + .../Arpeggiator_SharedCode.vcxproj | 10 + .../Arpeggiator_SharedCode.vcxproj.filters | 12 + .../Arpeggiator_SharedCode.vcxproj | 10 + .../Arpeggiator_SharedCode.vcxproj.filters | 12 + .../GainPlugIn_SharedCode.vcxproj | 10 + .../GainPlugIn_SharedCode.vcxproj.filters | 12 + .../GainPlugIn_SharedCode.vcxproj | 10 + .../GainPlugIn_SharedCode.vcxproj.filters | 12 + .../MultiOutSynth_SharedCode.vcxproj | 10 + .../MultiOutSynth_SharedCode.vcxproj.filters | 12 + .../MultiOutSynth_SharedCode.vcxproj | 10 + .../MultiOutSynth_SharedCode.vcxproj.filters | 12 + .../NoiseGate_SharedCode.vcxproj | 10 + .../NoiseGate_SharedCode.vcxproj.filters | 12 + .../NoiseGate_SharedCode.vcxproj | 10 + .../NoiseGate_SharedCode.vcxproj.filters | 12 + .../Surround_SharedCode.vcxproj | 10 + .../Surround_SharedCode.vcxproj.filters | 12 + .../Surround_SharedCode.vcxproj | 10 + .../Surround_SharedCode.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 138 ++ .../PushNotificationsDemo_App.vcxproj | 10 + .../PushNotificationsDemo_App.vcxproj.filters | 12 + .../SimpleFFTExample_App.vcxproj | 10 + .../SimpleFFTExample_App.vcxproj.filters | 12 + .../SimpleFFTExample_App.vcxproj | 10 + .../SimpleFFTExample_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 138 ++ .../JuceDemoPlugin_SharedCode.vcxproj | 10 + .../JuceDemoPlugin_SharedCode.vcxproj.filters | 12 + .../JuceDemoPlugin_SharedCode.vcxproj | 10 + .../JuceDemoPlugin_SharedCode.vcxproj.filters | 12 + .../VisualStudio2013/Plugin Host_App.vcxproj | 10 + .../Plugin Host_App.vcxproj.filters | 12 + .../VisualStudio2015/Plugin Host_App.vcxproj | 10 + .../Plugin Host_App.vcxproj.filters | 12 + .../VisualStudio2017/Plugin Host_App.vcxproj | 10 + .../Plugin Host_App.vcxproj.filters | 12 + .../Builds/Android/app/CMakeLists.txt | 10 +- .../SharingContentProvider.java | 138 ++ .../AudioPerformanceTest_App.vcxproj | 10 + .../AudioPerformanceTest_App.vcxproj.filters | 12 + .../VisualStudio2013/Projucer_App.vcxproj | 10 + .../Projucer_App.vcxproj.filters | 12 + .../VisualStudio2015/Projucer_App.vcxproj | 10 + .../Projucer_App.vcxproj.filters | 12 + .../VisualStudio2017/Projucer_App.vcxproj | 10 + .../Projucer_App.vcxproj.filters | 12 + .../jucer_ProjectExport_Android.h | 295 ++- .../Source/Utility/Helpers/jucer_PresetIDs.h | 1 + .../UnitTestRunner_ConsoleApp.vcxproj | 10 + .../UnitTestRunner_ConsoleApp.vcxproj.filters | 12 + .../juce_dll_StaticLibrary.vcxproj | 10 + .../juce_dll_StaticLibrary.vcxproj.filters | 12 + .../java/AndroidSharingContentProvider.java | 138 ++ .../juce_core/native/juce_android_Files.cpp | 33 +- .../native/juce_android_JNIHelpers.h | 136 +- .../filebrowser/juce_ContentSharer.cpp | 281 +++ .../filebrowser/juce_ContentSharer.h | 149 ++ modules/juce_gui_basics/juce_gui_basics.cpp | 5 + modules/juce_gui_basics/juce_gui_basics.h | 1 + .../native/juce_android_ContentSharer.cpp | 862 +++++++++ .../native/juce_android_FileChooser.cpp | 18 +- .../native/juce_android_Windowing.cpp | 6 + .../native/juce_common_MimeTypes.cpp | 42 + .../native/juce_ios_ContentSharer.cpp | 214 +++ .../native/juce_android_PushNotifications.cpp | 2 +- 161 files changed, 6505 insertions(+), 203 deletions(-) create mode 100644 examples/AnalyticsCollection/Builds/Android/app/src/main/java/com/yourcompany/analyticscollection/SharingContentProvider.java create mode 100644 examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/JuceDemo.java create mode 100644 examples/Demo/Builds/Android/app/src/main/java/com/roli/jucedemo/SharingContentProvider.java create mode 100644 examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/SharingContentProvider.java create mode 100644 examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/SharingContentProvider.java create mode 100644 examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/SharingContentProvider.java create mode 100644 examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/SharingContentProvider.java create mode 100644 examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/SharingContentProvider.java create mode 100644 examples/PushNotificationsDemo/Builds/Android/app/src/main/java/com/juce/pushnotificationsdemo/SharingContentProvider.java create mode 100644 examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/SharingContentProvider.java create mode 100644 extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/SharingContentProvider.java create mode 100644 modules/juce_core/native/java/AndroidSharingContentProvider.java create mode 100644 modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp create mode 100644 modules/juce_gui_basics/filebrowser/juce_ContentSharer.h create mode 100644 modules/juce_gui_basics/native/juce_android_ContentSharer.cpp create mode 100644 modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp 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);