Skip to content

Commit

Permalink
#122 update uploadservice-okhttp module, move out ok http implementat…
Browse files Browse the repository at this point in the history
…ion from core library and set hurl stack as default, to not forcefully depend on okhttp
  • Loading branch information
gotev committed Jan 11, 2017
1 parent 4302917 commit b82549c
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 293 deletions.
1 change: 1 addition & 0 deletions examples/app/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/app/app/build.gradle
Expand Up @@ -38,5 +38,6 @@ dependencies {
//compile 'net.gotev:uploadservice-ftp:3.0.3'
//comment the previous lines and uncomment the next ones for development (it uses the local libs)
compile project(':uploadservice')
compile project(':uploadservice-okhttp')
compile project(':uploadservice-ftp')
}
Expand Up @@ -4,7 +4,7 @@

import net.gotev.uploadservice.Logger;
import net.gotev.uploadservice.UploadService;
import net.gotev.uploadservice.http.impl.OkHttpStack;
import net.gotev.uploadservice.okhttp.OkHttpStack;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
Expand Down
2 changes: 2 additions & 0 deletions examples/app/settings.gradle
@@ -1,5 +1,7 @@
include ':app'
include ':uploadservice'
include ':uploadservice-okhttp'
include ':uploadservice-ftp'
project(':uploadservice').projectDir = file('../../uploadservice')
project(':uploadservice-okhttp').projectDir = file('../../uploadservice-okhttp')
project(':uploadservice-ftp').projectDir = file('../../uploadservice-ftp')
1 change: 1 addition & 0 deletions settings.gradle
@@ -1,2 +1,3 @@
include ':uploadservice'
include ':uploadservice-okhttp'
include ':uploadservice-ftp'
15 changes: 8 additions & 7 deletions uploadservice-okhttp/build.gradle
Expand Up @@ -8,16 +8,18 @@ def projectName = "android-upload-service-okhttp"
def projectDesc = "OkHttp stack implementation for Android Upload Service."
def projectGroup = "net.gotev"
group = projectGroup
version = "3.0.3"
version = "3.1"

def sdkVersion = 25;

