diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 4af307c275..20dccb6833 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -519,7 +519,6 @@ #include #include #include -#include #include #include #include @@ -8966,6 +8965,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_Socket.cpp ***/ #if JUCE_WINDOWS #include + #include #if JUCE_MSVC #pragma warning (push) @@ -13433,8 +13433,8 @@ struct StringEncodingConverter CharPointerType_Src text (source.getCharPointer()); const size_t extraBytesNeeded = CharPointerType_Dest::getBytesRequiredFor (text); - const size_t endOffset = text.sizeInBytes(); - + const size_t endOffset = (text.sizeInBytes() + 3) & ~3; // the new string must be word-aligned or many win32 + // functions will fail to read it correctly! source.preallocateBytes (endOffset + extraBytesNeeded); text = source.getCharPointer(); @@ -283438,6 +283438,7 @@ BEGIN_JUCE_NAMESPACE JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ JAVACLASS (fileClass, "java/io/File") \ JAVACLASS (systemClass, "java/lang/System") \ + JAVACLASS (stringBufferClass, "java/lang/StringBuffer") \ JAVACLASS (contextClass, "android/content/Context") \ JAVACLASS (canvasClass, "android/graphics/Canvas") \ JAVACLASS (paintClass, "android/graphics/Paint") \ @@ -283477,6 +283478,9 @@ BEGIN_JUCE_NAMESPACE METHOD (activityClass, excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ STATICMETHOD (activityClass, createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \ +\ + METHOD (stringBufferClass, stringBufferConstructor, "", "()V") \ + METHOD (stringBufferClass, stringBufferToString, "toString", "()Ljava/lang/String;") \ \ METHOD (httpStreamClass, httpStreamRelease, "release", "()V") \ METHOD (httpStreamClass, httpStreamRead, "read", "([BI)I") \ @@ -285395,46 +285399,94 @@ class WebInputStream : public InputStream { public: - WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_, + WebInputStream (const String& address, bool isPost, const MemoryBlock& postData, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers_, int timeOutMs_, StringPairArray* responseHeaders) + const String& headers, int timeOutMs, StringPairArray* responseHeaders) { - // TODO - openedOk = false; + jbyteArray postDataArray = 0; + + if (postData.getSize() > 0) + { + postDataArray = getEnv()->NewByteArray (postData.getSize()); + getEnv()->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData()); + } + + LocalRef responseHeaderBuffer (getEnv()->NewObject (android.stringBufferClass, android.stringBufferConstructor)); + + stream = GlobalRef (android.activity.callObjectMethod (android.createHTTPStream, + javaString (address).get(), + (jboolean) isPost, + postDataArray, + javaString (headers).get(), + (jint) timeOutMs, + responseHeaderBuffer.get())); + + getEnv()->DeleteLocalRef (postDataArray); + + if (stream != 0) + { + StringArray headerLines; + + { + LocalRef headersString ((jstring) getEnv()->CallObjectMethod (responseHeaderBuffer.get(), + android.stringBufferToString)); + headerLines.addLines (juceString (headersString)); + } + + for (int i = 0; i < headerLines.size(); ++i) + { + const String& header = headerLines[i]; + const String key (header.upToFirstOccurrenceOf (": ", false, false)); + const String value (header.fromFirstOccurrenceOf (": ", false, false)); + const String previousValue ((*responseHeaders) [key]); + + responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + } + + } } ~WebInputStream() { + stream.callVoidMethod (android.httpStreamRelease); } bool isExhausted() { - return true; // TODO + return stream != 0 && stream.callBooleanMethod (android.isExhausted); } int64 getPosition() { - return 0; // TODO + return stream != 0 ? stream.callLongMethod (android.getPosition) : 0; } int64 getTotalLength() { - return -1; // TODO + return stream != 0 ? stream.callLongMethod (android.getTotalLength) : 0; } - int read (void* buffer, int bytesToRead) + bool setPosition (int64 wantedPos) { - // TODO - return 0; + return stream != 0 && stream.callBooleanMethod (android.setPosition, (jlong) wantedPos); } - bool setPosition (int64 wantedPos) + int read (void* buffer, int bytesToRead) { - // TODO - return false; + JNIEnv* env = getEnv(); + + jbyteArray javaArray = env->NewByteArray (bytesToRead); + + int numBytes = stream.callIntMethod (android.httpStreamRead, javaArray, (jint) bytesToRead); + + if (numBytes > 0) + env->GetByteArrayRegion (javaArray, 0, numBytes, (jbyte*) buffer); + + env->DeleteLocalRef (javaArray); + return numBytes; } - bool openedOk; + GlobalRef stream; private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream); @@ -285448,7 +285500,7 @@ InputStream* URL::createNativeStream (const String& address, bool isPost, const progressCallback, progressCallbackContext, headers, timeOutMs, responseHeaders)); - return wi->openedOk ? wi.release() : 0; + return wi->stream != 0 ? wi.release() : 0; } #endif diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 7b98cf1067..891753d429 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 42 +#define JUCE_BUILDNUMBER 43 /** Current Juce version number. diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index ae07e5e327..0954cac304 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 42 +#define JUCE_BUILDNUMBER 43 /** Current Juce version number. diff --git a/src/io/network/juce_Socket.cpp b/src/io/network/juce_Socket.cpp index 15fb22f32f..3bd0506a78 100644 --- a/src/io/network/juce_Socket.cpp +++ b/src/io/network/juce_Socket.cpp @@ -27,6 +27,7 @@ #if JUCE_WINDOWS #include + #include #if JUCE_MSVC #pragma warning (push) diff --git a/src/native/android/juce_android_NativeCode.cpp b/src/native/android/juce_android_NativeCode.cpp index 6e1c98b29d..b875f59894 100644 --- a/src/native/android/juce_android_NativeCode.cpp +++ b/src/native/android/juce_android_NativeCode.cpp @@ -104,6 +104,7 @@ BEGIN_JUCE_NAMESPACE JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ JAVACLASS (fileClass, "java/io/File") \ JAVACLASS (systemClass, "java/lang/System") \ + JAVACLASS (stringBufferClass, "java/lang/StringBuffer") \ JAVACLASS (contextClass, "android/content/Context") \ JAVACLASS (canvasClass, "android/graphics/Canvas") \ JAVACLASS (paintClass, "android/graphics/Paint") \ @@ -146,6 +147,9 @@ BEGIN_JUCE_NAMESPACE METHOD (activityClass, excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ STATICMETHOD (activityClass, createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \ +\ + METHOD (stringBufferClass, stringBufferConstructor, "", "()V") \ + METHOD (stringBufferClass, stringBufferToString, "toString", "()Ljava/lang/String;") \ \ METHOD (httpStreamClass, httpStreamRelease, "release", "()V") \ METHOD (httpStreamClass, httpStreamRead, "read", "([BI)I") \ diff --git a/src/native/android/juce_android_Network.cpp b/src/native/android/juce_android_Network.cpp index 900a8a8ce9..9ab8a07314 100644 --- a/src/native/android/juce_android_Network.cpp +++ b/src/native/android/juce_android_Network.cpp @@ -51,48 +51,96 @@ class WebInputStream : public InputStream { public: //============================================================================== - WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_, + WebInputStream (const String& address, bool isPost, const MemoryBlock& postData, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers_, int timeOutMs_, StringPairArray* responseHeaders) + const String& headers, int timeOutMs, StringPairArray* responseHeaders) { - // TODO - openedOk = false; + jbyteArray postDataArray = 0; + + if (postData.getSize() > 0) + { + postDataArray = getEnv()->NewByteArray (postData.getSize()); + getEnv()->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData()); + } + + LocalRef responseHeaderBuffer (getEnv()->NewObject (android.stringBufferClass, android.stringBufferConstructor)); + + stream = GlobalRef (android.activity.callObjectMethod (android.createHTTPStream, + javaString (address).get(), + (jboolean) isPost, + postDataArray, + javaString (headers).get(), + (jint) timeOutMs, + responseHeaderBuffer.get())); + + getEnv()->DeleteLocalRef (postDataArray); + + if (stream != 0) + { + StringArray headerLines; + + { + LocalRef headersString ((jstring) getEnv()->CallObjectMethod (responseHeaderBuffer.get(), + android.stringBufferToString)); + headerLines.addLines (juceString (headersString)); + } + + for (int i = 0; i < headerLines.size(); ++i) + { + const String& header = headerLines[i]; + const String key (header.upToFirstOccurrenceOf (": ", false, false)); + const String value (header.fromFirstOccurrenceOf (": ", false, false)); + const String previousValue ((*responseHeaders) [key]); + + responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + } + + } } ~WebInputStream() { + stream.callVoidMethod (android.httpStreamRelease); } //============================================================================== bool isExhausted() { - return true; // TODO + return stream != 0 && stream.callBooleanMethod (android.isExhausted); } int64 getPosition() { - return 0; // TODO + return stream != 0 ? stream.callLongMethod (android.getPosition) : 0; } int64 getTotalLength() { - return -1; // TODO + return stream != 0 ? stream.callLongMethod (android.getTotalLength) : 0; } - int read (void* buffer, int bytesToRead) + bool setPosition (int64 wantedPos) { - // TODO - return 0; + return stream != 0 && stream.callBooleanMethod (android.setPosition, (jlong) wantedPos); } - bool setPosition (int64 wantedPos) + int read (void* buffer, int bytesToRead) { - // TODO - return false; + JNIEnv* env = getEnv(); + + jbyteArray javaArray = env->NewByteArray (bytesToRead); + + int numBytes = stream.callIntMethod (android.httpStreamRead, javaArray, (jint) bytesToRead); + + if (numBytes > 0) + env->GetByteArrayRegion (javaArray, 0, numBytes, (jbyte*) buffer); + + env->DeleteLocalRef (javaArray); + return numBytes; } //============================================================================== - bool openedOk; + GlobalRef stream; private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream); @@ -106,7 +154,7 @@ InputStream* URL::createNativeStream (const String& address, bool isPost, const progressCallback, progressCallbackContext, headers, timeOutMs, responseHeaders)); - return wi->openedOk ? wi.release() : 0; + return wi->stream != 0 ? wi.release() : 0; } #endif diff --git a/src/native/windows/juce_win32_NativeIncludes.h b/src/native/windows/juce_win32_NativeIncludes.h index b86489f64d..697b2ad9f7 100644 --- a/src/native/windows/juce_win32_NativeIncludes.h +++ b/src/native/windows/juce_win32_NativeIncludes.h @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 21fb18e754..92cefb61f9 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -2067,8 +2067,8 @@ struct StringEncodingConverter CharPointerType_Src text (source.getCharPointer()); const size_t extraBytesNeeded = CharPointerType_Dest::getBytesRequiredFor (text); - const size_t endOffset = text.sizeInBytes(); - + const size_t endOffset = (text.sizeInBytes() + 3) & ~3; // the new string must be word-aligned or many win32 + // functions will fail to read it correctly! source.preallocateBytes (endOffset + extraBytesNeeded); text = source.getCharPointer();