用 json 检查更新

This commit is contained in:
seven332 committed 2014-04-05 22:28:11 +08:00
1 parent eb1e49e7c7
commit ea58ffed74
20 files changed
+477 -310

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hippo.ehviewer"
android:versionCode="13"
android:versionName="0.4.3" >
android:versionName="0.4.0" >
<uses-sdk
android:minSdkVersion="14"
+1 -1
View File
@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hippo.ehviewer"
android:versionCode="13"
android:versionName="0.4.3" >
android:versionName="0.4.0" >
<uses-sdk
android:minSdkVersion="14"
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+2
View File
@@ -116,6 +116,8 @@
<string name="em_unexpected_response_code">非预期的响应码:%d</string>
<string name="em_redirection_error">太多重定向</string>
<string name="em_host_error">主机错误</string>
<string name="em_invalid_request">无效的请求</string>
<string name="em_no_sdcard">未挂载 SD卡</string>
<!-- Action -->
<string name="action_refresh">刷新</string>
+2
View File
@@ -121,6 +121,8 @@
<string name="em_unexpected_response_code">Unexpected response code : %d</string>
<string name="em_redirection_error">Too many redirects</string>
<string name="em_host_error">Host error</string>
<string name="em_invalid_request">Invalid request</string>
<string name="em_no_sdcard">SD card is Unmounted</string>
<!-- Action -->
<string name="action_refresh">Refresh</string>
+113 -106
View File
@@ -1,10 +1,10 @@
package com.hippo.ehviewer;
import java.io.File;
import java.net.MalformedURLException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
@@ -15,19 +15,16 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.view.View;
import com.hippo.ehviewer.network.Downloader;
import com.hippo.ehviewer.network.HttpHelper;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.EhClient;
import com.hippo.ehviewer.util.Future;
import com.hippo.ehviewer.util.FutureListener;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
import com.hippo.ehviewer.view.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
// TODO return onFailure when downloading update or check update
// TODO add disable to achieve
@@ -43,17 +40,22 @@ public class UpdateHelper {
private static final int GOOGLE = 0;
private static final int QINIU = 1;
private static boolean isWorking = false;
private Activity mActivity;
private AppContext mAppContext;
private String updateFileName;
private OnCheckUpdateListener mListener;
private static boolean mEnabled = true;
private int downloadHost = QINIU;
public UpdateHelper(Activity activity) {
mActivity = activity;
public interface OnCheckUpdateListener {
public void onSuccess(String version, long size, String url, String info);
public void onNoUpdate();
public void onFailure(String eMsg);
}
public UpdateHelper(AppContext appContext) {
mAppContext = appContext;
}
public UpdateHelper SetOnCheckUpdateListener(OnCheckUpdateListener listener) {
@@ -66,46 +68,62 @@ public class UpdateHelper {
checkUpdate();
}
public static void setEnabled(boolean enabled) {
mEnabled = enabled;
}
class CheckUpdatePackage {
public OnCheckUpdateListener listener;
public Activity activity;
public AppContext appContext;
public String pageContext;
public HttpHelper hp;
}
public void checkUpdate() {
if (isWorking) {
if (mListener != null)
mListener.onFailure("正在检查更新"); // TODO
return;
} else {
isWorking = true;
}
final AppContext appContext = (AppContext)(mActivity.getApplicationContext());
final HttpHelper hp = new HttpHelper(mActivity.getApplicationContext());
ThreadPool threadPool = appContext.getNetworkThreadPool();
final HttpHelper hp = new HttpHelper(mAppContext);
ThreadPool threadPool = mAppContext.getNetworkThreadPool();
threadPool.submit(new Job<String>() {
@Override
public String run(JobContext jc) {
PackageManager pm = appContext.getPackageManager();
if (!mEnabled) {
return "working";
}
mEnabled = false;
PackageManager pm = mAppContext.getPackageManager();
PackageInfo pi = null;
try {
pi = pm.getPackageInfo(appContext.getPackageName(), PackageManager.GET_ACTIVITIES);
pi = pm.getPackageInfo(mAppContext.getPackageName(), PackageManager.GET_ACTIVITIES);
JSONObject jo = new JSONObject();
jo.put("method", "update");
JSONObject detailJO = new JSONObject();
detailJO.put("version", pi.versionName);
// TODO switch server
detailJO.put("server", "qiniu");
jo.put("detail", detailJO);
return hp.postJson(UPDATE_API, jo.toString());
} catch (NameNotFoundException e) {
e.printStackTrace();
return "NameNotFound";
} catch (JSONException e) {
e.printStackTrace();
return "JSONException";
}
return hp.post(UPDATE_API, "last\n" + pi.versionName);
}
}, new FutureListener<String>() {
@Override
public void onFutureDone(Future<String> future) {
String pageContext = future.get();
CheckUpdatePackage checkUpdatePackage = new CheckUpdatePackage();
checkUpdatePackage.appContext = mAppContext;
checkUpdatePackage.listener = mListener;
checkUpdatePackage.activity = mActivity;
checkUpdatePackage.pageContext = pageContext;
checkUpdatePackage.hp = hp;
Message msg = new Message();
@@ -117,111 +135,98 @@ public class UpdateHelper {
}
// TODO move dialog into listener
// TODO
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
private static Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
CheckUpdatePackage checkUpdatePackage = (CheckUpdatePackage)msg.obj;
OnCheckUpdateListener listener = checkUpdatePackage.listener;
Activity activity = checkUpdatePackage.activity;
AppContext appContext = checkUpdatePackage.appContext;
String pageContext = checkUpdatePackage.pageContext;
if (pageContext != null) {
Config.setUpdateDate();
String[] items = pageContext.split("\n");
if (items.length > 3) {
String newVer = items[0];
String tempUrl = "";
switch (downloadHost) {
case GOOGLE:
tempUrl = EhClient.UPDATE_URL + items[1];
break;
case QINIU:
tempUrl = EhClient.UPDATE_URI_QINIU + Util.getFileForUrl(items[1]);
break;
}
final String url = tempUrl;
final String name = url.substring(url.lastIndexOf('/')+1);
updateFileName = name;
String size = items[2];
String info = items[3];
AlertDialog dialog = new DialogBuilder(activity).setTitle(R.string.update)
.setMessage(String.format(activity.getString(R.string.update_message), newVer, size, info))
.setNegativeButton(android.R.string.cancel, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
}
}).setPositiveButton(android.R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
Downloader d = new Downloader();
try {
d.resetData(Config.getDownloadPath(), name, url);
d.setOnDownloadListener(new UpdateListener());
new Thread(d).start();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}).create();
dialog.show();
if (pageContext.equals("working")) {
if (listener != null)
listener.onSuccess(pageContext);
listener.onFailure("正在检查更新或者下载更新"); // TODO
}
else if (pageContext.equals("NameNotFound")) {
if (listener != null)
listener.onFailure("NameNotFound"); // TODO
} else if (pageContext.equals("JSONException")) {
if (listener != null)
listener.onFailure("JSONException"); // TODO
} else {
if(pageContext.equals("none")) {
try {
JSONObject jo = new JSONObject(pageContext);
JSONObject updateJO = jo.getJSONObject("update");
String version = updateJO.getString("version");
if (version.equals("error")) {
if (listener != null)
listener.onFailure(appContext.getString(R.string.em_invalid_request));
} else if (version.equals("none")) {
if (listener != null)
listener.onNoUpdate();
} else {
long size = updateJO.getLong("size");
String url = updateJO.getString("url");
String info = updateJO.getString("info");
if (listener != null)
listener.onSuccess(version, size, url, info);
}
} catch (JSONException e) {
e.printStackTrace();
if (listener != null)
listener.onNoUpdate();
} else if(pageContext.equals("error")){
if (listener != null)
listener.onFailure(activity.getString(R.string.em_request_error));
} else if (pageContext.equals("NameNotFound")){
if (listener != null)
listener.onFailure("NameNotFound"); // TODO
}else {
if (listener != null)
listener.onFailure(activity.getString(R.string.em_host_error));
listener.onFailure(appContext.getString(R.string.em_host_error));
}
}
} else {
if (listener != null)
listener.onFailure(checkUpdatePackage.hp.getEMsg());
}
isWorking = false;
}
};
public interface OnCheckUpdateListener {
public void onSuccess(String pageContext);
public void onNoUpdate();
public void onFailure(String eMsg);
}
private class UpdateListener implements Downloader.OnDownloadListener {
public static class UpdateListener implements Downloader.OnDownloadListener {
private Context mContext;
private String mFileName;
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
public UpdateListener() {
public UpdateListener(Context context, String fileName) {
mContext = context;
mFileName = fileName;
mNotifyManager = (NotificationManager)
mActivity.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(mActivity.getApplicationContext());
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(mContext);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
}
@Override
public void onDownloadStart(int totalSize) {
mBuilder.setContentTitle("正在下载更新") // TODO
public void onDownloadStartConnect() {
mBuilder.setContentTitle("开始下载更新") // TODO
.setContentText(null)
.setProgress(0, 0, true).setOngoing(true);
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
}
@Override
public void onDownloadStartDownload(int totalSize) {
mBuilder.setContentTitle("正在下载更新")
.setContentText(String.format("%.2f / %.2f KB", 0/1024.0f, totalSize/1024.0f))
.setProgress(totalSize, 0, false).setOngoing(true);
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
}
@Override
public void onDownloadStatusUpdate(
int downloadSize, int totalSize) {
@@ -232,20 +237,22 @@ public class UpdateHelper {
}
@Override
public void onDownloadOver(boolean ok, int eMesgId) {
if (ok) {
public void onDownloadOver(int status) {
if (status == Downloader.COMPLETED) {
mNotifyManager.cancel(NOTIFICATION_ID);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Config.getDownloadPath(), updateFileName)),
intent.setDataAndType(Uri.fromFile(new File(Config.getDownloadPath(), mFileName)),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.getApplicationContext().startActivity(intent);
mContext.startActivity(intent);
} else {
mBuilder.setContentTitle("下载更新失败")
.setContentText(null)
.setProgress(0, 0, false).setOngoing(false);
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
}
setEnabled(true);
}
}
}
@@ -120,7 +120,7 @@ public class MangaActivity extends Activity {
final String imageName = String.format("%05d", index + 1) + "." + Util.getExtension(imageUrl);
final Downloader downloader = new Downloader();
final Downloader downloader = new Downloader(MangaActivity.this);
try {
downloader.resetData(mFolder.getPath(),
imageName,
@@ -1,5 +1,6 @@
package com.hippo.ehviewer.activity;
import java.net.MalformedURLException;
import java.util.ArrayList;
import com.hippo.ehviewer.AppContext;
@@ -9,6 +10,7 @@ import com.hippo.ehviewer.ListMangaDetail;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.UpdateHelper;
import com.hippo.ehviewer.network.Downloader;
import com.hippo.ehviewer.service.DownloadService;
import com.hippo.ehviewer.service.DownloadServiceConnection;
import com.hippo.ehviewer.util.Cache;
@@ -17,6 +19,7 @@ import com.hippo.ehviewer.util.EhClient;
import com.hippo.ehviewer.util.Favourite;
import com.hippo.ehviewer.util.Tag;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.view.AlertButton;
import com.hippo.ehviewer.view.CheckImage;
import com.hippo.ehviewer.view.GetPaddingRelativeLayout;
@@ -1414,7 +1417,50 @@ public class MangaListActivity extends Activity {
}
private void checkUpdate() {
new UpdateHelper(this).autoCheckUpdate();
new UpdateHelper((AppContext)getApplication())
.SetOnCheckUpdateListener(new UpdateHelper.OnCheckUpdateListener() {
@Override
public void onSuccess(String version, long size,
final String url, String info) {
String sizeStr = Util.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(MangaListActivity.this,
version, sizeStr, info,
new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
// TODO
try {
Downloader downloader = new Downloader(MangaListActivity.this);
String fileName = Util.getFileForUrl(url);
downloader.resetData(Config.getDownloadPath(), fileName, url);
downloader.setOnDownloadListener(
new UpdateHelper.UpdateListener(MangaListActivity.this,
fileName));
new Thread(downloader).start();
} catch (MalformedURLException e) {
UpdateHelper.setEnabled(true);
}
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
UpdateHelper.setEnabled(true);
}
});
if (!MangaListActivity.this.isFinishing())
dialog.show();
}
@Override
public void onNoUpdate() {
UpdateHelper.setEnabled(true);
}
@Override
public void onFailure(String eMsg) {
UpdateHelper.setEnabled(true);
}
}).autoCheckUpdate();
}
private void checkLogin(boolean force) {
@@ -1,7 +1,9 @@
package com.hippo.ehviewer.activity;
import java.io.InputStream;
import java.net.MalformedURLException;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.BeautifyScreen;
import com.hippo.ehviewer.DiskCache;
import com.hippo.ehviewer.R;
@@ -9,10 +11,14 @@ import com.hippo.ehviewer.UpdateHelper;
import com.hippo.ehviewer.util.Cache;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.view.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.SuperDialogUtil;
import com.hippo.ehviewer.network.Downloader;
import com.hippo.ehviewer.preference.AutoListPreference;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
@@ -28,9 +34,14 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.Toast;
// TODO 添加服务器选择
public class SettingsActivity extends PreferenceActivity {
@SuppressWarnings("unused")
private static String TAG = "Settings";
@@ -41,7 +52,6 @@ public class SettingsActivity extends PreferenceActivity {
private static final String CP_CACHE = "preference_cp_cache";
private static final String CLEAR_CP_CACHE = "preference_clear_cp_cache";
private static final String PAGE_SCALING = "preference_page_scaling";
private static final String AUTHOR = "preference_author";
private static final String SCREEN_ORI = "preference_screen_ori";
private static final String CHANGELOG = "preference_changelog";
@@ -51,9 +61,6 @@ public class SettingsActivity extends PreferenceActivity {
private EditTextPreference cpCachePre;
private Preference clearCpCachePre;
private EditTextPreference pageCachePre;
private Preference clearPageCachePre;
private AutoListPreference pageScalingListPre;
private Preference authorPer;
private AutoListPreference screenOriPer;
private Preference changelogPer;
@@ -213,24 +220,60 @@ public class SettingsActivity extends PreferenceActivity {
@Override
public boolean onPreferenceClick(Preference preference) {
update.setSummary(R.string.checking_update);
new UpdateHelper(SettingsActivity.this)
new UpdateHelper((AppContext)SettingsActivity.this.getApplication())
.SetOnCheckUpdateListener(new UpdateHelper.OnCheckUpdateListener() {
@Override
public void onSuccess(String pageContext) {
public void onSuccess(String version, long size,
final String url, String info) {
update.setSummary(R.string.found_update);
update.setEnabled(true);
String sizeStr = Util.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(SettingsActivity.this,
version, sizeStr, info,
new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
// TODO
try {
Downloader downloader = new Downloader(SettingsActivity.this);
String fileName = Util.getFileForUrl(url);
downloader.resetData(Config.getDownloadPath(), fileName, url);
downloader.setOnDownloadListener(
new UpdateHelper.UpdateListener(SettingsActivity.this,
fileName));
new Thread(downloader).start();
} catch (MalformedURLException e) {
update.setSummary(R.string.em_url_format_error);
UpdateHelper.setEnabled(true);
}
update.setEnabled(true);
}
}, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
update.setEnabled(true);
UpdateHelper.setEnabled(true);
}
});
if (!SettingsActivity.this.isFinishing())
dialog.show();
}
@Override
public void onNoUpdate() {
update.setSummary(R.string.up_to_date);
update.setEnabled(true);
UpdateHelper.setEnabled(true);
}
@Override
public void onFailure(String eMsg) {
update.setSummary(eMsg);
update.setEnabled(true);
UpdateHelper.setEnabled(true);
}
}).checkUpdate();
update.setEnabled(false);
return true;
}
@@ -1,8 +1,5 @@
package com.hippo.ehviewer.network;
package com.hippo.ehviewer.exception;
public class RedirectionException extends Exception {
private static final long serialVersionUID = 1L;
}
@@ -1,4 +1,4 @@
package com.hippo.ehviewer.network;
package com.hippo.ehviewer.exception;
public class ResponseCodeException extends Exception {
@@ -0,0 +1,5 @@
package com.hippo.ehviewer.exception;
public class StopRequestException extends Exception {
private static final long serialVersionUID = 1L;
}
+153 -78
View File
@@ -7,14 +7,25 @@ import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import org.apache.http.conn.ConnectTimeoutException;
import android.content.Context;
import android.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.Cache;
import com.hippo.ehviewer.util.Util;
// TODO 添加断点续传
// TODO 添加检查次磁盘空间
/**
@@ -26,21 +37,19 @@ import com.hippo.ehviewer.util.Util;
public class Downloader implements Runnable {
private static final String TAG = "Downloader";
public static final int HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
public static final int HTTP_TEMP_REDIRECT = 307;
public static final int COMPLETED = 0;
public static final int STOP = -1;
public static final int NO_SDCARD = -2;
public static final int STATUS_HTTP_DATA_ERROR = -3;
public static final int STATUS_TOO_MANY_REDIRECTS = -4;
public static final int STATUS_FILE_ERROR = -5;
public static final int NONE = 0x0;
public static final int READY = 0x1;
public static final int CONNECTING = 0x2;
public static final int DOWNLOADING = 0x3;
public static final int FAILED = 0x4;
public static final int COMPLETED = 0x5;
public static final int STOPED = 0x6;
private static final int BUFFER_SIZE = 4096;
private static final int MAX_RETRY = 3;
private static final int MAX_REDIRECTS = 5;
private static final int MAX_RETRY = 5;
private static final int DEFAULT_TIMEOUT = 5 * 1000;
private Context mContext;
private File mFolder;
private String mPath;
private String mFileName;
private URL mUrl;
@@ -51,13 +60,16 @@ public class Downloader implements Runnable {
private int mDownloadSize = 0;
private int mRedirectionCount = 0;
private int status;
private int status = NONE;
private OnDownloadListener mListener;
private Exception mException;
public interface OnDownloadListener {
public void onDownloadStart(int totalSize);
public void onDownloadStartConnect();
public void onDownloadStartDownload(int totalSize);
public void onDownloadStatusUpdate(int downloadSize, int totalSize);
public void onDownloadOver(boolean ok, int eMesgId);
public void onDownloadOver(int status);
}
public class Controlor {
@@ -80,10 +92,11 @@ public class Downloader implements Runnable {
mPath = path;
mFileName = fileName;
mUrl = new URL(urlStr);
mException = null;
mDownloadSize = 0;
mRedirectionCount = 0;
status = COMPLETED;
status = READY;
mContorlor.reset();
return mContorlor;
@@ -93,86 +106,151 @@ public class Downloader implements Runnable {
mListener = listener;
}
public Downloader() {
public Downloader(Context context) {
mContext = context;
mContorlor = new Controlor();
}
public String getEMsg() {
if (mException == null)
return mContext.getString(R.string.em_unknown_error);
else if (mException instanceof MalformedURLException)
return mContext.getString(R.string.em_url_format_error);
else if (mException instanceof ConnectTimeoutException ||
mException instanceof SocketTimeoutException)
return mContext.getString(R.string.em_timeout);
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();
else if (mException instanceof NoSdCardException)
return mContext.getString(R.string.em_no_sdcard);
else
return mException.getMessage();
}
@Override
public void run() {
boolean ok = false;
int retryTimes = 0;
if (Cache.hasSdCard())
while(true) {
if (Cache.hasSdCard()) {
boolean checkFolder = false;
try {
initFolder();
checkFolder = true;
} catch (Exception e) {
mException = e;
e.printStackTrace();
}
while(checkFolder) {
try {
if (mContorlor.isStop())
throw new StopRequestException(STOP, "Download is stopped");
throw new StopRequestException();
mRedirectionCount = 0;
status = COMPLETED;
status = READY;
executeDownload();
ok = true;
status = COMPLETED;
break;
} catch (StopRequestException e) {
} catch (Exception e) {
mException = e;
e.printStackTrace();
status = e.getFinalStatus();
if (status == STOP || retryTimes > MAX_RETRY)
if (mContorlor.isStop() || retryTimes > MAX_RETRY) {
status = FAILED;
break;
}
retryTimes++;
}
}
else
status = NO_SDCARD;
} else
mException = new NoSdCardException();
if (mContorlor.isStop())
status = STOPED;
if (mListener != null)
mListener.onDownloadOver(ok, status);
mListener.onDownloadOver(status);
}
public int getStatus() {
return status;
}
private void executeDownload() throws StopRequestException {
while (mRedirectionCount++ < MAX_REDIRECTS) {
private void initFolder() throws Exception {
mFolder = new File(mPath);
if (!mFolder.exists()) {
if (!mFolder.mkdirs())
throw new FileException(FileException.MKDIR_ERROR);
} else if (!mFolder.isDirectory()){
throw new FileException(FileException.NOT_DIR);
}
if (!mFolder.canWrite())
throw new FileException(FileException.CANNOT_WRITE);
}
private void executeDownload() throws Exception {
while (mRedirectionCount++ < Constant.MAX_REDIRECTS) {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Get file " + mUrl.toString());
status = CONNECTING;
if (mListener != null)
mListener.onDownloadStartConnect();
conn = (HttpURLConnection)mUrl.openConnection();
conn.setInstanceFollowRedirects(false);
conn.addRequestProperty("Range", "bytes=" + mDownloadSize + "-"); // TODO
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.addRequestProperty("Range", "bytes=" + mDownloadSize + "-");
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.connect();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
processResponseHeaders(conn);
status = DOWNLOADING;
if (mListener != null)
mListener.onDownloadStart(mTotalSize);
mListener.onDownloadStartDownload(mTotalSize);
transferData(conn);
return;
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
mUrl = new URL(mUrl, location);
continue;
default:
StopRequestException.throwUnhandledHttpError(
responseCode, conn.getResponseMessage());
throw new ResponseCodeException(responseCode);
}
} catch (IOException e) {
// Trouble with low-level sockets
throw new StopRequestException(STATUS_HTTP_DATA_ERROR, e);
} catch (Exception e) {
throw e;
} finally {
if (conn != null) conn.disconnect();
if (conn != null)
conn.disconnect();
}
}
throw new StopRequestException(STATUS_TOO_MANY_REDIRECTS, "Too many redirects");
throw new RedirectionException();
}
/**
@@ -220,20 +298,19 @@ public class Downloader implements Runnable {
/**
* Transfer data from the given connection to the destination file.
*/
private void transferData(HttpURLConnection conn) throws StopRequestException {
private void transferData(HttpURLConnection conn) throws Exception {
InputStream in = null;
RandomAccessFile raf = null;
File file = null;
if (mContorlor.isStop())
throw new StopRequestException(STOP,
"Download is stopped");
throw new StopRequestException();
try {
try {
in = conn.getInputStream();
} catch (IOException e) {
throw new StopRequestException(STATUS_HTTP_DATA_ERROR, e);
throw e; // TODO
}
try {
@@ -241,14 +318,15 @@ public class Downloader implements Runnable {
raf = new RandomAccessFile(file, "rw");
raf.seek(mDownloadSize);
} catch (IOException e) {
throw new StopRequestException(STATUS_FILE_ERROR, e);
throw new FileException(FileException.CREATE_FILE_ERROR);
}
// Start streaming data, periodically watch for pause/cancel
// commands and checking disk space as needed.
transferData(in, raf);
} finally {
Util.closeStreamQuietly(in);
if (in != null)
Util.closeStreamQuietly(in);
if (raf != null)
try {
raf.close();
@@ -265,9 +343,13 @@ public class Downloader implements Runnable {
*/
@SuppressWarnings("unused")
private void transferData(InputStream in, OutputStream out)
throws StopRequestException {
final byte data[] = new byte[BUFFER_SIZE];
for (;;) {
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
@@ -277,10 +359,7 @@ public class Downloader implements Runnable {
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
if (mContorlor.isStop())
throw new StopRequestException(STOP,
"Download is stopped");
}
}
@@ -289,9 +368,12 @@ public class Downloader implements Runnable {
* destination file.
*/
private void transferData(InputStream in, RandomAccessFile raf)
throws StopRequestException {
final byte data[] = new byte[BUFFER_SIZE];
for (;;) {
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
@@ -301,10 +383,6 @@ public class Downloader implements Runnable {
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
if (mContorlor.isStop())
throw new StopRequestException(STOP,
"Download is stopped");
}
}
@@ -315,13 +393,12 @@ public class Downloader implements Runnable {
* @return the number of bytes actually read or -1 if the end of the stream has been reached
*/
private int readFromResponse(byte[] data, InputStream entityStream)
throws StopRequestException {
throws Exception {
try {
return entityStream.read(data);
} catch (IOException ex) {
} catch (IOException e) {
// TODO: handle stream errors the same as other retries
throw new StopRequestException(STATUS_HTTP_DATA_ERROR,
"Failed reading response: " + ex, ex);
throw e;
}
}
@@ -332,15 +409,14 @@ public class Downloader implements Runnable {
* @param bytesRead how many bytes to write from the buffer
*/
private void writeDataToDestination(byte[] data, int bytesRead, OutputStream out)
throws StopRequestException {
throws Exception {
try {
out.write(data, 0, bytesRead);
return;
} catch (IOException ex) {
} catch (IOException e) {
// TODO: better differentiate between DRM and disk failures
// TODO: check disk is full
throw new StopRequestException(STATUS_FILE_ERROR,
"Failed to write data: " + ex);
throw e;
}
}
@@ -350,15 +426,14 @@ public class Downloader implements Runnable {
* @param bytesRead how many bytes to write from the buffer
*/
private void writeDataToDestination(byte[] data, int bytesRead, RandomAccessFile raf)
throws StopRequestException {
throws Exception {
try {
raf.write(data, 0, bytesRead);
return;
} catch (IOException ex) {
} catch (IOException e) {
// TODO: better differentiate between DRM and disk failures
// TODO: check disk is full
throw new StopRequestException(STATUS_FILE_ERROR,
"Failed to write data: " + ex);
throw e;
}
}
}
+61 -51
View File
@@ -18,6 +18,8 @@ import org.apache.http.conn.ConnectTimeoutException;
import com.hippo.ehviewer.DiskCache;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.exception.RedirectionException;
import com.hippo.ehviewer.exception.ResponseCodeException;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
@@ -36,15 +38,7 @@ import android.util.Log;
public class HttpHelper {
private static final String TAG = "HttpHelper";
public static final int HTTP_TEMP_REDIRECT = 307;
private static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36";
private static String userAgent = System.getProperty("http.agent", defaultUserAgent);
private static final int DEFAULT_TIMEOUT = 5 * 1000;
private static final int MAX_REDIRECTS = 5;
private Context mContext;
private int responseCode;
private Exception mException;
public HttpHelper(Context context) {
@@ -70,7 +64,8 @@ public class HttpHelper {
return mContext.getString(R.string.em_unknown_host);
else if (mException instanceof ResponseCodeException)
return String.format(mContext.getString(R.string.em_unexpected_response_code), responseCode);
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);
@@ -79,7 +74,7 @@ public class HttpHelper {
return "SocketException : " + mException.getMessage();
else
return mContext.getString(R.string.em_unknown_error) + " : " + mException.getMessage();
return mException.getMessage();
}
private String getPageContext(HttpURLConnection conn)
@@ -93,7 +88,7 @@ public class HttpHelper {
if (encoding != null && encoding.equals("gzip"))
is = new GZIPInputStream(is);
baos = new ByteArrayOutputStream();
Util.copy(is, baos, 1024);
Util.copy(is, baos, Constant.BUFFER_SIZE);
// TODO charset
pageContext = baos.toString("utf-8");
} catch (IOException e) {
@@ -113,16 +108,19 @@ public class HttpHelper {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Http get " + urlStr);
url = new URL(urlStr);
while (redirectionCount++ < MAX_REDIRECTS) {
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("Accept-Encoding", "gzip");
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.connect();
responseCode = conn.getResponseCode();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
@@ -131,7 +129,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
url = new URL(url, location);
continue;
@@ -140,16 +138,16 @@ public class HttpHelper {
throw new ResponseCodeException(responseCode);
}
}
if (redirectionCount > MAX_REDIRECTS)
throw new RedirectionException();
} catch (Exception e) {
mException = e;
e.printStackTrace();
return null;
} finally {
if (conn != null)
conn.disconnect();
}
mException = new RedirectionException();
return null;
}
@@ -161,13 +159,16 @@ public class HttpHelper {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Http post " + urlStr);
url = new URL(urlStr);
while (redirectionCount++ < MAX_REDIRECTS) {
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("Accept-Encoding", "gzip");
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
@@ -193,7 +194,7 @@ public class HttpHelper {
conn.connect();
responseCode = conn.getResponseCode();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
@@ -202,7 +203,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
url = new URL(url, location);
continue;
@@ -211,16 +212,16 @@ public class HttpHelper {
throw new ResponseCodeException(responseCode);
}
}
if (redirectionCount > MAX_REDIRECTS)
throw new RedirectionException();
} catch (Exception e) {
mException = e;
e.printStackTrace();
return null;
} finally {
if (conn != null)
conn.disconnect();
}
mException = new RedirectionException();
return null;
}
@@ -232,13 +233,16 @@ public class HttpHelper {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Http post " + urlStr);
url = new URL(urlStr);
while (redirectionCount++ < MAX_REDIRECTS) {
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("Accept-Encoding", "gzip");
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
@@ -252,7 +256,7 @@ public class HttpHelper {
conn.connect();
responseCode = conn.getResponseCode();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
@@ -261,7 +265,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
url = new URL(url, location);
continue;
@@ -270,16 +274,16 @@ public class HttpHelper {
throw new ResponseCodeException(responseCode);
}
}
if (redirectionCount > MAX_REDIRECTS)
throw new RedirectionException();
} catch (Exception e) {
mException = e;
e.printStackTrace();
return null;
} finally {
if (conn != null)
conn.disconnect();
}
mException = new RedirectionException();
return null;
}
@@ -292,13 +296,16 @@ public class HttpHelper {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Http post " + urlStr);
url = new URL(urlStr);
while (redirectionCount++ < MAX_REDIRECTS) {
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("Accept-Encoding", "gzip");
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
@@ -314,7 +321,7 @@ public class HttpHelper {
conn.connect();
responseCode = conn.getResponseCode();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
@@ -323,7 +330,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
url = new URL(url, location);
continue;
@@ -332,16 +339,16 @@ public class HttpHelper {
throw new ResponseCodeException(responseCode);
}
}
if (redirectionCount > MAX_REDIRECTS)
throw new RedirectionException();
} catch (Exception e) {
mException = e;
e.printStackTrace();
return null;
} finally {
if (conn != null)
conn.disconnect();
}
mException = new RedirectionException();
return null;
}
@@ -358,15 +365,18 @@ public class HttpHelper {
InputStream is = null;
try {
Log.d(TAG, "Http get bitmap " + urlStr);
url = new URL(urlStr);
while (redirectionCount++ < MAX_REDIRECTS) {
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
conn = (HttpURLConnection)url.openConnection();
conn.setRequestProperty("User-Agent", userAgent);
conn.setConnectTimeout(DEFAULT_TIMEOUT);
conn.setReadTimeout(DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.connect();
responseCode = conn.getResponseCode();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_PARTIAL:
@@ -408,7 +418,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case HTTP_TEMP_REDIRECT:
case Constant.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
url = new URL(url, location);
continue;
@@ -417,11 +427,10 @@ public class HttpHelper {
throw new ResponseCodeException(responseCode);
}
}
if (redirectionCount > MAX_REDIRECTS)
throw new RedirectionException();
} catch (Exception e) {
mException = e;
e.printStackTrace();
return null;
} finally {
if (baos != null)
Util.closeStreamQuietly(baos);
@@ -430,6 +439,7 @@ public class HttpHelper {
if (conn != null)
conn.disconnect();
}
mException = new RedirectionException();
return null;
}
}
@@ -1,31 +0,0 @@
package com.hippo.ehviewer.network;
class StopRequestException extends Exception {
private final int mFinalStatus;
public StopRequestException(int finalStatus, String message) {
super(message);
mFinalStatus = finalStatus;
}
public StopRequestException(int finalStatus, Throwable t) {
super(t);
mFinalStatus = finalStatus;
}
public StopRequestException(int finalStatus, String message, Throwable t) {
super(message, t);
mFinalStatus = finalStatus;
}
public int getFinalStatus() {
return mFinalStatus;
}
public static StopRequestException throwUnhandledHttpError(int code, String message)
throws StopRequestException {
final String error = "Unhandled HTTP response: " + code + " " + message;
throw new StopRequestException(code, error);
}
}
+11 -5
View File
@@ -1179,10 +1179,16 @@ public class EhClient {
listener.onDownloadMangaAllStart();
Parser parser = new Parser();
Downloader imageDownloader = new Downloader();
Downloader imageDownloader = new Downloader(mAppContext);
imageDownloader.setOnDownloadListener(new Downloader.OnDownloadListener() {
@Override
public void onDownloadStart(int totalSize) {
public void onDownloadStartConnect() {
}
@Override
public void onDownloadStartDownload(int totalSize) {
if (curDownloadInfo != null) {
curDownloadInfo.downloadSize = 0;
curDownloadInfo.totalSize = totalSize/1024.0f;
@@ -1199,8 +1205,8 @@ public class EhClient {
}
@Override
public void onDownloadOver(boolean ok, int eMesgId) {
if (ok)
public void onDownloadOver(int status) {
if (status == Downloader.COMPLETED)
mService.notifyUpdate(curDownloadInfo.gid, curDownloadInfo.lastStartIndex, ImageSet.STATE_LOADED);
else
mService.notifyUpdate(curDownloadInfo.gid, curDownloadInfo.lastStartIndex, ImageSet.STATE_FAIL);
@@ -1280,7 +1286,7 @@ public class EhClient {
curDownloadInfo.totalSize = 0;
int downloadStatus = imageDownloader.getStatus();
if (downloadStatus == Downloader.STOP) { // If stop by user
if (downloadStatus == Downloader.STOPED) { // If stop by user
listener.onDownloadMangaStop(curDownloadInfo.gid);
mService.notifyUpdate();
Download.notify(String.valueOf(curDownloadInfo.gid));
+17 -23
View File
@@ -1,44 +1,22 @@
package com.hippo.ehviewer.util;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import com.hippo.ehviewer.DiskCache;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Movie;
import android.os.Build;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.ImageView;
public class Util {
@SuppressWarnings("unused")
private static String TAG = "Util";
/**
@@ -213,4 +191,20 @@ public class Util {
} catch (NumberFormatException e) {}
return time;
}
private static String[] SIZE_UNIT = {"%.2f B", "%.2f KB", "%.2f MB", "%.2f GB"};
public static String sizeToString(long size) {
int length = SIZE_UNIT.length;
float sizeFloat = (float)size;
for (int i = 0; i < length; i++) {
if (sizeFloat < 1024 || i == length - 1) {
return String.format(SIZE_UNIT[i], sizeFloat);
}
sizeFloat /= 1024;
}
return null;
}
}
@@ -15,4 +15,15 @@ public class SuperDialogUtil {
titleView.setText(title);
}
public static AlertDialog createUpdateDialog(Context context, String version,
String size, String info, View.OnClickListener positiveListener,
View.OnClickListener negativeListener) {
return new DialogBuilder(context).setTitle(R.string.update).setCancelable(false)
.setMessage(String.format(context.getString(R.string.update_message), version, size, info))
.setPositiveButton(android.R.string.ok, positiveListener)
.setNegativeButton(android.R.string.cancel, negativeListener)
.create();
}
}