android {
compileSdkVersion 25
compileSdkVersion sdkVersion
buildToolsVersion "24.0.3"

defaultConfig {
minSdkVersion 10
targetSdkVersion 25
versionCode 4
targetSdkVersion sdkVersion
versionCode 5
versionName version
}
buildTypes {
Expand All @@ -32,9 +34,8 @@ android {
}

dependencies {
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.4.1'
//compile 'net.gotev:uploadservice:3.0.2'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
//compile 'net.gotev:uploadservice:3.1'
//comment the previous line and uncomment the next line for development (it uses the local lib)
compile project(':uploadservice')
}
Expand Down
@@ -1,4 +1,4 @@
package net.gotev.uploadservice.http.impl;
package net.gotev.uploadservice.okhttp;

import net.gotev.uploadservice.http.BodyWriter;

Expand Down
Expand Up @@ -2,165 +2,129 @@

import net.gotev.uploadservice.Logger;
import net.gotev.uploadservice.NameValue;
import net.gotev.uploadservice.UploadService;
import net.gotev.uploadservice.ServerResponse;
import net.gotev.uploadservice.http.HttpConnection;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.internal.huc.OkHttpURLConnection;
import okhttp3.internal.huc.OkHttpsURLConnection;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.http.HttpMethod;
import okio.BufferedSink;

/**
* {@link HttpConnection} implementation using {@link OkHttpClient}.
* {@link HttpConnection} implementation using OkHttpClient.
* @author Aleksandar Gotev
*/
public class OkHttpStackConnection implements HttpConnection {

private static final String LOG_TAG = OkHttpStackConnection.class.getSimpleName();

private HttpURLConnection mConnection;
private OkHttpClient mClient;
private Request.Builder mRequestBuilder;
private String mMethod;
private long mBodyLength;
private String mContentType;
private Response mResponse;

public OkHttpStackConnection(OkHttpClient client, String method, String url) throws IOException {
Logger.debug(getClass().getSimpleName(), "creating new connection");

URL urlObj = new URL(url);
mResponse = null;
mClient = client;
mMethod = method;

if (urlObj.getProtocol().equals("https")) {
mConnection = new OkHttpsURLConnection(urlObj, client);
} else {
mConnection = new OkHttpURLConnection(urlObj, client);
}

mConnection.setDoInput(true);
mConnection.setDoOutput(true);
mConnection.setRequestMethod(method);
mRequestBuilder = new Request.Builder().url(new URL(url));
}

@Override
public void setHeaders(List<NameValue> requestHeaders, boolean isFixedLengthStreamingMode,
long totalBodyBytes) throws IOException {
if (isFixedLengthStreamingMode) {
if (android.os.Build.VERSION.SDK_INT >= 19) {
mConnection.setFixedLengthStreamingMode(totalBodyBytes);

} else {
if (totalBodyBytes > Integer.MAX_VALUE)
throw new RuntimeException("You need Android API version 19 or newer to "
+ "upload more than 2GB in a single request using "
+ "fixed size content length. Try switching to "
+ "chunked mode instead, but make sure your server side supports it!");

mConnection.setFixedLengthStreamingMode((int) totalBodyBytes);
}
} else {
mConnection.setChunkedStreamingMode(0);
}

public void setHeaders(List<NameValue> requestHeaders) throws IOException {
for (final NameValue param : requestHeaders) {
mConnection.setRequestProperty(param.getName(), param.getValue());
}
}

@Override
public void writeBody(byte[] bytes) throws IOException {
mConnection.getOutputStream().write(bytes, 0, bytes.length);
}

@Override
public void writeBody(byte[] bytes, int lengthToWriteFromStart) throws IOException {
mConnection.getOutputStream().write(bytes, 0, lengthToWriteFromStart);
}
if ("Content-Type".equalsIgnoreCase(param.getName()))
mContentType = param.getValue();

@Override
public int getServerResponseCode() throws IOException {
return mConnection.getResponseCode();
mRequestBuilder.header(param.getName(), param.getValue());
}
}

@Override
public byte[] getServerResponseBody() throws IOException {
InputStream stream = null;

try {
if (mConnection.getResponseCode() / 100 == 2) {
stream = mConnection.getInputStream();
} else {
stream = mConnection.getErrorStream();
}
public void setTotalBodyBytes(long totalBodyBytes, boolean isFixedLengthStreamingMode) {
if (isFixedLengthStreamingMode) {
if (android.os.Build.VERSION.SDK_INT < 19 && totalBodyBytes > Integer.MAX_VALUE)
throw new RuntimeException("You need Android API version 19 or newer to "
+ "upload more than 2GB in a single request using "
+ "fixed size content length. Try switching to "
+ "chunked mode instead, but make sure your server side supports it!");

return getResponseBodyAsByteArray(stream);
mBodyLength = totalBodyBytes;

} finally {
if (stream != null) {
try {
stream.close();
} catch (Exception exc) {
Logger.error(LOG_TAG, "Error while closing server response stream", exc);
}
}
} else {
// http://stackoverflow.com/questions/33921894/how-do-i-enable-disable-chunked-transfer-encoding-for-a-multi-part-post-that-inc#comment55679982_33921894
mBodyLength = -1;
}
}

private byte[] getResponseBodyAsByteArray(final InputStream inputStream) {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

byte[] buffer = new byte[UploadService.BUFFER_SIZE];
int bytesRead;
private LinkedHashMap<String, String> getServerResponseHeaders(Headers headers) throws IOException {
LinkedHashMap<String, String> out = new LinkedHashMap<>(headers.size());

try {
while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) > 0) {
byteStream.write(buffer, 0, bytesRead);
}
} catch (Exception ignored) {}
for (String headerName : headers.names()) {
out.put(headerName, headers.get(headerName));
}

return byteStream.toByteArray();
return out;
}

@Override
public LinkedHashMap<String, String> getServerResponseHeaders() throws IOException {
Map<String, List<String>> headers = mConnection.getHeaderFields();
if (headers == null)
return null;
public ServerResponse getResponse(final RequestBodyDelegate delegate) throws IOException {
if (HttpMethod.permitsRequestBody(mMethod) || HttpMethod.requiresRequestBody(mMethod)) {
RequestBody body = new RequestBody() {
@Override
public long contentLength() throws IOException {
return mBodyLength;
}

LinkedHashMap<String, String> out = new LinkedHashMap<>(headers.size());
@Override
public MediaType contentType() {
if (mContentType == null)
return null;
return MediaType.parse(mContentType);
}

for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
if (entry.getKey() != null) {
StringBuilder headerValue = new StringBuilder();
for (String value : entry.getValue()) {
headerValue.append(value);
@Override
public void writeTo(BufferedSink sink) throws IOException {
final OkHttpBodyWriter bodyWriter = new OkHttpBodyWriter(sink);
delegate.onBodyReady(bodyWriter);
bodyWriter.flush();
}
out.put(entry.getKey(), headerValue.toString());
}
};

mRequestBuilder.method(mMethod, body);
} else {
mRequestBuilder.method(mMethod, null);
}

return out;
mResponse = mClient.newCall(mRequestBuilder.build()).execute();

return new ServerResponse(mResponse.code(),
mResponse.body().bytes(),
getServerResponseHeaders(mResponse.headers()));
}

@Override
public void close() {
Logger.debug(getClass().getSimpleName(), "closing connection");

if (mConnection != null) {
try {
mConnection.getInputStream().close();
} catch (Exception ignored) { }

try {
mConnection.getOutputStream().flush();
mConnection.getOutputStream().close();
} catch (Exception ignored) { }

if (mResponse != null) {
try {
mConnection.disconnect();
} catch (Exception exc) {
mResponse.close();
} catch (Throwable exc) {
Logger.error(LOG_TAG, "Error while closing connection", exc);
}
}
Expand Down
2 changes: 0 additions & 2 deletions uploadservice/build.gradle
Expand Up @@ -34,12 +34,10 @@ android {
}

def supportLibraryVersion = "25.1.0"
def okHttpVersion = "3.5.0"

dependencies {
compile "com.android.support:appcompat-v7:${supportLibraryVersion}"
compile "com.android.support:support-v4:${supportLibraryVersion}"
compile "com.squareup.okhttp3:okhttp:${okHttpVersion}"
}

// add the following information to the file: local.properties situated in the parent directory of
Expand Down
Expand Up @@ -7,7 +7,7 @@
import android.os.PowerManager;

import net.gotev.uploadservice.http.HttpStack;
import net.gotev.uploadservice.http.impl.OkHttpStack;
import net.gotev.uploadservice.http.impl.HurlStack;

import java.util.ArrayList;
import java.util.Iterator;
Expand Down Expand Up @@ -63,9 +63,9 @@ public final class UploadService extends Service {

/**
* Sets the HTTP Stack to use to perform HTTP based upload requests.
* By default {@link OkHttpStack} implementation is used.
* By default {@link HurlStack} implementation is used.
*/
public static HttpStack HTTP_STACK = new OkHttpStack();
public static HttpStack HTTP_STACK = new HurlStack();

/**
* Buffer size in bytes used for data transfer by the upload tasks.
Expand Down

This file was deleted.

0 comments on commit b82549c

Please sign in to comment.