| @@ -63,6 +63,9 @@ public: | |||
| if (getNDKPath().toString().isEmpty()) | |||
| getNDKPath() = "${user.home}/SDKs/android-ndk-r7"; | |||
| if (getMinimumSDKVersion().toString().isEmpty()) | |||
| getMinimumSDKVersion() = 7; | |||
| if (getInternetNeeded().toString().isEmpty()) | |||
| getInternetNeeded() = true; | |||
| } | |||
| @@ -100,12 +103,21 @@ public: | |||
| props.add (new BooleanPropertyComponent (getInternetNeeded(), "Internet Access", "Specify internet access permission in the manifest"), | |||
| "If enabled, this will set the android.permission.INTERNET flag in the manifest."); | |||
| props.add (new BooleanPropertyComponent (getAudioRecordNeeded(), "Audio Input Required", "Specify audio record permission in the manifest"), | |||
| "If enabled, this will set the android.permission.RECORD_AUDIO flag in the manifest."); | |||
| props.add (new TextPropertyComponent (getOtherPermissions(), "Custom permissions", 2048, false), | |||
| "A space-separated list of other permission flags that should be added to the manifest."); | |||
| } | |||
| Value getActivityClassPath() const { return getSetting (Ids::androidActivityClass); } | |||
| Value getSDKPath() const { return getSetting (Ids::androidSDKPath); } | |||
| Value getNDKPath() const { return getSetting (Ids::androidNDKPath); } | |||
| Value getInternetNeeded() const { return getSetting (Ids::androidInternetNeeded); } | |||
| Value getAudioRecordNeeded() const { return getSetting (Ids::androidMicNeeded); } | |||
| Value getMinimumSDKVersion() const { return getSetting (Ids::androidMinimumSDK); } | |||
| Value getOtherPermissions() const { return getSetting (Ids::androidOtherPermissions); } | |||
| String createDefaultClassName() const | |||
| { | |||
| @@ -224,10 +236,13 @@ private: | |||
| //screens->setAttribute ("android:xlargeScreens", "true"); | |||
| screens->setAttribute ("android:anyDensity", "true"); | |||
| if (getInternetNeeded().getValue()) | |||
| manifest->createNewChildElement ("uses-sdk")->setAttribute ("android:minSdkVersion", getMinimumSDKVersion().toString()); | |||
| { | |||
| XmlElement* permission = manifest->createNewChildElement ("uses-permission"); | |||
| permission->setAttribute ("android:name", "android.permission.INTERNET"); | |||
| const StringArray permissions (getPermissionsRequired()); | |||
| for (int i = permissions.size(); --i >= 0;) | |||
| manifest->createNewChildElement ("uses-permission")->setAttribute ("android:name", permissions[i]); | |||
| } | |||
| XmlElement* app = manifest->createNewChildElement ("application"); | |||
| @@ -245,6 +260,19 @@ private: | |||
| return manifest; | |||
| } | |||
| StringArray getPermissionsRequired() const | |||
| { | |||
| StringArray s; | |||
| s.addTokens (getOtherPermissions().toString(), ", ", ""); | |||
| if (getInternetNeeded().getValue()) s.add ("android.permission.INTERNET"); | |||
| if (getAudioRecordNeeded().getValue()) s.add ("android.permission.RECORD_AUDIO"); | |||
| s.trim(); | |||
| s.removeDuplicates (false); | |||
| return s; | |||
| } | |||
| //============================================================================== | |||
| void findAllFilesToCompile (const Project::Item& projectItem, Array<RelativePath>& results) | |||
| { | |||
| @@ -102,6 +102,9 @@ namespace Ids | |||
| DECLARE_ID (androidNDKPath); | |||
| DECLARE_ID (androidInternetNeeded); | |||
| DECLARE_ID (androidArchitectures); | |||
| DECLARE_ID (androidMicNeeded); | |||
| DECLARE_ID (androidMinimumSDK); | |||
| DECLARE_ID (androidOtherPermissions); | |||
| const Identifier class_ ("class"); | |||
| #undef DECLARE_ID | |||
| @@ -3,6 +3,8 @@ | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" | |||
| package="com.juce"> | |||
| <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/> | |||
| <uses-sdk android:minSdkVersion="7"/> | |||
| <uses-permission android:name="android.permission.RECORD_AUDIO"/> | |||
| <uses-permission android:name="android.permission.INTERNET"/> | |||
| <application android:label="@string/app_name" android:icon="@drawable/icon"> | |||
| <activity android:name="JuceDemo" android:label="@string/app_name"> | |||
| @@ -74,7 +74,8 @@ | |||
| </VS2010> | |||
| <ANDROID targetFolder="Builds/Android" androidSDKPath="${user.home}/SDKs/android-sdk-macosx" | |||
| androidNDKPath="${user.home}/SDKs/android-ndk-r7b" juceFolder="../../../juce" | |||
| androidInternetNeeded="1" bigIcon="f4hwldS" androidActivityClass="com.juce.JuceDemo"> | |||
| androidInternetNeeded="1" bigIcon="f4hwldS" androidActivityClass="com.juce.JuceDemo" | |||
| androidMinimumSDK="7" androidMicNeeded="1"> | |||
| <CONFIGURATIONS> | |||
| <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo" | |||
| defines="JUCE_UNIT_TESTS=1" androidArchitectures="armeabi"/> | |||
| @@ -704,20 +704,12 @@ public: | |||
| for (int i = 0; i < items.size(); i += 2) | |||
| { | |||
| const String name (items[i]); | |||
| const String name2 (items[i + 1]); | |||
| String commonBit; | |||
| const String& name = items[i]; | |||
| for (int j = 0; j < name.length(); ++j) | |||
| if (name.substring (0, j).equalsIgnoreCase (name2.substring (0, j))) | |||
| commonBit = name.substring (0, j); | |||
| // Make sure we only split the name at a space, because otherwise, things | |||
| // like "input 11" + "input 12" would become "input 11 + 2" | |||
| while (commonBit.isNotEmpty() && ! CharacterFunctions::isWhitespace (commonBit.getLastCharacter())) | |||
| commonBit = commonBit.dropLastCharacters (1); | |||
| pairs.add (name.trim() + " + " + name2.substring (commonBit.length()).trim()); | |||
| if (i + 1 >= items.size()) | |||
| pairs.add (name.trim()); | |||
| else | |||
| pairs.add (getNameForChannelPair (name, items[i + 1])); | |||
| } | |||
| items = pairs; | |||
| @@ -820,6 +812,22 @@ public: | |||
| const String noItemsMessage; | |||
| StringArray items; | |||
| static String getNameForChannelPair (const String& name1, const String& name2) | |||
| { | |||
| String commonBit; | |||
| for (int j = 0; j < name1.length(); ++j) | |||
| if (name1.substring (0, j).equalsIgnoreCase (name2.substring (0, j))) | |||
| commonBit = name1.substring (0, j); | |||
| // Make sure we only split the name at a space, because otherwise, things | |||
| // like "input 11" + "input 12" would become "input 11 + 2" | |||
| while (commonBit.isNotEmpty() && ! CharacterFunctions::isWhitespace (commonBit.getLastCharacter())) | |||
| commonBit = commonBit.dropLastCharacters (1); | |||
| return name1.trim() + " + " + name2.substring (commonBit.length()).trim(); | |||
| } | |||
| void flipEnablement (const int row) | |||
| { | |||
| jassert (type == audioInputType || type == audioOutputType); | |||
| @@ -248,6 +248,9 @@ using namespace juce; | |||
| //============================================================================== | |||
| namespace juce | |||
| { | |||
| #if JUCE_IOS || JUCE_WINDOWS | |||
| #include "native/juce_MultiTouchMapper.h" | |||
| #endif | |||
| #if JUCE_MAC || JUCE_IOS | |||
| #include "../juce_core/native/juce_osx_ObjCHelpers.h" | |||
| @@ -256,7 +259,6 @@ namespace juce | |||
| #include "../juce_graphics/native/juce_mac_CoreGraphicsContext.h" | |||
| #if JUCE_IOS | |||
| #include "native/juce_MultiTouchMapper.h" | |||
| #include "native/juce_ios_UIViewComponentPeer.mm" | |||
| #include "native/juce_ios_Windowing.mm" | |||
| #else | |||
| @@ -271,7 +273,6 @@ namespace juce | |||
| #elif JUCE_WINDOWS | |||
| #include "../juce_core/native/juce_win32_ComSmartPtr.h" | |||
| #include "../juce_events/native/juce_win32_HiddenMessageWindow.h" | |||
| #include "native/juce_MultiTouchMapper.h" | |||
| #include "native/juce_win32_Windowing.cpp" | |||
| #include "native/juce_win32_DragAndDrop.cpp" | |||
| #include "native/juce_win32_FileChooser.cpp" | |||