diff --git a/app/build.gradle b/app/build.gradle index e58524e30..9e4ca5578 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 - } } \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index 6949fd4ad..bd3720dbf 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -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' +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index 117cbf96b..5ee40186f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -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 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 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 added, Collection 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"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java index 67f059d7d..ec3d3e2fe 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java @@ -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; - } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 32d0d351a..6bfd9b4a0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -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); } }