| @@ -29,7 +29,6 @@ extras/JuceDemo/Builds/VisualStudio2008/Release | |||||
| extras/JuceDemo/Builds/VisualStudio2010/Debug | extras/JuceDemo/Builds/VisualStudio2010/Debug | ||||
| extras/JuceDemo/Builds/VisualStudio2010/Release | extras/JuceDemo/Builds/VisualStudio2010/Release | ||||
| extras/JuceDemo/Builds/Android/bin | extras/JuceDemo/Builds/Android/bin | ||||
| extras/JuceDemo/Builds/Android/src/com | |||||
| extras/JuceDemo/Builds/iPhone/build | extras/JuceDemo/Builds/iPhone/build | ||||
| extras/audio plugin demo/Builds/MacOSX/build | extras/audio plugin demo/Builds/MacOSX/build | ||||
| extras/audio plugin demo/Builds/Linux/build | extras/audio plugin demo/Builds/Linux/build | ||||
| @@ -42,7 +42,7 @@ public: | |||||
| if (settings.hasType (getValueTreeTypeName())) | if (settings.hasType (getValueTreeTypeName())) | ||||
| return new AndroidProjectExporter (project, settings); | return new AndroidProjectExporter (project, settings); | ||||
| return 0; | |||||
| return nullptr; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -54,6 +54,9 @@ public: | |||||
| if (getTargetLocation().toString().isEmpty()) | if (getTargetLocation().toString().isEmpty()) | ||||
| getTargetLocation() = getDefaultBuildsRootFolder() + "Android"; | getTargetLocation() = getDefaultBuildsRootFolder() + "Android"; | ||||
| if (getActivityClassPath().toString().isEmpty()) | |||||
| getActivityClassPath() = createDefaultClassName(); | |||||
| if (getSDKPath().toString().isEmpty()) | if (getSDKPath().toString().isEmpty()) | ||||
| getSDKPath() = "${user.home}/SDKs/android-sdk-macosx"; | getSDKPath() = "${user.home}/SDKs/android-sdk-macosx"; | ||||
| @@ -86,6 +89,9 @@ public: | |||||
| { | { | ||||
| ProjectExporter::createPropertyEditors (props); | ProjectExporter::createPropertyEditors (props); | ||||
| props.add (new TextPropertyComponent (getActivityClassPath(), "Android Activity class name", 256, false), | |||||
| "The full java class name to use for the app's Activity class."); | |||||
| props.add (new TextPropertyComponent (getSDKPath(), "Android SDK Path", 1024, false), | props.add (new TextPropertyComponent (getSDKPath(), "Android SDK Path", 1024, false), | ||||
| "The path to the Android SDK folder on the target build machine"); | "The path to the Android SDK folder on the target build machine"); | ||||
| @@ -96,19 +102,40 @@ public: | |||||
| "If enabled, this will set the android.permission.INTERNET flag in the manifest."); | "If enabled, this will set the android.permission.INTERNET flag in the manifest."); | ||||
| } | } | ||||
| Value getActivityClassPath() const { return getSetting (Ids::androidActivityClass); } | |||||
| Value getSDKPath() const { return getSetting (Ids::androidSDKPath); } | Value getSDKPath() const { return getSetting (Ids::androidSDKPath); } | ||||
| Value getNDKPath() const { return getSetting (Ids::androidNDKPath); } | Value getNDKPath() const { return getSetting (Ids::androidNDKPath); } | ||||
| Value getInternetNeeded() const { return getSetting (Ids::androidInternetNeeded); } | Value getInternetNeeded() const { return getSetting (Ids::androidInternetNeeded); } | ||||
| String createDefaultClassName() const | |||||
| { | |||||
| String s (project.getBundleIdentifier().toString().toLowerCase()); | |||||
| if (s.length() > 5 | |||||
| && s.containsChar ('.') | |||||
| && s.containsOnly ("abcdefghijklmnopqrstuvwxyz_.") | |||||
| && ! s.startsWithChar ('.')) | |||||
| { | |||||
| if (! s.endsWithChar ('.')) | |||||
| s << "."; | |||||
| } | |||||
| else | |||||
| { | |||||
| s = "com.yourcompany."; | |||||
| } | |||||
| return s + CodeHelpers::makeValidIdentifier (project.getProjectFilenameRoot(), false, true, false); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void create() | |||||
| void create (const OwnedArray<LibraryModule>& modules) | |||||
| { | { | ||||
| const File target (getTargetFolder()); | const File target (getTargetFolder()); | ||||
| const File jniFolder (target.getChildFile ("jni")); | const File jniFolder (target.getChildFile ("jni")); | ||||
| createDirectoryOrThrow (target.getChildFile ("src/com")); | |||||
| copyActivityJavaFiles (modules); | |||||
| createDirectoryOrThrow (jniFolder); | createDirectoryOrThrow (jniFolder); | ||||
| createDirectoryOrThrow (target.getChildFile ("res/values")); | |||||
| createDirectoryOrThrow (target.getChildFile ("res").getChildFile ("values")); | |||||
| createDirectoryOrThrow (target.getChildFile ("libs")); | createDirectoryOrThrow (target.getChildFile ("libs")); | ||||
| createDirectoryOrThrow (target.getChildFile ("bin")); | createDirectoryOrThrow (target.getChildFile ("bin")); | ||||
| @@ -156,12 +183,19 @@ protected: | |||||
| { | { | ||||
| androidDynamicLibs.add ("GLESv1_CM"); | androidDynamicLibs.add ("GLESv1_CM"); | ||||
| androidDynamicLibs.add ("GLESv2"); | androidDynamicLibs.add ("GLESv2"); | ||||
| if (getArchitectures().toString().isEmpty()) | |||||
| getArchitectures() = "armeabi armeabi-v7a"; | |||||
| } | } | ||||
| Value getArchitectures() const { return getValue (Ids::androidArchitectures); } | |||||
| void createPropertyEditors (PropertyListBuilder& props) | void createPropertyEditors (PropertyListBuilder& props) | ||||
| { | { | ||||
| createBasicPropertyEditors (props); | createBasicPropertyEditors (props); | ||||
| props.add (new TextPropertyComponent (getArchitectures(), "Architectures", 256, false), | |||||
| "A list of the ARM architectures to build (for a fat binary)."); | |||||
| } | } | ||||
| StringArray androidDynamicLibs; | StringArray androidDynamicLibs; | ||||
| @@ -181,7 +215,7 @@ private: | |||||
| manifest->setAttribute ("xmlns:android", "http://schemas.android.com/apk/res/android"); | manifest->setAttribute ("xmlns:android", "http://schemas.android.com/apk/res/android"); | ||||
| manifest->setAttribute ("android:versionCode", "1"); | manifest->setAttribute ("android:versionCode", "1"); | ||||
| manifest->setAttribute ("android:versionName", "1.0"); | manifest->setAttribute ("android:versionName", "1.0"); | ||||
| manifest->setAttribute ("package", "com.juce"); | |||||
| manifest->setAttribute ("package", getActivityClassPackage()); | |||||
| XmlElement* screens = manifest->createNewChildElement ("supports-screens"); | XmlElement* screens = manifest->createNewChildElement ("supports-screens"); | ||||
| screens->setAttribute ("android:smallScreens", "true"); | screens->setAttribute ("android:smallScreens", "true"); | ||||
| @@ -201,7 +235,7 @@ private: | |||||
| app->setAttribute ("android:icon", "@drawable/icon"); | app->setAttribute ("android:icon", "@drawable/icon"); | ||||
| XmlElement* act = app->createNewChildElement ("activity"); | XmlElement* act = app->createNewChildElement ("activity"); | ||||
| act->setAttribute ("android:name", "JuceAppActivity"); | |||||
| act->setAttribute ("android:name", getActivityName()); | |||||
| act->setAttribute ("android:label", "@string/app_name"); | act->setAttribute ("android:label", "@string/app_name"); | ||||
| XmlElement* intent = act->createNewChildElement ("intent-filter"); | XmlElement* intent = act->createNewChildElement ("intent-filter"); | ||||
| @@ -226,6 +260,63 @@ private: | |||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | |||||
| String getActivityName() const | |||||
| { | |||||
| return getActivityClassPath().toString().fromLastOccurrenceOf (".", false, false); | |||||
| } | |||||
| String getActivityClassPackage() const | |||||
| { | |||||
| return getActivityClassPath().toString().upToLastOccurrenceOf (".", false, false); | |||||
| } | |||||
| String getJNIActivityClassName() const | |||||
| { | |||||
| return getActivityClassPath().toString().replaceCharacter ('.', '/'); | |||||
| } | |||||
| static LibraryModule* getCoreModule (const OwnedArray<LibraryModule>& modules) | |||||
| { | |||||
| for (int i = modules.size(); --i >= 0;) | |||||
| if (modules.getUnchecked(i)->getID() == "juce_core") | |||||
| return modules.getUnchecked(i); | |||||
| return nullptr; | |||||
| } | |||||
| void copyActivityJavaFiles (const OwnedArray<LibraryModule>& modules) | |||||
| { | |||||
| const String className (getActivityName()); | |||||
| const String package (getActivityClassPackage()); | |||||
| String path (package.replaceCharacter ('.', File::separator)); | |||||
| if (path.isEmpty() || className.isEmpty()) | |||||
| throw SaveError ("Invalid Android Activity class name: " + getActivityClassPath().toString()); | |||||
| const File classFolder (getTargetFolder().getChildFile ("src") | |||||
| .getChildFile (path)); | |||||
| createDirectoryOrThrow (classFolder); | |||||
| LibraryModule* const coreModule = getCoreModule (modules); | |||||
| if (coreModule == nullptr) | |||||
| throw SaveError ("To build an Android app, the juce_core module must be included in your project!"); | |||||
| File javaDestFile (classFolder.getChildFile (className + ".java")); | |||||
| File javaSourceFile (coreModule->getFolder().getChildFile ("native") | |||||
| .getChildFile ("java") | |||||
| .getChildFile ("JuceAppActivity.java")); | |||||
| MemoryOutputStream newFile; | |||||
| newFile << javaSourceFile.loadFileAsString() | |||||
| .replace ("JuceAppActivity", className) | |||||
| .replace ("package com.juce;", "package " + package + ";"); | |||||
| overwriteFileIfDifferentOrThrow (javaDestFile, newFile); | |||||
| } | |||||
| void writeApplicationMk (const File& file) | void writeApplicationMk (const File& file) | ||||
| { | { | ||||
| MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
| @@ -235,8 +326,7 @@ private: | |||||
| << newLine | << newLine | ||||
| << "APP_STL := gnustl_static" << newLine | << "APP_STL := gnustl_static" << newLine | ||||
| << "APP_CPPFLAGS += -fsigned-char -fexceptions -frtti" << newLine | << "APP_CPPFLAGS += -fsigned-char -fexceptions -frtti" << newLine | ||||
| << "APP_PLATFORM := android-7" << newLine | |||||
| << "APP_ABI := armeabi armeabi-v7a" << newLine; | |||||
| << "APP_PLATFORM := android-7" << newLine; | |||||
| overwriteFileIfDifferentOrThrow (file, mo); | overwriteFileIfDifferentOrThrow (file, mo); | ||||
| } | } | ||||
| @@ -287,8 +377,11 @@ private: | |||||
| { | { | ||||
| if (config->isDebug() == forDebug) | if (config->isDebug() == forDebug) | ||||
| { | { | ||||
| const AndroidBuildConfiguration& androidConfig = dynamic_cast <const AndroidBuildConfiguration&> (*config); | |||||
| out << " LOCAL_CPPFLAGS += " << createCPPFlags (*config) << newLine | out << " LOCAL_CPPFLAGS += " << createCPPFlags (*config) << newLine | ||||
| << getDynamicLibs (dynamic_cast <const AndroidBuildConfiguration&> (*config)); | |||||
| << " APP_ABI := " << androidConfig.getArchitectures().toString() << newLine | |||||
| << getDynamicLibs (androidConfig); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -327,6 +420,8 @@ private: | |||||
| { | { | ||||
| StringPairArray defines; | StringPairArray defines; | ||||
| defines.set ("JUCE_ANDROID", "1"); | defines.set ("JUCE_ANDROID", "1"); | ||||
| defines.set ("JUCE_ANDROID_ACTIVITY_CLASSNAME", getJNIActivityClassName().replaceCharacter ('/', '_')); | |||||
| defines.set ("JUCE_ANDROID_ACTIVITY_CLASSPATH", "\\\"" + getJNIActivityClassName() + "\\\""); | |||||
| String flags ("-fsigned-char -fexceptions -frtti"); | String flags ("-fsigned-char -fexceptions -frtti"); | ||||
| @@ -371,9 +466,6 @@ private: | |||||
| addNDKBuildStep (proj, "clean", "clean"); | addNDKBuildStep (proj, "clean", "clean"); | ||||
| //addLinkStep (proj, "${basedir}/" + rebaseFromProjectFolderToBuildTarget (RelativePath()).toUnixStyle() + "/", "jni/app"); | |||||
| addLinkStep (proj, "${basedir}/" + getJucePathFromTargetFolder().toUnixStyle() + "/modules/juce_core/native/java/", "src/com/juce"); | |||||
| addNDKBuildStep (proj, "debug", "CONFIG=Debug"); | addNDKBuildStep (proj, "debug", "CONFIG=Debug"); | ||||
| addNDKBuildStep (proj, "release", "CONFIG=Release"); | addNDKBuildStep (proj, "release", "CONFIG=Release"); | ||||
| @@ -396,18 +488,6 @@ private: | |||||
| executable->createNewChildElement ("arg")->setAttribute ("value", arg); | executable->createNewChildElement ("arg")->setAttribute ("value", arg); | ||||
| } | } | ||||
| static void addLinkStep (XmlElement* project, const String& from, const String& to) | |||||
| { | |||||
| XmlElement* executable = project->createNewChildElement ("exec"); | |||||
| executable->setAttribute ("executable", "ln"); | |||||
| executable->setAttribute ("dir", "${basedir}"); | |||||
| executable->setAttribute ("failonerror", "false"); | |||||
| executable->createNewChildElement ("arg")->setAttribute ("value", "-s"); | |||||
| executable->createNewChildElement ("arg")->setAttribute ("value", from); | |||||
| executable->createNewChildElement ("arg")->setAttribute ("value", to); | |||||
| } | |||||
| void writeProjectPropertiesFile (const File& file) | void writeProjectPropertiesFile (const File& file) | ||||
| { | { | ||||
| MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
| @@ -457,7 +457,7 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void create() | |||||
| void create (const OwnedArray<LibraryModule>&) | |||||
| { | { | ||||
| createIconFile(); | createIconFile(); | ||||
| @@ -802,7 +802,7 @@ public: | |||||
| if (settings.hasType (getValueTreeTypeName())) | if (settings.hasType (getValueTreeTypeName())) | ||||
| return new MSVCProjectExporterVC2005 (project, settings); | return new MSVCProjectExporterVC2005 (project, settings); | ||||
| return 0; | |||||
| return nullptr; | |||||
| } | } | ||||
| protected: | protected: | ||||
| @@ -845,7 +845,7 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void create() | |||||
| void create (const OwnedArray<LibraryModule>&) | |||||
| { | { | ||||
| createIconFile(); | createIconFile(); | ||||
| @@ -42,7 +42,7 @@ public: | |||||
| if (settings.hasType (getValueTreeTypeName())) | if (settings.hasType (getValueTreeTypeName())) | ||||
| return new MakefileProjectExporter (project, settings); | return new MakefileProjectExporter (project, settings); | ||||
| return 0; | |||||
| return nullptr; | |||||
| } | } | ||||
| @@ -82,7 +82,7 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void create() | |||||
| void create (const OwnedArray<LibraryModule>&) | |||||
| { | { | ||||
| Array<RelativePath> files; | Array<RelativePath> files; | ||||
| for (int i = 0; i < groups.size(); ++i) | for (int i = 0; i < groups.size(); ++i) | ||||
| @@ -73,7 +73,7 @@ public: | |||||
| else if (settings.hasType (getValueTreeTypeName (true))) | else if (settings.hasType (getValueTreeTypeName (true))) | ||||
| return new XCodeProjectExporter (project, settings, true); | return new XCodeProjectExporter (project, settings, true); | ||||
| return 0; | |||||
| return nullptr; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -144,7 +144,7 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void create() | |||||
| void create (const OwnedArray<LibraryModule>&) | |||||
| { | { | ||||
| infoPlistFile = getTargetFolder().getChildFile ("Info.plist"); | infoPlistFile = getTargetFolder().getChildFile ("Info.plist"); | ||||
| @@ -55,7 +55,7 @@ public: | |||||
| virtual bool usesMMFiles() const = 0; | virtual bool usesMMFiles() const = 0; | ||||
| virtual void createPropertyEditors (PropertyListBuilder&); | virtual void createPropertyEditors (PropertyListBuilder&); | ||||
| virtual void launchProject() = 0; | virtual void launchProject() = 0; | ||||
| virtual void create() = 0; // may throw a SaveError | |||||
| virtual void create (const OwnedArray<LibraryModule>&) = 0; // may throw a SaveError | |||||
| virtual bool shouldFileBeCompiledByDefault (const RelativePath& path) const; | virtual bool shouldFileBeCompiledByDefault (const RelativePath& path) const; | ||||
| virtual bool canCopeWithDuplicateFiles() = 0; | virtual bool canCopeWithDuplicateFiles() = 0; | ||||
| @@ -432,7 +432,7 @@ private: | |||||
| try | try | ||||
| { | { | ||||
| exporter->create(); | |||||
| exporter->create (modules); | |||||
| } | } | ||||
| catch (ProjectExporter::SaveError& error) | catch (ProjectExporter::SaveError& error) | ||||
| { | { | ||||
| @@ -44,6 +44,7 @@ public: | |||||
| String getVersion() const { return moduleInfo ["version"].toString(); } | String getVersion() const { return moduleInfo ["version"].toString(); } | ||||
| String getName() const { return moduleInfo ["name"].toString(); } | String getName() const { return moduleInfo ["name"].toString(); } | ||||
| String getDescription() const { return moduleInfo ["description"].toString(); } | String getDescription() const { return moduleInfo ["description"].toString(); } | ||||
| const File& getFolder() const { return moduleFolder; } | |||||
| void writeIncludes (ProjectSaver&, OutputStream&); | void writeIncludes (ProjectSaver&, OutputStream&); | ||||
| void prepareExporter (ProjectExporter&, ProjectSaver&) const; | void prepareExporter (ProjectExporter&, ProjectSaver&) const; | ||||
| @@ -134,7 +134,10 @@ String createGCCPreprocessorFlags (const StringPairArray& defs) | |||||
| if (value.isNotEmpty()) | if (value.isNotEmpty()) | ||||
| def << "=" << value; | def << "=" << value; | ||||
| s += " -D " + def.quoted(); | |||||
| if (! def.endsWithChar ('"')) | |||||
| def = def.quoted(); | |||||
| s += " -D " + def; | |||||
| } | } | ||||
| return s; | return s; | ||||
| @@ -97,9 +97,11 @@ namespace Ids | |||||
| DECLARE_ID (useStdCall); | DECLARE_ID (useStdCall); | ||||
| DECLARE_ID (showAllCode); | DECLARE_ID (showAllCode); | ||||
| DECLARE_ID (useLocalCopy); | DECLARE_ID (useLocalCopy); | ||||
| DECLARE_ID (androidActivityClass); | |||||
| DECLARE_ID (androidSDKPath); | DECLARE_ID (androidSDKPath); | ||||
| DECLARE_ID (androidNDKPath); | DECLARE_ID (androidNDKPath); | ||||
| DECLARE_ID (androidInternetNeeded); | DECLARE_ID (androidInternetNeeded); | ||||
| DECLARE_ID (androidArchitectures); | |||||
| const Identifier class_ ("class"); | const Identifier class_ ("class"); | ||||
| #undef DECLARE_ID | #undef DECLARE_ID | ||||
| @@ -5,7 +5,7 @@ | |||||
| <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | ||||
| <uses-permission android:name="android.permission.INTERNET"/> | <uses-permission android:name="android.permission.INTERNET"/> | ||||
| <application android:label="@string/app_name" android:icon="@drawable/icon"> | <application android:label="@string/app_name" android:icon="@drawable/icon"> | ||||
| <activity android:name="JuceAppActivity" android:label="@string/app_name"> | |||||
| <activity android:name="JuceDemo" android:label="@string/app_name"> | |||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN"/> | <action android:name="android.intent.action.MAIN"/> | ||||
| <category android:name="android.intent.category.LAUNCHER"/> | <category android:name="android.intent.category.LAUNCHER"/> | ||||
| @@ -15,11 +15,6 @@ | |||||
| <arg value="clean"/> | <arg value="clean"/> | ||||
| </exec> | </exec> | ||||
| </target> | </target> | ||||
| <exec executable="ln" dir="${basedir}" failonerror="false"> | |||||
| <arg value="-s"/> | |||||
| <arg value="${basedir}/../../../../../juce/modules/juce_core/native/java/"/> | |||||
| <arg value="src/com/juce"/> | |||||
| </exec> | |||||
| <target name="debug"> | <target name="debug"> | ||||
| <exec executable="${ndk.dir}/ndk-build" dir="${basedir}" failonerror="true"> | <exec executable="${ndk.dir}/ndk-build" dir="${basedir}" failonerror="true"> | ||||
| <arg value="--jobs=2"/> | <arg value="--jobs=2"/> | ||||
| @@ -46,10 +46,12 @@ LOCAL_SRC_FILES := \ | |||||
| ../../../../../modules/juce_video/juce_video.cpp\ | ../../../../../modules/juce_video/juce_video.cpp\ | ||||
| ifeq ($(CONFIG),Debug) | ifeq ($(CONFIG),Debug) | ||||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -O0 -D "JUCE_ANDROID=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -g -I "../../JuceLibraryCode" -O0 -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/JuceDemo\" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||||
| APP_ABI := armeabi | |||||
| LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 | LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 | ||||
| else | else | ||||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -Os -D "JUCE_ANDROID=1" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||||
| LOCAL_CPPFLAGS += -fsigned-char -fexceptions -frtti -I "../../JuceLibraryCode" -Os -D "JUCE_ANDROID=1" -D "JUCE_ANDROID_ACTIVITY_CLASSNAME=com_juce_JuceDemo" -D JUCE_ANDROID_ACTIVITY_CLASSPATH=\"com/juce/JuceDemo\" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -D "JUCER_ANDROID_7F0E4A25=1" | |||||
| APP_ABI := armeabi armeabi-v7a | |||||
| LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 | LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 | ||||
| endif | endif | ||||
| @@ -4,4 +4,3 @@ | |||||
| APP_STL := gnustl_static | APP_STL := gnustl_static | ||||
| APP_CPPFLAGS += -fsigned-char -fexceptions -frtti | APP_CPPFLAGS += -fsigned-char -fexceptions -frtti | ||||
| APP_PLATFORM := android-7 | APP_PLATFORM := android-7 | ||||
| APP_ABI := armeabi armeabi-v7a | |||||
| @@ -0,0 +1,456 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-10 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| package com.juce; | |||||
| import android.app.Activity; | |||||
| import android.app.AlertDialog; | |||||
| import android.content.DialogInterface; | |||||
| import android.content.Context; | |||||
| import android.os.Bundle; | |||||
| import android.view.*; | |||||
| import android.graphics.*; | |||||
| import android.text.ClipboardManager; | |||||
| import java.io.BufferedInputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.net.URL; | |||||
| import java.net.HttpURLConnection; | |||||
| //============================================================================== | |||||
| public final class JuceDemo extends Activity | |||||
| { | |||||
| //============================================================================== | |||||
| static | |||||
| { | |||||
| System.loadLibrary ("juce_jni"); | |||||
| } | |||||
| @Override | |||||
| public final void onCreate (Bundle savedInstanceState) | |||||
| { | |||||
| super.onCreate (savedInstanceState); | |||||
| viewHolder = new ViewHolder (this); | |||||
| setContentView (viewHolder); | |||||
| } | |||||
| @Override | |||||
| protected final void onDestroy() | |||||
| { | |||||
| quitApp(); | |||||
| super.onDestroy(); | |||||
| } | |||||
| private void callAppLauncher() | |||||
| { | |||||
| launchApp (getApplicationInfo().publicSourceDir, | |||||
| getApplicationInfo().dataDir); | |||||
| } | |||||
| //============================================================================== | |||||
| public native void launchApp (String appFile, String appDataDir); | |||||
| public native void quitApp(); | |||||
| public native void setScreenSize (int screenWidth, int screenHeight); | |||||
| //============================================================================== | |||||
| public static final void printToConsole (String s) | |||||
| { | |||||
| android.util.Log.i ("Juce", s); | |||||
| } | |||||
| //============================================================================== | |||||
| public native void deliverMessage (long value); | |||||
| private android.os.Handler messageHandler = new android.os.Handler(); | |||||
| public final void postMessage (long value) | |||||
| { | |||||
| messageHandler.post (new MessageCallback (value)); | |||||
| } | |||||
| private final class MessageCallback implements Runnable | |||||
| { | |||||
| public MessageCallback (long value_) { value = value_; } | |||||
| public final void run() { deliverMessage (value); } | |||||
| private long value; | |||||
| } | |||||
| //============================================================================== | |||||
| private ViewHolder viewHolder; | |||||
| public final ComponentPeerView createNewView (boolean opaque) | |||||
| { | |||||
| ComponentPeerView v = new ComponentPeerView (this, opaque); | |||||
| viewHolder.addView (v); | |||||
| return v; | |||||
| } | |||||
| public final void deleteView (ComponentPeerView view) | |||||
| { | |||||
| viewHolder.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()); | |||||
| if (isFirstResize) | |||||
| { | |||||
| isFirstResize = false; | |||||
| callAppLauncher(); | |||||
| } | |||||
| } | |||||
| 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 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) | |||||
| .setPositiveButton ("OK", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| JuceDemo.this.alertDismissed (callback, 0); | |||||
| } | |||||
| }); | |||||
| builder.create().show(); | |||||
| } | |||||
| public final void showOkCancelBox (String title, String message, final long callback) | |||||
| { | |||||
| AlertDialog.Builder builder = new AlertDialog.Builder (this); | |||||
| builder.setTitle (title) | |||||
| .setMessage (message) | |||||
| .setCancelable (true) | |||||
| .setPositiveButton ("OK", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| JuceDemo.this.alertDismissed (callback, 1); | |||||
| } | |||||
| }) | |||||
| .setNegativeButton ("Cancel", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| 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) | |||||
| .setPositiveButton ("Yes", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| JuceDemo.this.alertDismissed (callback, 1); | |||||
| } | |||||
| }) | |||||
| .setNegativeButton ("No", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| JuceDemo.this.alertDismissed (callback, 2); | |||||
| } | |||||
| }) | |||||
| .setNeutralButton ("Cancel", new DialogInterface.OnClickListener() | |||||
| { | |||||
| public void onClick (DialogInterface dialog, int id) | |||||
| { | |||||
| dialog.cancel(); | |||||
| JuceDemo.this.alertDismissed (callback, 0); | |||||
| } | |||||
| }); | |||||
| builder.create().show(); | |||||
| } | |||||
| public native void alertDismissed (long callback, int id); | |||||
| //============================================================================== | |||||
| public class ComponentPeerView extends View | |||||
| implements View.OnFocusChangeListener | |||||
| { | |||||
| public ComponentPeerView (Context context, boolean opaque_) | |||||
| { | |||||
| super (context); | |||||
| opaque = opaque_; | |||||
| setFocusable (true); | |||||
| setFocusableInTouchMode (true); | |||||
| setOnFocusChangeListener (this); | |||||
| requestFocus(); | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handlePaint (Canvas canvas); | |||||
| @Override | |||||
| public void draw (Canvas canvas) | |||||
| { | |||||
| handlePaint (canvas); | |||||
| } | |||||
| @Override | |||||
| public boolean isOpaque() | |||||
| { | |||||
| return opaque; | |||||
| } | |||||
| private boolean opaque; | |||||
| //============================================================================== | |||||
| private native void handleMouseDown (float x, float y, long time); | |||||
| private native void handleMouseDrag (float x, float y, long time); | |||||
| private native void handleMouseUp (float x, float y, long time); | |||||
| @Override | |||||
| public boolean onTouchEvent (MotionEvent event) | |||||
| { | |||||
| switch (event.getAction()) | |||||
| { | |||||
| case MotionEvent.ACTION_DOWN: handleMouseDown (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_MOVE: handleMouseDrag (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_CANCEL: | |||||
| case MotionEvent.ACTION_UP: handleMouseUp (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| default: break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
| { | |||||
| viewSizeChanged(); | |||||
| } | |||||
| @Override | |||||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) {} | |||||
| private native void viewSizeChanged(); | |||||
| @Override | |||||
| public void onFocusChange (View v, boolean hasFocus) | |||||
| { | |||||
| if (v == this) | |||||
| focusChanged (hasFocus); | |||||
| } | |||||
| private native void focusChanged (boolean hasFocus); | |||||
| public void setViewName (String newName) {} | |||||
| 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 final int[] renderGlyph (char glyph, Paint paint, android.graphics.Matrix matrix, Rect bounds) | |||||
| { | |||||
| Path p = new Path(); | |||||
| paint.getTextPath (String.valueOf (glyph), 0, 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 = 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); | |||||
| 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 HTTPStream | |||||
| { | |||||
| public HTTPStream (HttpURLConnection connection_) throws IOException | |||||
| { | |||||
| connection = connection_; | |||||
| inputStream = new BufferedInputStream (connection.getInputStream()); | |||||
| } | |||||
| public final void release() | |||||
| { | |||||
| try | |||||
| { | |||||
| inputStream.close(); | |||||
| } | |||||
| catch (IOException e) | |||||
| {} | |||||
| connection.disconnect(); | |||||
| } | |||||
| public final int read (byte[] buffer, int numBytes) | |||||
| { | |||||
| int num = 0; | |||||
| try | |||||
| { | |||||
| 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 -1; | |||||
| } | |||||
| public final boolean isExhausted() | |||||
| { | |||||
| return false; | |||||
| } | |||||
| public final boolean setPosition (long newPos) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| private HttpURLConnection connection; | |||||
| private InputStream inputStream; | |||||
| private long position; | |||||
| } | |||||
| public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData, | |||||
| String headers, int timeOutMs, java.lang.StringBuffer responseHeaders) | |||||
| { | |||||
| try | |||||
| { | |||||
| HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection()); | |||||
| if (connection != null) | |||||
| { | |||||
| try | |||||
| { | |||||
| if (isPost) | |||||
| { | |||||
| connection.setConnectTimeout (timeOutMs); | |||||
| connection.setDoOutput (true); | |||||
| connection.setChunkedStreamingMode (0); | |||||
| OutputStream out = connection.getOutputStream(); | |||||
| out.write (postData); | |||||
| out.flush(); | |||||
| } | |||||
| return new HTTPStream (connection); | |||||
| } | |||||
| catch (Throwable e) | |||||
| { | |||||
| connection.disconnect(); | |||||
| } | |||||
| } | |||||
| } | |||||
| catch (Throwable e) | |||||
| {} | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -74,12 +74,12 @@ | |||||
| </VS2010> | </VS2010> | ||||
| <ANDROID targetFolder="Builds/Android" androidSDKPath="${user.home}/SDKs/android-sdk-macosx" | <ANDROID targetFolder="Builds/Android" androidSDKPath="${user.home}/SDKs/android-sdk-macosx" | ||||
| androidNDKPath="${user.home}/SDKs/android-ndk-r7b" juceFolder="../../../juce" | androidNDKPath="${user.home}/SDKs/android-ndk-r7b" juceFolder="../../../juce" | ||||
| androidInternetNeeded="1" bigIcon="f4hwldS"> | |||||
| androidInternetNeeded="1" bigIcon="f4hwldS" androidActivityClass="com.juce.JuceDemo"> | |||||
| <CONFIGURATIONS> | <CONFIGURATIONS> | ||||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | ||||
| defines="JUCE_UNIT_TESTS=1"/> | |||||
| defines="JUCE_UNIT_TESTS=1" androidArchitectures="armeabi"/> | |||||
| <CONFIGURATION name="Release" isDebug="0" optimisation="2" targetName="JuceDemo" | <CONFIGURATION name="Release" isDebug="0" optimisation="2" targetName="JuceDemo" | ||||
| defines="JUCE_UNIT_TESTS=1"/> | |||||
| defines="JUCE_UNIT_TESTS=1" androidArchitectures="armeabi armeabi-v7a"/> | |||||
| </CONFIGURATIONS> | </CONFIGURATIONS> | ||||
| </ANDROID> | </ANDROID> | ||||
| </EXPORTFORMATS> | </EXPORTFORMATS> | ||||
| @@ -1,124 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-10 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| package com.juce; | |||||
| import android.content.Context; | |||||
| import android.view.*; | |||||
| import android.graphics.*; | |||||
| //============================================================================== | |||||
| public class ComponentPeerView extends View | |||||
| implements View.OnFocusChangeListener | |||||
| { | |||||
| public ComponentPeerView (Context context, boolean opaque_) | |||||
| { | |||||
| super (context); | |||||
| opaque = opaque_; | |||||
| setFocusable (true); | |||||
| setFocusableInTouchMode (true); | |||||
| setOnFocusChangeListener (this); | |||||
| requestFocus(); | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handlePaint (Canvas canvas); | |||||
| @Override | |||||
| public void draw (Canvas canvas) | |||||
| { | |||||
| handlePaint (canvas); | |||||
| } | |||||
| @Override | |||||
| public boolean isOpaque() | |||||
| { | |||||
| return opaque; | |||||
| } | |||||
| private boolean opaque; | |||||
| //============================================================================== | |||||
| private native void handleMouseDown (float x, float y, long time); | |||||
| private native void handleMouseDrag (float x, float y, long time); | |||||
| private native void handleMouseUp (float x, float y, long time); | |||||
| @Override | |||||
| public boolean onTouchEvent (MotionEvent event) | |||||
| { | |||||
| switch (event.getAction()) | |||||
| { | |||||
| case MotionEvent.ACTION_DOWN: handleMouseDown (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_MOVE: handleMouseDrag (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_CANCEL: | |||||
| case MotionEvent.ACTION_UP: handleMouseUp (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| default: break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
| { | |||||
| viewSizeChanged(); | |||||
| } | |||||
| @Override | |||||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||||
| { | |||||
| } | |||||
| private native void viewSizeChanged(); | |||||
| @Override | |||||
| public void onFocusChange (View v, boolean hasFocus) | |||||
| { | |||||
| if (v == this) | |||||
| focusChanged (hasFocus); | |||||
| } | |||||
| private native void focusChanged (boolean hasFocus); | |||||
| public void setViewName (String newName) | |||||
| { | |||||
| } | |||||
| 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 | |||||
| } | |||||
| } | |||||
| @@ -28,18 +28,11 @@ package com.juce; | |||||
| import android.app.Activity; | import android.app.Activity; | ||||
| import android.app.AlertDialog; | import android.app.AlertDialog; | ||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||
| import android.os.Bundle; | |||||
| import android.content.Context; | import android.content.Context; | ||||
| import android.view.ViewGroup; | |||||
| import android.graphics.Paint; | |||||
| import android.graphics.Canvas; | |||||
| import android.graphics.Path; | |||||
| import android.graphics.Bitmap; | |||||
| import android.graphics.Matrix; | |||||
| import android.graphics.RectF; | |||||
| import android.graphics.Rect; | |||||
| import android.os.Bundle; | |||||
| import android.view.*; | |||||
| import android.graphics.*; | |||||
| import android.text.ClipboardManager; | import android.text.ClipboardManager; | ||||
| import com.juce.ComponentPeerView; | |||||
| import java.io.BufferedInputStream; | import java.io.BufferedInputStream; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| @@ -98,17 +91,10 @@ public final class JuceAppActivity extends Activity | |||||
| messageHandler.post (new MessageCallback (value)); | messageHandler.post (new MessageCallback (value)); | ||||
| } | } | ||||
| final class MessageCallback implements Runnable | |||||
| private final class MessageCallback implements Runnable | |||||
| { | { | ||||
| public MessageCallback (long value_) | |||||
| { | |||||
| value = value_; | |||||
| } | |||||
| public final void run() | |||||
| { | |||||
| deliverMessage (value); | |||||
| } | |||||
| public MessageCallback (long value_) { value = value_; } | |||||
| public final void run() { deliverMessage (value); } | |||||
| private long value; | private long value; | ||||
| } | } | ||||
| @@ -251,7 +237,91 @@ public final class JuceAppActivity extends Activity | |||||
| public native void alertDismissed (long callback, int id); | public native void alertDismissed (long callback, int id); | ||||
| //============================================================================== | //============================================================================== | ||||
| public final int[] renderGlyph (char glyph, Paint paint, Matrix matrix, Rect bounds) | |||||
| public class ComponentPeerView extends View | |||||
| implements View.OnFocusChangeListener | |||||
| { | |||||
| public ComponentPeerView (Context context, boolean opaque_) | |||||
| { | |||||
| super (context); | |||||
| opaque = opaque_; | |||||
| setFocusable (true); | |||||
| setFocusableInTouchMode (true); | |||||
| setOnFocusChangeListener (this); | |||||
| requestFocus(); | |||||
| } | |||||
| //============================================================================== | |||||
| private native void handlePaint (Canvas canvas); | |||||
| @Override | |||||
| public void draw (Canvas canvas) | |||||
| { | |||||
| handlePaint (canvas); | |||||
| } | |||||
| @Override | |||||
| public boolean isOpaque() | |||||
| { | |||||
| return opaque; | |||||
| } | |||||
| private boolean opaque; | |||||
| //============================================================================== | |||||
| private native void handleMouseDown (float x, float y, long time); | |||||
| private native void handleMouseDrag (float x, float y, long time); | |||||
| private native void handleMouseUp (float x, float y, long time); | |||||
| @Override | |||||
| public boolean onTouchEvent (MotionEvent event) | |||||
| { | |||||
| switch (event.getAction()) | |||||
| { | |||||
| case MotionEvent.ACTION_DOWN: handleMouseDown (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_MOVE: handleMouseDrag (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| case MotionEvent.ACTION_CANCEL: | |||||
| case MotionEvent.ACTION_UP: handleMouseUp (event.getX(), event.getY(), event.getEventTime()); return true; | |||||
| default: break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| //============================================================================== | |||||
| @Override | |||||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||||
| { | |||||
| viewSizeChanged(); | |||||
| } | |||||
| @Override | |||||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) {} | |||||
| private native void viewSizeChanged(); | |||||
| @Override | |||||
| public void onFocusChange (View v, boolean hasFocus) | |||||
| { | |||||
| if (v == this) | |||||
| focusChanged (hasFocus); | |||||
| } | |||||
| private native void focusChanged (boolean hasFocus); | |||||
| public void setViewName (String newName) {} | |||||
| 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 final int[] renderGlyph (char glyph, Paint paint, android.graphics.Matrix matrix, Rect bounds) | |||||
| { | { | ||||
| Path p = new Path(); | Path p = new Path(); | ||||
| paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p); | paint.getTextPath (String.valueOf (glyph), 0, 1, 0.0f, 0.0f, p); | ||||
| @@ -30,6 +30,10 @@ | |||||
| #define USE_ANDROID_CANVAS 0 | #define USE_ANDROID_CANVAS 0 | ||||
| #endif | #endif | ||||
| #if ! (defined (JUCE_ANDROID_ACTIVITY_CLASSNAME) && defined (JUCE_ANDROID_ACTIVITY_CLASSPATH)) | |||||
| #error "The JUCE_ANDROID_ACTIVITY_CLASSNAME and JUCE_ANDROID_ACTIVITY_CLASSPATH macros must be set!" | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| extern JNIEnv* getEnv() noexcept; | extern JNIEnv* getEnv() noexcept; | ||||
| @@ -226,7 +230,7 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| #define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | #define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | ||||
| extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params | |||||
| extern "C" __attribute__ ((visibility("default"))) returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params | |||||
| //============================================================================== | //============================================================================== | ||||
| class AndroidSystem | class AndroidSystem | ||||
| @@ -330,20 +334,20 @@ extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; | |||||
| //============================================================================== | //============================================================================== | ||||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | ||||
| STATICMETHOD (printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | STATICMETHOD (printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | ||||
| METHOD (createNewView, "createNewView", "(Z)Lcom/juce/ComponentPeerView;") \ | |||||
| METHOD (deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ | |||||
| METHOD (createNewView, "createNewView", "(Z)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \ | |||||
| METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \ | |||||
| METHOD (postMessage, "postMessage", "(J)V") \ | METHOD (postMessage, "postMessage", "(J)V") \ | ||||
| METHOD (finish, "finish", "()V") \ | METHOD (finish, "finish", "()V") \ | ||||
| METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \ | METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \ | ||||
| METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \ | METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \ | ||||
| METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ | METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ | ||||
| METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ | METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ | ||||
| STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \ | |||||
| STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \ | |||||
| METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | ||||
| METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | ||||
| METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | ||||
| DECLARE_JNI_CLASS (JuceAppActivity, "com/juce/JuceAppActivity"); | |||||
| DECLARE_JNI_CLASS (JuceAppActivity, JUCE_ANDROID_ACTIVITY_CLASSPATH); | |||||
| #undef JNI_CLASS_MEMBERS | #undef JNI_CLASS_MEMBERS | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -40,7 +40,7 @@ DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer"); | |||||
| METHOD (isExhausted, "isExhausted", "()Z") \ | METHOD (isExhausted, "isExhausted", "()Z") \ | ||||
| METHOD (setPosition, "setPosition", "(J)Z") \ | METHOD (setPosition, "setPosition", "(J)Z") \ | ||||
| DECLARE_JNI_CLASS (HTTPStream, "com/juce/JuceAppActivity$HTTPStream"); | |||||
| DECLARE_JNI_CLASS (HTTPStream, JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream"); | |||||
| #undef JNI_CLASS_MEMBERS | #undef JNI_CLASS_MEMBERS | ||||
| @@ -43,7 +43,7 @@ bool MessageManager::postMessageToSystemQueue (Message* message) | |||||
| return true; | return true; | ||||
| } | } | ||||
| JUCE_JNI_CALLBACK (JuceAppActivity, deliverMessage, void, (jobject activity, jlong value)) | |||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (jobject activity, jlong value)) | |||||
| { | { | ||||
| Message* const message = (Message*) (pointer_sized_uint) value; | Message* const message = (Message*) (pointer_sized_uint) value; | ||||
| MessageManager::getInstance()->deliverMessage (message); | MessageManager::getInstance()->deliverMessage (message); | ||||
| @@ -31,8 +31,8 @@ namespace juce | |||||
| { | { | ||||
| //============================================================================== | //============================================================================== | ||||
| JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activity, | |||||
| jstring appFile, jstring appDataDir)) | |||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* env, jobject activity, | |||||
| jstring appFile, jstring appDataDir)) | |||||
| { | { | ||||
| android.initialise (env, activity, appFile, appDataDir); | android.initialise (env, activity, appFile, appDataDir); | ||||
| @@ -47,7 +47,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, launchApp, void, (JNIEnv* env, jobject activ | |||||
| exit (0); | exit (0); | ||||
| } | } | ||||
| JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activity)) | |||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, quitApp, void, (JNIEnv* env, jobject activity)) | |||||
| { | { | ||||
| JUCEApplicationBase::appWillTerminateByForce(); | JUCEApplicationBase::appWillTerminateByForce(); | ||||
| @@ -79,7 +79,7 @@ DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas"); | |||||
| METHOD (invalidate, "invalidate", "(IIII)V") \ | METHOD (invalidate, "invalidate", "(IIII)V") \ | ||||
| METHOD (containsPoint, "containsPoint", "(II)Z") \ | METHOD (containsPoint, "containsPoint", "(II)Z") \ | ||||
| DECLARE_JNI_CLASS (ComponentPeerView, "com/juce/ComponentPeerView"); | |||||
| DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView"); | |||||
| #undef JNI_CLASS_MEMBERS | #undef JNI_CLASS_MEMBERS | ||||
| @@ -565,7 +565,7 @@ Point<int> AndroidComponentPeer::lastMousePos; | |||||
| //============================================================================== | //============================================================================== | ||||
| #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | ||||
| JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ | |||||
| JUCE_JNI_CALLBACK (JUCE_JOIN_MACRO (JUCE_ANDROID_ACTIVITY_CLASSNAME, _00024ComponentPeerView), javaMethodName, returnType, params) \ | |||||
| { \ | { \ | ||||
| AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (env, view); \ | AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (env, view); \ | ||||
| if (peer != nullptr) \ | if (peer != nullptr) \ | ||||
| @@ -671,8 +671,8 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| JUCE_JNI_CALLBACK (JuceAppActivity, alertDismissed, void, (JNIEnv* env, jobject activity, | |||||
| jlong callbackAsLong, jint result)) | |||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, alertDismissed, void, (JNIEnv* env, jobject activity, | |||||
| jlong callbackAsLong, jint result)) | |||||
| { | { | ||||
| ModalComponentManager::Callback* callback = (ModalComponentManager::Callback*) callbackAsLong; | ModalComponentManager::Callback* callback = (ModalComponentManager::Callback*) callbackAsLong; | ||||
| @@ -703,8 +703,8 @@ void Desktop::getCurrentMonitorPositions (Array <Rectangle<int> >& monitorCoords | |||||
| monitorCoords.add (Rectangle<int> (0, 0, android.screenWidth, android.screenHeight)); | monitorCoords.add (Rectangle<int> (0, 0, android.screenWidth, android.screenHeight)); | ||||
| } | } | ||||
| JUCE_JNI_CALLBACK (JuceAppActivity, setScreenSize, void, (JNIEnv* env, jobject activity, | |||||
| jint screenWidth, jint screenHeight)) | |||||
| JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, setScreenSize, void, (JNIEnv* env, jobject activity, | |||||
| jint screenWidth, jint screenHeight)) | |||||
| { | { | ||||
| const bool isSystemInitialised = android.screenWidth != 0; | const bool isSystemInitialised = android.screenWidth != 0; | ||||
| android.screenWidth = screenWidth; | android.screenWidth = screenWidth; | ||||