From db3fe7e44669e50488815cd67308cd539ec9c673 Mon Sep 17 00:00:00 2001 From: seven332 Date: Sat, 28 Jun 2014 02:36:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20HttpHelper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- res/values-zh-rCN/strings.xml | 1 + res/values/strings.xml | 1 + .../hippo/ehviewer/GallerysDownloader.java | 5 - src/com/hippo/ehviewer/ehclient/EhClient.java | 43 +- src/com/hippo/ehviewer/ehclient/EhInfo.java | 1 + .../exception/RedirectionException.java | 21 - .../exception/ResponseCodeException.java | 37 -- .../ehviewer/exception/SadPandaException.java | 21 - .../hippo/ehviewer/network/Downloader.java | 15 +- .../hippo/ehviewer/network/HttpHelper.java | 443 ++++++++++++------ 10 files changed, 331 insertions(+), 257 deletions(-) delete mode 100644 src/com/hippo/ehviewer/exception/RedirectionException.java delete mode 100644 src/com/hippo/ehviewer/exception/ResponseCodeException.java delete mode 100644 src/com/hippo/ehviewer/exception/SadPandaException.java diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index cebe5c14e..04ecea792 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -144,6 +144,7 @@ 非预期的响应码:%d 太多重定向 主机错误 + 获取正文失败 无效的请求 未挂载 SD卡 diff --git a/res/values/strings.xml b/res/values/strings.xml index 1ea76b8ef..64eef3048 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -145,6 +145,7 @@ Unexpected response code : %d Too many redirects Host error + Get body error Invalid request SD card is Unmounted diff --git a/src/com/hippo/ehviewer/GallerysDownloader.java b/src/com/hippo/ehviewer/GallerysDownloader.java index 1934d86b8..f90259091 100644 --- a/src/com/hippo/ehviewer/GallerysDownloader.java +++ b/src/com/hippo/ehviewer/GallerysDownloader.java @@ -131,9 +131,4 @@ public class GallerysDownloader { void onGalleryDownloadFailed(DownloadInfo downloadInfo, String eMsg); void onGalleryDownloadCompleted(DownloadInfo downloadInfo); } - - - - - } diff --git a/src/com/hippo/ehviewer/ehclient/EhClient.java b/src/com/hippo/ehviewer/ehclient/EhClient.java index a2a0aaa46..2e4ccdc71 100644 --- a/src/com/hippo/ehviewer/ehclient/EhClient.java +++ b/src/com/hippo/ehviewer/ehclient/EhClient.java @@ -272,7 +272,8 @@ public class EhClient { final HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String body) { + public void onSuccess(Object obj) { + String body = (String)obj; LoginParser parser = new LoginParser(); if (parser.parser(body)) { mInfo.login(username, parser.displayname); @@ -360,7 +361,8 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String body) { + public void onSuccess(Object obj) { + String body = (String)obj; ListParser parser = new ListParser(); switch (parser.parser(body)) { case ListParser.ALL: @@ -398,7 +400,8 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String body) { + public void onSuccess(Object obj) { + String body = (String)obj; DetailParser parser = new DetailParser(); int mode = DetailParser.DETAIL | DetailParser.TAG | DetailParser.PREVIEW_INFO | DetailParser.PREVIEW @@ -463,7 +466,8 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String body) { + public void onSuccess(Object obj) { + String body = (String)obj; DetailParser parser = new DetailParser(); parser.setMode(DetailParser.PREVIEW); if (parser.parser(body) == DetailParser.PREVIEW) { @@ -905,10 +909,11 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContent) { + public void onSuccess(Object obj) { + String body = (String)obj; DetailParser parser = new DetailParser(); parser.setMode(DetailParser.COMMENT); - if (parser.parser(pageContent) == DetailParser.COMMENT) { + if (parser.parser(body) == DetailParser.COMMENT) { listener.onSuccess(parser.comments); } else { listener.onFailure("parser error"); // TODO @@ -958,9 +963,10 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContext) { + public void onSuccess(Object obj) { + String body = (String)obj; RateParser parser = new RateParser(); - if (parser.parser(pageContext)) { + if (parser.parser(body)) { listener.onSuccess(parser.mRatingAvg, parser.mRatingCnt); } else { listener.onFailure("parser error"); // TODO @@ -1008,9 +1014,10 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContext) { + public void onSuccess(Object obj) { + String body = (String)obj; VoteParser parser = new VoteParser(); - if (parser.parser(pageContext)) { + if (parser.parser(body)) { listener.onSuccess(parser.mTagPane); } else { listener.onFailure("parser error"); // TODO @@ -1065,10 +1072,10 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContext) { - + public void onSuccess(Object obj) { + String body = (String)obj; AddToFavoriteParser parser = new AddToFavoriteParser(); - if (parser.parser(pageContext)) { + if (parser.parser(body)) { listener.onSuccess(); // Analytics Analytics.addToFavoriteGallery(mAppContext, gid, token); @@ -1185,9 +1192,10 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContext) { + public void onSuccess(Object obj) { + String body = (String)obj; ListParser parser = new ListParser(); - int re = parser.parser(pageContext); + int re = parser.parser(body); if (re == ListParser.ALL) { listener.onSuccess(parser.giList, parser.indexPerPage, parser.maxPage); } else if (re == ListParser.NOT_FOUND) { @@ -1240,10 +1248,11 @@ public class EhClient { HttpHelper hp = new HttpHelper(mAppContext); hp.setOnRespondListener(new HttpHelper.OnRespondListener() { @Override - public void onSuccess(String pageContext) { + public void onSuccess(Object obj) { + String body = (String)obj; try { List gis = new ArrayList(); - JSONObject js = new JSONObject(pageContext); + JSONObject js = new JSONObject(body); js = js.getJSONObject("popular"); if (!js.has("galleries")) { diff --git a/src/com/hippo/ehviewer/ehclient/EhInfo.java b/src/com/hippo/ehviewer/ehclient/EhInfo.java index a9b577831..47e004265 100644 --- a/src/com/hippo/ehviewer/ehclient/EhInfo.java +++ b/src/com/hippo/ehviewer/ehclient/EhInfo.java @@ -48,6 +48,7 @@ public class EhInfo { private static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.PNG; private static Bitmap DEFAULT_AVATAR; + public static final String EX_HOST = "exhentai.org"; public static final String[] COOKIABLE_HOSTS = {"exhentai.org", "g.e-hentai.org", "forums.e-hentai.org"}; diff --git a/src/com/hippo/ehviewer/exception/RedirectionException.java b/src/com/hippo/ehviewer/exception/RedirectionException.java deleted file mode 100644 index e437a4e68..000000000 --- a/src/com/hippo/ehviewer/exception/RedirectionException.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2014 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.exception; - -public class RedirectionException extends Exception { - private static final long serialVersionUID = 1L; -} diff --git a/src/com/hippo/ehviewer/exception/ResponseCodeException.java b/src/com/hippo/ehviewer/exception/ResponseCodeException.java deleted file mode 100644 index 867700fd7..000000000 --- a/src/com/hippo/ehviewer/exception/ResponseCodeException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2014 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.exception; - -public class ResponseCodeException extends Exception { - - private static final long serialVersionUID = 1L; - private static final String eMsg = "Error response code"; - private int mResponseCode; - - public ResponseCodeException(int responseCode) { - this(responseCode, eMsg); - } - - public ResponseCodeException(int responseCode, String message) { - super(message); - mResponseCode = responseCode; - } - - public int getResponseCode() { - return mResponseCode; - } -} diff --git a/src/com/hippo/ehviewer/exception/SadPandaException.java b/src/com/hippo/ehviewer/exception/SadPandaException.java deleted file mode 100644 index e62383969..000000000 --- a/src/com/hippo/ehviewer/exception/SadPandaException.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2014 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.exception; - -public class SadPandaException extends Exception { - private static final long serialVersionUID = 1L; -} diff --git a/src/com/hippo/ehviewer/network/Downloader.java b/src/com/hippo/ehviewer/network/Downloader.java index 1ae1c7794..f243301b7 100644 --- a/src/com/hippo/ehviewer/network/Downloader.java +++ b/src/com/hippo/ehviewer/network/Downloader.java @@ -36,8 +36,6 @@ import com.hippo.ehviewer.util.Log; import com.hippo.ehviewer.R; import com.hippo.ehviewer.exception.FileException; import com.hippo.ehviewer.exception.NoSdCardException; -import com.hippo.ehviewer.exception.RedirectionException; -import com.hippo.ehviewer.exception.ResponseCodeException; import com.hippo.ehviewer.exception.StopRequestException; import com.hippo.ehviewer.util.Util; @@ -146,13 +144,6 @@ public class Downloader implements Runnable { else if (mException instanceof UnknownHostException) return mContext.getString(R.string.em_unknown_host); - else if (mException instanceof ResponseCodeException) - return String.format(mContext.getString(R.string.em_unexpected_response_code), - ((ResponseCodeException)mException).getResponseCode()); - - else if (mException instanceof RedirectionException) - return mContext.getString(R.string.em_redirection_error); - else if (mException instanceof SocketException) return "SocketException : " + mException.getMessage(); @@ -267,7 +258,7 @@ public class Downloader implements Runnable { continue; default: - throw new ResponseCodeException(responseCode); + //throw new ResponseCodeException(responseCode); } } catch (Exception e) { throw e; @@ -276,7 +267,7 @@ public class Downloader implements Runnable { conn.disconnect(); } } - throw new RedirectionException(); + //throw new RedirectionException(); } /** @@ -287,7 +278,7 @@ public class Downloader implements Runnable { private void processResponseHeaders(HttpURLConnection conn) { mTotalSize = conn.getContentLength(); - // bytes 500-999/1234 + // String range; if ((range = conn.getHeaderField("Content-Range")) != null) { // Support Content-Range boolean newNum = true; diff --git a/src/com/hippo/ehviewer/network/HttpHelper.java b/src/com/hippo/ehviewer/network/HttpHelper.java index dd8647346..ee143bb0d 100644 --- a/src/com/hippo/ehviewer/network/HttpHelper.java +++ b/src/com/hippo/ehviewer/network/HttpHelper.java @@ -16,24 +16,20 @@ package com.hippo.ehviewer.network; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.CookiePolicy; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.ProtocolException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLEncoder; import java.net.UnknownHostException; -import java.util.List; -import java.util.Map; import java.util.zip.GZIPInputStream; import org.apache.http.conn.ConnectTimeoutException; @@ -42,9 +38,7 @@ import org.json.JSONObject; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ehclient.EhClient; import com.hippo.ehviewer.ehclient.EhInfo; -import com.hippo.ehviewer.exception.RedirectionException; -import com.hippo.ehviewer.exception.ResponseCodeException; -import com.hippo.ehviewer.exception.SadPandaException; +import com.hippo.ehviewer.exception.StopRequestException; import com.hippo.ehviewer.util.Constants; import com.hippo.ehviewer.util.Ui; import com.hippo.ehviewer.util.Util; @@ -67,13 +61,18 @@ public class HttpHelper { private static final String TAG = "HttpHelper"; public static final String SAD_PANDA_ERROR = "Sad Panda"; public static final String HAPPY_PANDA_BODY = "Happy Panda"; - + public static final String DOWNLOAD_STOP = "Stop"; + public static final String DOWNLOAD_OK = "Download"; private static String DEFAULT_CHARSET = "utf-8"; private static String CHARSET_KEY = "charset="; class Package { + Object obj; OnRespondListener listener; - String str; + public Package(Object obj, OnRespondListener listener) { + this.obj = obj; + this.listener = listener; + } } private static Handler mHandler; @@ -90,13 +89,13 @@ public class HttpHelper { public void handleMessage(Message msg) { Package p = (Package)msg.obj; OnRespondListener listener = p.listener; - String str = p.str; + Object obj = p.obj; switch (msg.what) { case Constants.TRUE: - listener.onSuccess(str); + listener.onSuccess(obj); break; case Constants.FALSE: - listener.onFailure(str); + listener.onFailure((String)obj); break; } } @@ -104,7 +103,7 @@ public class HttpHelper { } public interface OnRespondListener { - void onSuccess(String body); + void onSuccess(Object body); void onFailure(String eMsg); } @@ -114,7 +113,6 @@ public class HttpHelper { public HttpHelper(Context context) { mContext = context; - mContext.getApplicationContext(); } @@ -153,49 +151,13 @@ public class HttpHelper { else if (e instanceof SadPandaException) return SAD_PANDA_ERROR; + else if (e instanceof GetBodyException) + return "获取失败"; // TODO + else return e.getMessage(); } - private String getBody(HttpURLConnection conn) - throws IOException { - String pageContext = null; - InputStream is = null; - ByteArrayOutputStream baos = null; - try { - is = conn.getInputStream(); - String encoding = conn.getContentEncoding(); - if (encoding != null && encoding.equals("gzip")) - is = new GZIPInputStream(is); - - int length = conn.getContentLength(); - if (length >= 0) - baos = new ByteArrayOutputStream(length); - else - baos = new ByteArrayOutputStream(); - - Util.copy(is, baos, Constant.BUFFER_SIZE); - - // Get charset - String charset = null; - String contentType = conn.getContentType(); - int index = -1; - if (contentType != null - && (index = contentType.indexOf(CHARSET_KEY)) != -1) { - charset = contentType.substring(index + CHARSET_KEY.length()); - } else - charset = DEFAULT_CHARSET; - - pageContext = baos.toString(charset); - } catch (IOException e) { - throw e; - } finally { - Util.closeStreamQuietly(is); - Util.closeStreamQuietly(baos); - } - return pageContext; - } - private boolean isUrlCookiable(URL url) { String host = url.getHost(); for (String h : EhInfo.COOKIABLE_HOSTS) { @@ -205,7 +167,7 @@ public class HttpHelper { return false; } - private String requst(RequestHelper rh, String urlStr) { + private Object requst(RequestHelper rh, String urlStr) { mException = null; int redirectionCount = 0; URL url = null; @@ -221,7 +183,6 @@ public class HttpHelper { while (redirectionCount++ < Constant.MAX_REDIRECTS) { conn = (HttpURLConnection) url.openConnection(); conn.setInstanceFollowRedirects(true); - conn.addRequestProperty("Accept-Encoding", "gzip"); conn.setRequestProperty("User-Agent", Constant.userAgent); conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT); conn.setReadTimeout(Constant.DEFAULT_TIMEOUT); @@ -237,32 +198,30 @@ public class HttpHelper { case HttpURLConnection.HTTP_OK: case HttpURLConnection.HTTP_PARTIAL: // Test sad panda - String contentType = conn.getHeaderField("Content-Type"); - if (contentType != null && contentType.equals("image/gif")) - throw new SadPandaException(); + if (url.getHost().equals(EhInfo.EX_HOST)) { + String contentType = conn.getHeaderField("Content-Type"); + if (contentType != null && contentType.equals("image/gif")) + throw new SadPandaException(); + } // Store cookie if necessary if (isCookiable) EhInfo.getInstance(mContext).storeCookie(conn); - // Get body if necessary - String body = rh.isNeedBody(); - if (body == null) - body = getBody(conn); + // Get object connection + Object obj = rh.onAfterConnect(conn); // Send to UI thread if necessary if (msg != null) { - Package p = new Package(); - p.listener = mListener; - p.str = body; - msg.obj = p; + msg.obj = new Package(obj, mListener); msg.what = Constants.TRUE; mHandler.sendMessage(msg); } - return body; + return obj; // redirect case HttpURLConnection.HTTP_MOVED_PERM: case HttpURLConnection.HTTP_MOVED_TEMP: case HttpURLConnection.HTTP_SEE_OTHER: case Constant.HTTP_TEMP_REDIRECT: final String location = conn.getHeaderField("Location"); + conn.disconnect(); url = new URL(url, location); continue; @@ -270,15 +229,13 @@ public class HttpHelper { throw new ResponseCodeException(responseCode); } } + throw new RedirectionException(); } catch (Exception e) { mException = e; e.printStackTrace(); if (msg != null) { - Package p = new Package(); - p.listener = mListener; - p.str = getEMsg(); - msg.obj = p; + msg.obj = new Package(getEMsg(), mListener); msg.what = Constants.FALSE; mHandler.sendMessage(msg); } @@ -287,17 +244,23 @@ public class HttpHelper { if (conn != null) conn.disconnect(); } - mException = new RedirectionException(); - return null; } - interface RequestHelper { + private interface RequestHelper { + /** + * Add header or do something else for HttpURLConnection before connect + * @param conn + * @throws Exception + */ public void onBeforeConnect(HttpURLConnection conn) throws Exception; /** - * If need body, return null, otherwise return a string used as body + * Get what do you need from HttpURLConnection after connect + * Return null means get error + * @param conn * @return + * @throws Exception */ - public String isNeedBody(); + public Object onAfterConnect(HttpURLConnection conn) throws Exception; } /** @@ -306,35 +269,88 @@ public class HttpHelper { private class CheckSpHelper implements RequestHelper { @Override public void onBeforeConnect(HttpURLConnection conn) - throws ProtocolException { + throws Exception { conn.setRequestMethod("HEAD"); } @Override - public String isNeedBody() { + public Object onAfterConnect(HttpURLConnection conn) + throws Exception { return HAPPY_PANDA_BODY; } } + private abstract class GetStringHelper implements RequestHelper { + @Override + public void onBeforeConnect(HttpURLConnection conn) + throws Exception { + conn.addRequestProperty("Accept-Encoding", "gzip"); + } + + private String getBody(HttpURLConnection conn) + throws Exception { + String body = null; + InputStream is = null; + ByteArrayOutputStream baos = null; + try { + is = conn.getInputStream(); + String encoding = conn.getContentEncoding(); + if (encoding != null && encoding.equals("gzip")) + is = new GZIPInputStream(is); + + int length = conn.getContentLength(); + if (length >= 0) + baos = new ByteArrayOutputStream(length); + else + baos = new ByteArrayOutputStream(); + + Util.copy(is, baos, Constant.BUFFER_SIZE); + + // Get charset + String charset = null; + String contentType = conn.getContentType(); + int index = -1; + if (contentType != null + && (index = contentType.indexOf(CHARSET_KEY)) != -1) { + charset = contentType.substring(index + CHARSET_KEY.length()); + } else + charset = DEFAULT_CHARSET; + + body = baos.toString(charset); + if (body == null) + throw new GetBodyException(); + } catch (Exception e) { + throw e; + } finally { + Util.closeStreamQuietly(is); + Util.closeStreamQuietly(baos); + } + return body; + } + + @Override + public Object onAfterConnect(HttpURLConnection conn) + throws Exception { + return getBody(conn); + } + } + /** * RequstHelper for GET method */ - private class GetHelper implements RequestHelper { + private class GetHelper extends GetStringHelper { @Override public void onBeforeConnect(HttpURLConnection conn) - throws ProtocolException { + throws Exception { + super.onBeforeConnect(conn); conn.setRequestMethod("GET"); } - @Override - public String isNeedBody() { - return null; - } } /** * RequstHelper for post form data, use POST method */ - private class PostFormHelper implements RequestHelper { + private class PostFormHelper extends GetStringHelper { private String[][] mArgs; public PostFormHelper(String[][] args) { @@ -344,6 +360,7 @@ public class HttpHelper { @Override public void onBeforeConnect(HttpURLConnection conn) throws Exception { + super.onBeforeConnect(conn); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); @@ -367,16 +384,12 @@ public class HttpHelper { out.flush(); out.close(); } - @Override - public String isNeedBody() { - return null; - } } /** * RequstHelper for post json, use POST method */ - private class PostJsonHelper implements RequestHelper { + private class PostJsonHelper extends GetStringHelper { private JSONObject mJo; public PostJsonHelper(JSONObject jo) { @@ -385,6 +398,7 @@ public class HttpHelper { @Override public void onBeforeConnect(HttpURLConnection conn) throws Exception { + super.onBeforeConnect(conn); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); @@ -396,18 +410,155 @@ public class HttpHelper { out.flush(); out.close(); } + } + + private class GetImageHelper implements RequestHelper { @Override - public String isNeedBody() { - return null; + public void onBeforeConnect(HttpURLConnection conn) + throws Exception { + conn.setRequestMethod("GET"); + } + + @Override + public Object onAfterConnect(HttpURLConnection conn) + throws Exception { + Bitmap bmp = BitmapFactory.decodeStream(conn.getInputStream(), null, Ui.getBitmapOpt()); + if (bmp == null) + throw new GetBodyException(); + return bmp; } } + public interface OnDownloadListener { + public void onDownloadStartConnect(); + /** + * If totalSize -1 for can't get length info + * @param totalSize + */ + public void onDownloadStartDownload(int totalSize); + public void onDownloadStatusUpdate(int downloadSize, int totalSize); + /** + * FAILED or COMPLETED or STOPED + * @param status + */ + public void onDownloadOver(int status, String eMsg); + } + + public class DownloadControlor { + private boolean mStop = false; + + public void stop() { + mStop = true; + } + + public void reset() { + mStop = false; + } + + public boolean isStop() { + return mStop; + } + } + + private class DownloadHelper implements RequestHelper { + private File mDir; + private String mFileName; + private DownloadControlor mControlor; + private OnDownloadListener mListener; + private int mContentLength; + private int mReceivedSize; + + public DownloadHelper(File dir, String fileName, DownloadControlor controlor, OnDownloadListener listener) { + mDir = dir; + mFileName = fileName; + mControlor = controlor; + mListener = listener; + } + + @Override + public void onBeforeConnect(HttpURLConnection conn) throws Exception { + conn.setRequestMethod("GET"); + conn.addRequestProperty("Range", "bytes=0-"); + mListener.onDownloadStartConnect(); + } + + private int getContentLength(HttpURLConnection conn) { + int contentLength = conn.getContentLength(); + String range; + if (contentLength == -1 && + (range = conn.getHeaderField("Content-Range")) != null) { + // Content-Range looks like bytes 500-999/1234 + contentLength = 0; + int step = 0; + boolean isNum = false; + char ch; + for (int i = 0; i < range.length(); i++) { + ch = range.charAt(i); + if (ch >= '0' && ch <= '9') { + if (!isNum) { + isNum = true; + step++; + } + } else { + isNum = false; + } + if (isNum && step == 3) + contentLength = contentLength * 10 + ch - '0'; + } + } + return contentLength; + } + + @Override + public Object onAfterConnect(HttpURLConnection conn) throws Exception { + mContentLength = getContentLength(conn); + mListener.onDownloadStartDownload(mContentLength); + + // Make sure parent exist + mDir.mkdirs(); + File file = new File(mDir, mFileName); + try { + transferData(conn.getInputStream(), new FileOutputStream(file)); + return DOWNLOAD_OK; + } catch (StopRequestException e) { + return DOWNLOAD_STOP; + } catch (Exception e) { + throw e; + } + } + + private void transferData(InputStream in, OutputStream out) + throws Exception { + final byte data[] = new byte[Constant.BUFFER_SIZE]; + mReceivedSize = 0; + + while (true) { + if (mControlor.isStop()) + throw new StopRequestException(); + + int bytesRead = in.read(data); + if (bytesRead == -1) + break; + out.write(data, 0, bytesRead); + mReceivedSize += bytesRead; + + mListener.onDownloadStatusUpdate(mReceivedSize, mContentLength); + } + + if (mContentLength != -1 && mReceivedSize != mContentLength) + throw new UncompletedException(); + } + + } + /** - * Check Sad Panda + * Check Sad Panda. + * If get Sad Panda, return null, + * else return HttpHelper.HAPPY_PANDA_BODY * @return */ public String checkSadPanda() { - return requst(new CheckSpHelper(), EhClient.EX_HEADER); + return (String)requst(new CheckSpHelper(), EhClient.EX_HEADER); } /** @@ -416,7 +567,7 @@ public class HttpHelper { * @return */ public String get(String url) { - return requst(new GetHelper(), url); + return (String)requst(new GetHelper(), url); } /** @@ -426,7 +577,7 @@ public class HttpHelper { * @return */ public String postForm(String url, String[][] args) { - return requst(new PostFormHelper(args), url); + return (String)requst(new PostFormHelper(args), url); } /** @@ -436,55 +587,59 @@ public class HttpHelper { * @return */ public String postJson(String url, JSONObject json) { - return requst(new PostJsonHelper(json), url); + return (String)requst(new PostJsonHelper(json), url); } - public Bitmap getImage(String urlStr) { - mException = null; + /** + * Get image + * @param url + * @return + */ + public Bitmap getImage(String url) { + return (Bitmap)requst(new GetImageHelper(), url); + } + + public String download(String url, File dir, String file, + DownloadControlor controlor, OnDownloadListener listener) { + return (String)requst(new DownloadHelper(dir, file, + controlor, listener), url); + } + + /** Exceptions **/ + + public class SadPandaException extends Exception { + private static final long serialVersionUID = 1L; + } + + public class GetBodyException extends Exception { + private static final long serialVersionUID = 1L; + } + + public class RedirectionException extends Exception { + private static final long serialVersionUID = 1L; + } + + public class UncompletedException extends Exception { + private static final long serialVersionUID = 1L; + } + + public class ResponseCodeException extends Exception { - int redirectionCount = 0; - URL url = null; - HttpURLConnection conn = null; + private static final long serialVersionUID = 1L; + private static final String eMsg = "Error response code"; + private int mResponseCode; - try { - Log.d(TAG, "Http get image " + urlStr); - url = new URL(urlStr); - while (redirectionCount++ < Constant.MAX_REDIRECTS) { - conn = (HttpURLConnection)url.openConnection(); - conn.setRequestProperty("User-Agent", Constant.userAgent); - conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT); - conn.setReadTimeout(Constant.DEFAULT_TIMEOUT); - conn.setRequestMethod("GET"); - conn.connect(); - - final int responseCode = conn.getResponseCode(); - switch (responseCode) { - case HttpURLConnection.HTTP_OK: - case HttpURLConnection.HTTP_PARTIAL: - Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(), null, Ui.getBitmapOpt()); - return bitmap; - - case HttpURLConnection.HTTP_MOVED_PERM: - case HttpURLConnection.HTTP_MOVED_TEMP: - case HttpURLConnection.HTTP_SEE_OTHER: - case Constant.HTTP_TEMP_REDIRECT: - final String location = conn.getHeaderField("Location"); - url = new URL(url, location); - continue; - - default: - throw new ResponseCodeException(responseCode); - } - } - } catch (Exception e) { - mException = e; - e.printStackTrace(); - return null; - } finally { - if (conn != null) - conn.disconnect(); + public ResponseCodeException(int responseCode) { + this(responseCode, eMsg); + } + + public ResponseCodeException(int responseCode, String message) { + super(message); + mResponseCode = responseCode; + } + + public int getResponseCode() { + return mResponseCode; } - mException = new RedirectionException(); - return null; } }