diff --git a/examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java b/examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java index 4b248803c6..703e23abce 100644 --- a/examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java +++ b/examples/Demo/Builds/Android/app/src/main/java/com/yourcompany/jucedemo/JuceDemo.java @@ -519,11 +519,18 @@ public class JuceDemo extends Activity 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.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 0); } }); @@ -538,11 +545,18 @@ public class JuceDemo extends Activity 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.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 1); } }) @@ -550,7 +564,7 @@ public class JuceDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 0); } }); @@ -564,11 +578,18 @@ public class JuceDemo extends Activity 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.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 1); } }) @@ -576,7 +597,7 @@ public class JuceDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 2); } }) @@ -584,7 +605,7 @@ public class JuceDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemo.this.alertDismissed (callback, 0); } }); @@ -982,13 +1003,75 @@ public class JuceDemo extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1011,19 +1094,12 @@ public class JuceDemo extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1031,6 +1107,89 @@ public class JuceDemo extends Activity } 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) { @@ -1068,9 +1227,16 @@ public class JuceDemo extends Activity {} 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"); + { + 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; } @@ -1173,13 +1339,20 @@ public class JuceDemo extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -1201,89 +1374,15 @@ public class JuceDemo extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); - - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -1309,7 +1408,14 @@ public class JuceDemo extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -1404,7 +1510,7 @@ public class JuceDemo extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt b/examples/InAppPurchase/Builds/Android/app/CMakeLists.txt index 089a14d0b7..eedb74d85b 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\"" "-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_IN_APP_PURCHASES=1" "-DJUCER_ANDROIDSTUDIO_7F0E4A25=1" "-DJUCE_APP_VERSION=0.0.2" "-DJUCE_APP_VERSION_HEX=0x2") include_directories( AFTER "../../../JuceLibraryCode" diff --git a/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/InAppPurchase.java b/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/InAppPurchase.java index 3843d8fa1c..05a6ab9409 100644 --- a/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/InAppPurchase.java +++ b/examples/InAppPurchase/Builds/Android/app/src/main/java/com/roli/juceinapppurchasesample/InAppPurchase.java @@ -519,11 +519,18 @@ public class InAppPurchase extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + InAppPurchase.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 0); } }); @@ -538,11 +545,18 @@ public class InAppPurchase extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + InAppPurchase.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 1); } }) @@ -550,7 +564,7 @@ public class InAppPurchase extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 0); } }); @@ -564,11 +578,18 @@ public class InAppPurchase extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + InAppPurchase.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 1); } }) @@ -576,7 +597,7 @@ public class InAppPurchase extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 2); } }) @@ -584,7 +605,7 @@ public class InAppPurchase extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); InAppPurchase.this.alertDismissed (callback, 0); } }); @@ -982,13 +1003,75 @@ public class InAppPurchase extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1011,19 +1094,12 @@ public class InAppPurchase extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1031,6 +1107,89 @@ public class InAppPurchase extends Activity } 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) { @@ -1068,9 +1227,16 @@ public class InAppPurchase extends Activity {} 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"); + { + 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; } @@ -1173,13 +1339,20 @@ public class InAppPurchase extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -1201,89 +1374,15 @@ public class InAppPurchase extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); - - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -1309,7 +1408,14 @@ public class InAppPurchase extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -1404,7 +1510,7 @@ public class InAppPurchase extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/InAppPurchase/Builds/iOS/InAppPurchase.xcodeproj/project.pbxproj b/examples/InAppPurchase/Builds/iOS/InAppPurchase.xcodeproj/project.pbxproj index 92aa55501a..e74d1b597e 100644 --- a/examples/InAppPurchase/Builds/iOS/InAppPurchase.xcodeproj/project.pbxproj +++ b/examples/InAppPurchase/Builds/iOS/InAppPurchase.xcodeproj/project.pbxproj @@ -223,6 +223,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "_DEBUG=1", "DEBUG=1", + "JUCE_IN_APP_PURCHASES=1", "JUCER_XCODE_IPHONE_5BC26AE3=1", "JUCE_APP_VERSION=0.0.2", "JUCE_APP_VERSION_HEX=0x2", @@ -254,6 +255,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "_NDEBUG=1", "NDEBUG=1", + "JUCE_IN_APP_PURCHASES=1", "JUCER_XCODE_IPHONE_5BC26AE3=1", "JUCE_APP_VERSION=0.0.2", "JUCE_APP_VERSION_HEX=0x2", diff --git a/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java b/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java index 9afbb4fa1d..5eeb94785f 100644 --- a/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java +++ b/examples/MidiTest/Builds/Android/app/src/main/java/com/yourcompany/miditest/MidiTest.java @@ -1448,11 +1448,18 @@ public class MidiTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + MidiTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 0); } }); @@ -1467,11 +1474,18 @@ public class MidiTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + MidiTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 1); } }) @@ -1479,7 +1493,7 @@ public class MidiTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 0); } }); @@ -1493,11 +1507,18 @@ public class MidiTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + MidiTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 1); } }) @@ -1505,7 +1526,7 @@ public class MidiTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 2); } }) @@ -1513,7 +1534,7 @@ public class MidiTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); MidiTest.this.alertDismissed (callback, 0); } }); @@ -1911,13 +1932,75 @@ public class MidiTest extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1940,19 +2023,12 @@ public class MidiTest extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1960,6 +2036,89 @@ public class MidiTest extends Activity } 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) { @@ -1997,9 +2156,16 @@ public class MidiTest extends Activity {} 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"); + { + 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; } @@ -2102,13 +2268,20 @@ public class MidiTest extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -2130,89 +2303,15 @@ public class MidiTest extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); - - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -2238,7 +2337,14 @@ public class MidiTest extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -2333,7 +2439,7 @@ public class MidiTest extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java b/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java index c8085c28d3..bac81b0d10 100644 --- a/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java +++ b/examples/NetworkGraphicsDemo/Builds/Android/app/src/main/java/com/juce/networkgraphicsdemo/JUCENetworkGraphicsDemo.java @@ -519,11 +519,18 @@ public class JUCENetworkGraphicsDemo extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); } }); @@ -538,11 +545,18 @@ public class JUCENetworkGraphicsDemo extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 1); } }) @@ -550,7 +564,7 @@ public class JUCENetworkGraphicsDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); } }); @@ -564,11 +578,18 @@ public class JUCENetworkGraphicsDemo extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 1); } }) @@ -576,7 +597,7 @@ public class JUCENetworkGraphicsDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 2); } }) @@ -584,7 +605,7 @@ public class JUCENetworkGraphicsDemo extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JUCENetworkGraphicsDemo.this.alertDismissed (callback, 0); } }); @@ -982,13 +1003,75 @@ public class JUCENetworkGraphicsDemo extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1011,19 +1094,12 @@ public class JUCENetworkGraphicsDemo extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1031,6 +1107,89 @@ public class JUCENetworkGraphicsDemo extends Activity } 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) { @@ -1068,9 +1227,16 @@ public class JUCENetworkGraphicsDemo extends Activity {} 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"); + { + 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; } @@ -1173,13 +1339,20 @@ public class JUCENetworkGraphicsDemo extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -1201,89 +1374,15 @@ public class JUCENetworkGraphicsDemo extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); - - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -1309,7 +1408,14 @@ public class JUCENetworkGraphicsDemo extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -1404,7 +1510,7 @@ public class JUCENetworkGraphicsDemo extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java b/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java index a49408d60b..d08af129e5 100644 --- a/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java +++ b/examples/OSCReceiver/Builds/Android/app/src/main/java/com/yourcompany/oscreceiver/OSCReceiver.java @@ -519,11 +519,18 @@ public class OSCReceiver extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCReceiver.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 0); } }); @@ -538,11 +545,18 @@ public class OSCReceiver extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCReceiver.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 1); } }) @@ -550,7 +564,7 @@ public class OSCReceiver extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 0); } }); @@ -564,11 +578,18 @@ public class OSCReceiver extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCReceiver.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 1); } }) @@ -576,7 +597,7 @@ public class OSCReceiver extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 2); } }) @@ -584,7 +605,7 @@ public class OSCReceiver extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCReceiver.this.alertDismissed (callback, 0); } }); @@ -982,13 +1003,75 @@ public class OSCReceiver extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1011,19 +1094,12 @@ public class OSCReceiver extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1031,6 +1107,89 @@ public class OSCReceiver extends Activity } 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) { @@ -1068,9 +1227,16 @@ public class OSCReceiver extends Activity {} 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"); + { + 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; } @@ -1173,13 +1339,20 @@ public class OSCReceiver extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -1201,89 +1374,15 @@ public class OSCReceiver extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); - - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -1309,7 +1408,14 @@ public class OSCReceiver extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -1404,7 +1510,7 @@ public class OSCReceiver extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java b/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java index fa138371bf..b22efadf57 100644 --- a/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java +++ b/examples/OSCSender/Builds/Android/app/src/main/java/com/yourcompany/oscsender/OSCSender.java @@ -519,11 +519,18 @@ public class OSCSender extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCSender.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 0); } }); @@ -538,11 +545,18 @@ public class OSCSender extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCSender.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 1); } }) @@ -550,7 +564,7 @@ public class OSCSender extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 0); } }); @@ -564,11 +578,18 @@ public class OSCSender extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + OSCSender.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 1); } }) @@ -576,7 +597,7 @@ public class OSCSender extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 2); } }) @@ -584,7 +605,7 @@ public class OSCSender extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); OSCSender.this.alertDismissed (callback, 0); } }); @@ -982,13 +1003,75 @@ public class OSCSender extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1011,19 +1094,12 @@ public class OSCSender extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1031,6 +1107,89 @@ public class OSCSender extends Activity } 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) { @@ -1068,9 +1227,16 @@ public class OSCSender extends Activity {} 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"); + { + 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; } @@ -1173,13 +1339,20 @@ public class OSCSender extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -1201,89 +1374,15 @@ public class OSCSender extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); - - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -1309,7 +1408,14 @@ public class OSCSender extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -1404,7 +1510,7 @@ public class OSCSender extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java b/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java index c76005c03c..59ac9dc0cf 100644 --- a/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java +++ b/examples/audio plugin demo/Builds/Android/app/src/main/java/com/juce/jucedemoplugin/JuceDemoPlugin.java @@ -1448,11 +1448,18 @@ public class JuceDemoPlugin extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JuceDemoPlugin.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 0); } }); @@ -1467,11 +1474,18 @@ public class JuceDemoPlugin extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JuceDemoPlugin.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 1); } }) @@ -1479,7 +1493,7 @@ public class JuceDemoPlugin extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 0); } }); @@ -1493,11 +1507,18 @@ public class JuceDemoPlugin extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + JuceDemoPlugin.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 1); } }) @@ -1505,7 +1526,7 @@ public class JuceDemoPlugin extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 2); } }) @@ -1513,7 +1534,7 @@ public class JuceDemoPlugin extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); JuceDemoPlugin.this.alertDismissed (callback, 0); } }); @@ -1911,13 +1932,75 @@ public class JuceDemoPlugin extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1940,19 +2023,12 @@ public class JuceDemoPlugin extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1960,6 +2036,89 @@ public class JuceDemoPlugin extends Activity } 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) { @@ -1997,9 +2156,16 @@ public class JuceDemoPlugin extends Activity {} 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"); + { + 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; } @@ -2102,13 +2268,20 @@ public class JuceDemoPlugin extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -2130,89 +2303,15 @@ public class JuceDemoPlugin extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); - - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -2238,7 +2337,14 @@ public class JuceDemoPlugin extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -2333,7 +2439,7 @@ public class JuceDemoPlugin extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java b/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java index 5feced2ee7..5f1a6c3451 100644 --- a/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java +++ b/extras/AudioPerformanceTest/Builds/Android/app/src/main/java/com/juce/audioperformancetest/AudioPerformanceTest.java @@ -1448,11 +1448,18 @@ public class AudioPerformanceTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + AudioPerformanceTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("OK", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 0); } }); @@ -1467,11 +1474,18 @@ public class AudioPerformanceTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + AudioPerformanceTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton (okButtonText.isEmpty() ? "OK" : okButtonText, new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 1); } }) @@ -1479,7 +1493,7 @@ public class AudioPerformanceTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 0); } }); @@ -1493,11 +1507,18 @@ public class AudioPerformanceTest extends Activity builder.setTitle (title) .setMessage (message) .setCancelable (true) + .setOnCancelListener (new DialogInterface.OnCancelListener() + { + public void onCancel (DialogInterface dialog) + { + AudioPerformanceTest.this.alertDismissed (callback, 0); + } + }) .setPositiveButton ("Yes", new DialogInterface.OnClickListener() { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 1); } }) @@ -1505,7 +1526,7 @@ public class AudioPerformanceTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 2); } }) @@ -1513,7 +1534,7 @@ public class AudioPerformanceTest extends Activity { public void onClick (DialogInterface dialog, int id) { - dialog.cancel(); + dialog.dismiss(); AudioPerformanceTest.this.alertDismissed (callback, 0); } }); @@ -1911,13 +1932,75 @@ public class AudioPerformanceTest extends Activity //============================================================================== public static class HTTPStream { - public HTTPStream (HttpURLConnection connection_, - int[] statusCode_, - StringBuffer responseHeaders_) + public HTTPStream (String address, boolean isPostToUse, byte[] postDataToUse, + String headersToUse, int timeOutMsToUse, + int[] statusCodeToUse, StringBuffer responseHeadersToUse, + int numRedirectsToFollowToUse, String httpRequestCmdToUse) throws IOException { - connection = connection_; - statusCode = statusCode_; - responseHeaders = responseHeaders_; + 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 @@ -1940,19 +2023,12 @@ public class AudioPerformanceTest extends Activity try { - if (connection.getConnectTimeout() > 0) - return streamFuture.get (connection.getConnectTimeout(), TimeUnit.MILLISECONDS); - else - return streamFuture.get(); + return streamFuture.get(); } catch (InterruptedException e) { return null; } - catch (TimeoutException e) - { - return null; - } catch (CancellationException e) { return null; @@ -1960,6 +2036,89 @@ public class AudioPerformanceTest extends Activity } 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) { @@ -1997,9 +2156,16 @@ public class AudioPerformanceTest extends Activity {} 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"); + { + 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; } @@ -2102,13 +2268,20 @@ public class AudioPerformanceTest extends Activity } public final long getPosition() { return position; } - public final long getTotalLength() { return -1; } + 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(); @@ -2130,89 +2303,15 @@ public class AudioPerformanceTest extends Activity else if (timeOutMs == 0) timeOutMs = 30000; - // 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"); - for (;;) { try { - HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); + HTTPStream httpStream = new HTTPStream (address, isPost, postData, headers, + timeOutMs, statusCode, responseHeaders, + numRedirectsToFollow, httpRequestCmd); - if (connection != null) - { - try - { - connection.setInstanceFollowRedirects (false); - connection.setConnectTimeout (timeOutMs); - connection.setReadTimeout (timeOutMs); - - // 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) - connection.setRequestProperty (field, value); - } - } - - connection.setRequestMethod (httpRequestCmd); - if (isPost) - { - connection.setDoOutput (true); - - if (postData != null) - { - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } - } - - HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); - - // Process redirect & continue as necessary - int status = statusCode[0]; - - if (--numRedirectsToFollow >= 0 - && (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 newLocation = responseHeaders.substring(pos1, pos2); - // Handle newLocation whether it's absolute or relative - URL baseUrl = new URL (address); - URL newUrl = new URL (baseUrl, newLocation); - String transformedNewLocation = newUrl.toString(); - - if (transformedNewLocation != address) - { - address = transformedNewLocation; - // Clear responseHeaders before next iteration - responseHeaders.delete (0, responseHeaders.length()); - continue; - } - } - } - - return httpStream; - } - catch (Throwable e) - { - connection.disconnect(); - } - } + return httpStream; } catch (Throwable e) {} @@ -2238,7 +2337,14 @@ public class AudioPerformanceTest extends Activity return Environment.getExternalStoragePublicDirectory (type).getAbsolutePath(); } - public static final String getDocumentsFolder() { return Environment.getDataDirectory().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); } @@ -2333,7 +2439,7 @@ public class AudioPerformanceTest extends Activity return null; } - public final int getAndroidSDKVersion() + public static final int getAndroidSDKVersion() { return android.os.Build.VERSION.SDK_INT; } diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index 4b70bc30e4..ab7a9dda7e 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -1540,9 +1540,9 @@ static const unsigned char temp_binary_data_8[] = " #endif\r\n" "}\r\n" "\r\n" -"bool FILTERCLASSNAME::isMidiEffect () const\r\n" +"bool FILTERCLASSNAME::isMidiEffect() const\r\n" "{\r\n" -" #ifdef JucePlugin_IsMidiEffect\r\n" +" #if JucePlugin_IsMidiEffect\r\n" " return true;\r\n" " #else\r\n" " return false;\r\n" @@ -7028,7 +7028,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw case 0xafccbd3f: numBytes = 3141; return jucer_AudioComponentTemplate_cpp; case 0x27c5a93a: numBytes = 1310; return jucer_AudioPluginEditorTemplate_cpp; case 0x4d0721bf: numBytes = 938; return jucer_AudioPluginEditorTemplate_h; - case 0x51b49ac5: numBytes = 5615; return jucer_AudioPluginFilterTemplate_cpp; + case 0x51b49ac5: numBytes = 5611; return jucer_AudioPluginFilterTemplate_cpp; case 0x488afa0a: numBytes = 2245; return jucer_AudioPluginFilterTemplate_h; case 0xabad7041: numBytes = 2151; return jucer_ComponentTemplate_cpp; case 0xfc72fe86: numBytes = 2064; return jucer_ComponentTemplate_h; diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index 8c93be578b..1ad41adb5c 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -33,7 +33,7 @@ namespace BinaryData const int jucer_AudioPluginEditorTemplate_hSize = 938; extern const char* jucer_AudioPluginFilterTemplate_cpp; - const int jucer_AudioPluginFilterTemplate_cppSize = 5615; + const int jucer_AudioPluginFilterTemplate_cppSize = 5611; extern const char* jucer_AudioPluginFilterTemplate_h; const int jucer_AudioPluginFilterTemplate_hSize = 2245;