Squashed commit of the following:

commit 8ab8f77557a98adad56006e6d372d8f348191742
Author: daniel oeh <daniel.oeh@gmail.com>
Date:   Wed Nov 12 16:05:32 2014 +0100

    Use OkHttp instead of HttpClient in HttpDownloader

    - Adds support for SNI -> fixes #354
    - fixes #548

commit 38278bc72abcdc190d44f26593f6efdd2b390877
Author: daniel oeh <daniel.oeh@gmail.com>
Date:   Wed Nov 12 15:04:32 2014 +0100

    Use OkHttp instead of HttpClient in GpodnetService
This commit is contained in:
daniel oeh 2014-11-12 18:46:36 +01:00
parent 976df32cae
commit 7127277626
5 changed files with 196 additions and 260 deletions

View File

@ -18,9 +18,9 @@ dependencies {
compile 'com.jayway.android.robotium:robotium-solo:5.2.1'
compile 'org.jsoup:jsoup:1.7.3'
compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.squareup.okhttp:okhttp:2.0.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
compile 'com.squareup.okio:okio:1.0.0'
compile 'com.squareup.okhttp:okhttp:2.1.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.1.0'
compile 'com.squareup.okio:okio:1.0.1'
compile project(':core')
}
@ -89,9 +89,4 @@ android {
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}

View File

@ -22,6 +22,12 @@ android {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
@ -39,7 +45,7 @@ dependencies {
compile 'com.jayway.android.robotium:robotium-solo:5.2.1'
compile 'org.jsoup:jsoup:1.7.3'
compile 'com.squareup.picasso:picasso:2.4.0'
compile 'com.squareup.okhttp:okhttp:2.0.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
compile 'com.squareup.okio:okio:1.0.0'
}
compile 'com.squareup.okhttp:okhttp:2.1.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.1.0'
compile 'com.squareup.okio:okio:1.0.1'
}

View File

@ -1,20 +1,16 @@
package de.danoeh.antennapod.core.gpoddernet;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import org.apache.commons.lang3.Validate;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -22,14 +18,18 @@ import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetPodcast;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetSubscriptionChange;
@ -48,7 +48,11 @@ public class GpodnetService {
public static final String DEFAULT_BASE_HOST = "gpodder.net";
private final String BASE_HOST;
private final HttpClient httpClient;
private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8");
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private final OkHttpClient httpClient;
public GpodnetService() {
httpClient = AntennapodHttpClient.getHttpClient();
@ -60,16 +64,16 @@ public class GpodnetService {
*/
public List<GpodnetTag> getTopTags(int count)
throws GpodnetServiceException {
URI uri;
URL url;
try {
uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/tags/%d.json", count), null);
} catch (URISyntaxException e1) {
e1.printStackTrace();
throw new IllegalStateException(e1);
url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/tags/%d.json", count), null).toURL();
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
HttpGet request = new HttpGet(uri);
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
try {
JSONArray jsonTagList = new JSONArray(response);
@ -98,21 +102,17 @@ public class GpodnetService {
Validate.notNull(tag);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/tag/%s/%d.json", tag.getName(), count), null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/tag/%s/%d.json", tag.getName(), count), null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJSONArray(jsonArray);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
}
@ -127,21 +127,17 @@ public class GpodnetService {
Validate.isTrue(count >= 1 && count <= 100, "Count must be in range 1..100");
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/toplist/%d.json", count), null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/toplist/%d.json", count), null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJSONArray(jsonArray);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
@ -161,17 +157,14 @@ public class GpodnetService {
Validate.isTrue(count >= 1 && count <= 100, "Count must be in range 1..100");
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/suggestions/%d.json", count), null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/suggestions/%d.json", count), null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJSONArray(jsonArray);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
@ -191,22 +184,20 @@ public class GpodnetService {
.format("q=%s&scale_logo=%d", query, scaledLogoSize) : String
.format("q=%s", query);
try {
URI uri = new URI(BASE_SCHEME, null, BASE_HOST, -1, "/search.json",
parameters, null);
System.out.println(uri.toASCIIString());
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, "/search.json",
parameters, null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray jsonArray = new JSONArray(response);
return readPodcastListFromJSONArray(jsonArray);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
@ -225,18 +216,13 @@ public class GpodnetService {
Validate.notNull(username);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/devices/%s.json", username), null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/devices/%s.json", username), null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONArray devicesArray = new JSONArray(response);
List<GpodnetDevice> result = readDeviceListFromJSONArray(devicesArray);
return result;
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (JSONException e) {
return readDeviceListFromJSONArray(devicesArray);
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
@ -260,9 +246,9 @@ public class GpodnetService {
Validate.notNull(deviceId);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/devices/%s/%s.json", username, deviceId), null);
HttpPost request = new HttpPost(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/devices/%s/%s.json", username, deviceId), null).toURL();
String content;
if (caption != null || type != null) {
JSONObject jsonContent = new JSONObject();
if (caption != null) {
@ -271,19 +257,14 @@ public class GpodnetService {
if (type != null) {
jsonContent.put("type", type.toString());
}
StringEntity strEntity = new StringEntity(
jsonContent.toString(), "UTF-8");
strEntity.setContentType("application/json");
request.setEntity(strEntity);
content = jsonContent.toString();
} else {
content = "";
}
RequestBody body = RequestBody.create(JSON, content);
Request.Builder request = new Request.Builder().post(body).url(url);
executeRequest(request);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalArgumentException(e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
@ -307,14 +288,13 @@ public class GpodnetService {
Validate.notNull(deviceId);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s/%s.opml", username, deviceId), null);
HttpGet request = new HttpGet(uri);
String response = executeRequest(request);
return response;
} catch (URISyntaxException e) {
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s/%s.opml", username, deviceId), null).toURL();
Request.Builder request = new Request.Builder().url(url);
return executeRequest(request);
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new IllegalArgumentException(e);
throw new GpodnetServiceException(e);
}
}
@ -334,14 +314,14 @@ public class GpodnetService {
Validate.notNull(username);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s.opml", username), null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s.opml", username), null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
return response;
} catch (URISyntaxException e) {
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new IllegalArgumentException(e);
throw new GpodnetServiceException(e);
}
}
@ -365,24 +345,19 @@ public class GpodnetService {
"Username, device ID and subscriptions must not be null");
}
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s/%s.txt", username, deviceId), null);
HttpPut request = new HttpPut(uri);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/subscriptions/%s/%s.txt", username, deviceId), null).toURL();
StringBuilder builder = new StringBuilder();
for (String s : subscriptions) {
builder.append(s);
builder.append("\n");
}
StringEntity entity = new StringEntity(builder.toString(), "UTF-8");
request.setEntity(entity);
RequestBody body = RequestBody.create(TEXT, builder.toString());
Request.Builder request = new Request.Builder().put(body).url(url);
executeRequest(request);
} catch (URISyntaxException e) {
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new IllegalStateException(e);
throw new GpodnetServiceException(e);
}
}
@ -398,9 +373,9 @@ public class GpodnetService {
* @param removed Collection of feed URLs of removed feeds. This Collection MUST NOT contain any duplicates
* @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse}
* for details.
* @throws java.lang.IllegalArgumentException if username, deviceId, added or removed is null.
* @throws java.lang.IllegalArgumentException if username, deviceId, added or removed is null.
* @throws de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there
* is an authentication error.
* is an authentication error.
*/
public GpodnetUploadChangesResponse uploadChanges(String username, String deviceId, Collection<String> added,
Collection<String> removed) throws GpodnetServiceException {
@ -410,28 +385,21 @@ public class GpodnetService {
Validate.notNull(removed);
try {
URI uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/subscriptions/%s/%s.json", username, deviceId), null);
URL url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/subscriptions/%s/%s.json", username, deviceId), null).toURL();
final JSONObject requestObject = new JSONObject();
requestObject.put("add", new JSONArray(added));
requestObject.put("remove", new JSONArray(removed));
HttpPost request = new HttpPost(uri);
StringEntity entity = new StringEntity(requestObject.toString(), "UTF-8");
request.setEntity(entity);
RequestBody body = RequestBody.create(JSON, requestObject.toString());
Request.Builder request = new Request.Builder().post(body).url(url);
final String response = executeRequest(request);
return GpodnetUploadChangesResponse.fromJSONObject(response);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new IllegalStateException(e);
}
}
@ -459,9 +427,9 @@ public class GpodnetService {
String path = String.format("/api/2/subscriptions/%s/%s.json",
username, deviceId);
try {
URI uri = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params,
null);
HttpGet request = new HttpGet(uri);
URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params,
null).toURL();
Request.Builder request = new Request.Builder().url(url);
String response = executeRequest(request);
JSONObject changes = new JSONObject(response);
@ -469,7 +437,7 @@ public class GpodnetService {
} catch (URISyntaxException e) {
e.printStackTrace();
throw new IllegalStateException(e);
} catch (JSONException e) {
} catch (JSONException | MalformedURLException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
@ -487,15 +455,15 @@ public class GpodnetService {
Validate.notNull(username);
Validate.notNull(password);
URI uri;
URL url;
try {
uri = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/auth/%s/login.json", username), null);
} catch (URISyntaxException e) {
url = new URI(BASE_SCHEME, BASE_HOST, String.format(
"/api/2/auth/%s/login.json", username), null).toURL();
} catch (MalformedURLException | URISyntaxException e) {
e.printStackTrace();
throw new GpodnetServiceException();
throw new GpodnetServiceException(e);
}
HttpPost request = new HttpPost(uri);
Request.Builder request = new Request.Builder().url(url).post(null);
executeRequestWithAuthentication(request, username, password);
}
@ -512,26 +480,27 @@ public class GpodnetService {
}.start();
}
private String executeRequest(HttpRequestBase request)
private String executeRequest(Request.Builder requestB)
throws GpodnetServiceException {
Validate.notNull(request);
Validate.notNull(requestB);
Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build();
String responseString = null;
HttpResponse response = null;
Response response = null;
ResponseBody body = null;
try {
response = httpClient.execute(request);
response = httpClient.newCall(request).execute();
checkStatusCode(response);
responseString = getStringFromEntity(response.getEntity());
} catch (ClientProtocolException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
body = response.body();
responseString = getStringFromResponseBody(body);
} catch (IOException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} finally {
if (response != null) {
if (response != null && body != null) {
try {
response.getEntity().consumeContent();
body.close();
} catch (IOException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
@ -542,35 +511,33 @@ public class GpodnetService {
return responseString;
}
private String executeRequestWithAuthentication(HttpRequestBase request,
private String executeRequestWithAuthentication(Request.Builder requestB,
String username, String password) throws GpodnetServiceException {
if (request == null || username == null || password == null) {
if (requestB == null || username == null || password == null) {
throw new IllegalArgumentException(
"request and credentials must not be null");
}
Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build();
String result = null;
HttpResponse response = null;
ResponseBody body = null;
try {
Header auth = new BasicScheme().authenticate(
new UsernamePasswordCredentials(username, password),
request);
request.addHeader(auth);
response = httpClient.execute(request);
String credential = Credentials.basic(username, password);
Request authRequest = request.newBuilder().header("Authorization", credential).build();
Response response = httpClient.newCall(authRequest).execute();
checkStatusCode(response);
result = getStringFromEntity(response.getEntity());
body = response.body();
result = getStringFromResponseBody(body);
} catch (ClientProtocolException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (IOException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} catch (AuthenticationException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
} finally {
if (response != null) {
if (body != null) {
try {
response.getEntity().consumeContent();
body.close();
} catch (IOException e) {
e.printStackTrace();
throw new GpodnetServiceException(e);
@ -580,12 +547,12 @@ public class GpodnetService {
return result;
}
private String getStringFromEntity(HttpEntity entity)
private String getStringFromResponseBody(ResponseBody body)
throws GpodnetServiceException {
Validate.notNull(entity);
Validate.notNull(body);
ByteArrayOutputStream outputStream;
int contentLength = (int) entity.getContentLength();
int contentLength = (int) body.contentLength();
if (contentLength > 0) {
outputStream = new ByteArrayOutputStream(contentLength);
} else {
@ -593,7 +560,7 @@ public class GpodnetService {
}
try {
byte[] buffer = new byte[8 * 1024];
InputStream in = entity.getContent();
InputStream in = body.byteStream();
int count;
while ((count = in.read(buffer)) > 0) {
outputStream.write(buffer, 0, count);
@ -602,14 +569,13 @@ public class GpodnetService {
e.printStackTrace();
throw new GpodnetServiceException(e);
}
// System.out.println(outputStream.toString());
return outputStream.toString();
}
private void checkStatusCode(HttpResponse response)
private void checkStatusCode(Response response)
throws GpodnetServiceException {
Validate.notNull(response);
int responseCode = response.getStatusLine().getStatusCode();
int responseCode = response.code();
if (responseCode != HttpStatus.SC_OK) {
if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
throw new GpodnetServiceAuthenticationException("Wrong username or password");

View File

@ -2,26 +2,13 @@ package de.danoeh.antennapod.core.service.download;
import android.util.Log;
import org.apache.http.client.HttpClient;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerPNames;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import com.squareup.okhttp.OkHttpClient;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.ClientConfig;
/**
* Provides access to a HttpClient singleton.
@ -29,37 +16,41 @@ import de.danoeh.antennapod.core.ClientConfig;
public class AntennapodHttpClient {
private static final String TAG = "AntennapodHttpClient";
public static final long EXPIRED_CONN_TIMEOUT_SEC = 30;
public static final int MAX_REDIRECTS = 5;
public static final int CONNECTION_TIMEOUT = 30000;
public static final int SOCKET_TIMEOUT = 30000;
public static final int READ_TIMEOUT = 30000;
public static final int MAX_CONNECTIONS = 8;
private static volatile HttpClient httpClient = null;
private static volatile OkHttpClient httpClient = null;
/**
* Returns the HttpClient singleton.
*/
public static synchronized HttpClient getHttpClient() {
public static synchronized OkHttpClient getHttpClient() {
if (httpClient == null) {
if (BuildConfig.DEBUG) Log.d(TAG, "Creating new instance of HTTP client");
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.USER_AGENT, ClientConfig.USER_AGENT);
params.setIntParameter("http.protocol.max-redirects", MAX_REDIRECTS);
params.setBooleanParameter("http.protocol.reject-relative-redirect",
false);
HttpConnectionParams.setSoTimeout(params, SOCKET_TIMEOUT);
HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
HttpClientParams.setRedirecting(params, true);
System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS));
httpClient = new DefaultHttpClient(createClientConnectionManager(), params);
// Workaround for broken URLs in redirection
((AbstractHttpClient) httpClient)
.setRedirectHandler(new APRedirectHandler());
OkHttpClient client = new OkHttpClient();
// set cookie handler
CookieManager cm = new CookieManager();
cm.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
client.setCookieHandler(cm);
// set timeouts
client.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);
client.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
client.setWriteTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
// configure redirects
client.setFollowRedirects(true);
client.setFollowSslRedirects(true);
httpClient = client;
}
return httpClient;
}
@ -70,29 +61,7 @@ public class AntennapodHttpClient {
*/
public static synchronized void cleanup() {
if (httpClient != null) {
httpClient.getConnectionManager().closeExpiredConnections();
httpClient.getConnectionManager().closeIdleConnections(EXPIRED_CONN_TIMEOUT_SEC, TimeUnit.SECONDS);
// does nothing at the moment
}
}
private static ClientConnectionManager createClientConnectionManager() {
HttpParams params = new BasicHttpParams();
params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, MAX_CONNECTIONS);
return new ThreadSafeClientConnManager(params, prepareSchemeRegistry());
}
private static SchemeRegistry prepareSchemeRegistry() {
SchemeRegistry sr = new SchemeRegistry();
Scheme http = new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80);
sr.register(http);
Scheme https = new Scheme("https",
SSLSocketFactory.getSocketFactory(), 443);
sr.register(https);
return sr;
}
}

View File

@ -1,19 +1,16 @@
package de.danoeh.antennapod.core.service.download;
import android.net.http.AndroidHttpClient;
import android.util.Log;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.message.BasicHeader;
import java.io.BufferedInputStream;
import java.io.File;
@ -22,6 +19,7 @@ import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.UnknownHostException;
import de.danoeh.antennapod.core.BuildConfig;
@ -57,54 +55,56 @@ public class HttpDownloader extends Downloader {
}
}
HttpClient httpClient = AntennapodHttpClient.getHttpClient();
OkHttpClient httpClient = AntennapodHttpClient.getHttpClient();
RandomAccessFile out = null;
InputStream connection = null;
InputStream connection;
ResponseBody responseBody = null;
try {
HttpGet httpGet = new HttpGet(URIUtil.getURIFromRequestUrl(request.getSource()));
final URI uri = URIUtil.getURIFromRequestUrl(request.getSource());
Request.Builder httpReq = new Request.Builder().url(uri.toURL())
.header("User-Agent", ClientConfig.USER_AGENT);
// add authentication information
String userInfo = httpGet.getURI().getUserInfo();
String userInfo = uri.getUserInfo();
if (userInfo != null) {
String[] parts = userInfo.split(":");
if (parts.length == 2) {
httpGet.addHeader(BasicScheme.authenticate(
new UsernamePasswordCredentials(parts[0], parts[1]),
"UTF-8", false));
String credentials = Credentials.basic(parts[0], parts[1]);
httpReq.header("Authorization", credentials);
}
} else if (!StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) {
httpGet.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(request.getUsername(),
request.getPassword()), "UTF-8", false));
String credentials = Credentials.basic(request.getUsername(), request.getPassword());
httpReq.header("Authorization", credentials);
}
// add range header if necessary
if (fileExists) {
request.setSoFar(destination.length());
httpGet.addHeader(new BasicHeader("Range",
"bytes=" + request.getSoFar() + "-"));
httpReq.addHeader("Range",
"bytes=" + request.getSoFar() + "-");
if (BuildConfig.DEBUG) Log.d(TAG, "Adding range header: " + request.getSoFar());
}
HttpResponse response = httpClient.execute(httpGet);
HttpEntity httpEntity = response.getEntity();
int responseCode = response.getStatusLine().getStatusCode();
Header contentEncodingHeader = response.getFirstHeader("Content-Encoding");
Response response = httpClient.newCall(httpReq.build()).execute();
responseBody = response.body();
final boolean isGzip = contentEncodingHeader != null &&
contentEncodingHeader.getValue().equalsIgnoreCase("gzip");
String contentEncodingHeader = response.header("Content-Encoding");
final boolean isGzip = StringUtils.equalsIgnoreCase(contentEncodingHeader, "gzip");
if (BuildConfig.DEBUG)
Log.d(TAG, "Response code is " + responseCode);
Log.d(TAG, "Response code is " + response.code());
if (responseCode / 100 != 2 || httpEntity == null) {
if (!response.isSuccessful() || response.body() == null) {
final DownloadError error;
final String details;
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
error = DownloadError.ERROR_UNAUTHORIZED;
details = String.valueOf(responseCode);
details = String.valueOf(response.code());
} else {
error = DownloadError.ERROR_HTTP_DATA_ERROR;
details = String.valueOf(responseCode);
details = String.valueOf(response.code());
}
onFail(error, details);
return;
@ -115,15 +115,14 @@ public class HttpDownloader extends Downloader {
return;
}
connection = new BufferedInputStream(AndroidHttpClient
.getUngzippedContent(httpEntity));
connection = new BufferedInputStream(responseBody.byteStream());
Header[] contentRangeHeaders = (fileExists) ? response.getHeaders("Content-Range") : null;
String contentRangeHeader = (fileExists) ? response.header("Content-Range") : null;
if (fileExists && responseCode == HttpStatus.SC_PARTIAL_CONTENT
&& contentRangeHeaders != null && contentRangeHeaders.length > 0) {
String start = contentRangeHeaders[0].getValue().substring("bytes ".length(),
contentRangeHeaders[0].getValue().indexOf("-"));
if (fileExists && response.code() == HttpStatus.SC_PARTIAL_CONTENT
&& !StringUtils.isEmpty(contentRangeHeader)) {
String start = contentRangeHeader.substring("bytes ".length(),
contentRangeHeader.indexOf("-"));
request.setSoFar(Long.valueOf(start));
Log.d(TAG, "Starting download at position " + request.getSoFar());
@ -141,7 +140,7 @@ public class HttpDownloader extends Downloader {
request.setStatusMsg(R.string.download_running);
if (BuildConfig.DEBUG)
Log.d(TAG, "Getting size of download");
request.setSize(httpEntity.getContentLength() + request.getSoFar());
request.setSize(responseBody.contentLength() + request.getSoFar());
if (BuildConfig.DEBUG)
Log.d(TAG, "Size is " + request.getSize());
if (request.getSize() < 0) {
@ -205,6 +204,7 @@ public class HttpDownloader extends Downloader {
} finally {
IOUtils.closeQuietly(out);
AntennapodHttpClient.cleanup();
IOUtils.closeQuietly(responseBody);
}
}