DownloadUtil 优化
This commit is contained in:
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
*
|
||||||
|
* 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.arialyy.aria.core.task;
|
||||||
|
|
||||||
|
import com.arialyy.aria.util.CAConfiguration;
|
||||||
|
import com.arialyy.aria.util.SSLContextUtil;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.ProtocolException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lyy on 2017/1/18.
|
||||||
|
* 链接帮助类
|
||||||
|
*/
|
||||||
|
class ConnectionHelp {
|
||||||
|
/**
|
||||||
|
* 处理链接
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
static HttpURLConnection handleConnection(URL url) throws IOException {
|
||||||
|
HttpURLConnection conn;
|
||||||
|
URLConnection urlConn = url.openConnection();
|
||||||
|
if (urlConn instanceof HttpsURLConnection) {
|
||||||
|
conn = (HttpsURLConnection) urlConn;
|
||||||
|
SSLContext sslContext =
|
||||||
|
SSLContextUtil.getSSLContext(CAConfiguration.CA_ALIAS, CAConfiguration.CA_ALIAS);
|
||||||
|
if (sslContext == null) {
|
||||||
|
sslContext = SSLContextUtil.getDefaultSLLContext();
|
||||||
|
}
|
||||||
|
SSLSocketFactory ssf = sslContext.getSocketFactory();
|
||||||
|
((HttpsURLConnection) conn).setSSLSocketFactory(ssf);
|
||||||
|
((HttpsURLConnection) conn).setHostnameVerifier(SSLContextUtil.HOSTNAME_VERIFIER);
|
||||||
|
} else {
|
||||||
|
conn = (HttpURLConnection) urlConn;
|
||||||
|
}
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置头部参数
|
||||||
|
*
|
||||||
|
* @throws ProtocolException
|
||||||
|
*/
|
||||||
|
static HttpURLConnection setConnectParam(HttpURLConnection conn) throws ProtocolException {
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setRequestProperty("Charset", "UTF-8");
|
||||||
|
conn.setRequestProperty("User-Agent",
|
||||||
|
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
|
||||||
|
conn.setRequestProperty("Accept",
|
||||||
|
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
|
||||||
|
////用于处理Disconnect 不起作用问题
|
||||||
|
//conn.setRequestProperty("Connection", "close");
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
*
|
||||||
|
* 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.arialyy.aria.core.task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lyy on 2017/1/18.
|
||||||
|
* 下载状态常量
|
||||||
|
*/
|
||||||
|
final class DownloadStateConstance {
|
||||||
|
int CANCEL_NUM = 0;
|
||||||
|
int STOP_NUM = 0;
|
||||||
|
int FAIL_NUM = 0;
|
||||||
|
int CONNECT_TIME_OUT = 5000 * 4; //连接超时时间
|
||||||
|
int READ_TIME_OUT = 1000 * 20; //流读取的超时时间
|
||||||
|
int COMPLETE_THREAD_NUM = 0;
|
||||||
|
int THREAD_NUM = 3;
|
||||||
|
long CURRENT_LOCATION = 0;
|
||||||
|
boolean isDownloading = false;
|
||||||
|
boolean isCancel = false;
|
||||||
|
boolean isStop = false;
|
||||||
|
|
||||||
|
DownloadStateConstance(int num) {
|
||||||
|
THREAD_NUM = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanState() {
|
||||||
|
isCancel = false;
|
||||||
|
isStop = false;
|
||||||
|
isDownloading = true;
|
||||||
|
CURRENT_LOCATION = 0;
|
||||||
|
CANCEL_NUM = 0;
|
||||||
|
STOP_NUM = 0;
|
||||||
|
FAIL_NUM = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有子线程是否都已经停止下载
|
||||||
|
*/
|
||||||
|
boolean isStop() {
|
||||||
|
return STOP_NUM == THREAD_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有子线程是否都已经下载失败
|
||||||
|
*/
|
||||||
|
boolean isFail() {
|
||||||
|
return FAIL_NUM == THREAD_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有子线程是否都已经完成下载
|
||||||
|
*/
|
||||||
|
boolean isComplete() {
|
||||||
|
return COMPLETE_THREAD_NUM == THREAD_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有子线程是否都已经取消下载
|
||||||
|
*/
|
||||||
|
boolean isCancel() {
|
||||||
|
return CANCEL_NUM == THREAD_NUM;
|
||||||
|
}
|
||||||
|
}
|
@ -20,24 +20,15 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import com.arialyy.aria.core.DownloadEntity;
|
import com.arialyy.aria.core.DownloadEntity;
|
||||||
import com.arialyy.aria.util.CAConfiguration;
|
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.aria.util.SSLContextUtil;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.ProtocolException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2015/8/25.
|
* Created by lyy on 2015/8/25.
|
||||||
@ -45,7 +36,6 @@ import javax.net.ssl.SSLSocketFactory;
|
|||||||
*/
|
*/
|
||||||
final class DownloadUtil implements IDownloadUtil, Runnable {
|
final class DownloadUtil implements IDownloadUtil, Runnable {
|
||||||
private static final String TAG = "DownloadUtil";
|
private static final String TAG = "DownloadUtil";
|
||||||
private static final Object LOCK = new Object();
|
|
||||||
/**
|
/**
|
||||||
* 线程数
|
* 线程数
|
||||||
*/
|
*/
|
||||||
@ -54,25 +44,15 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
private IDownloadListener mListener;
|
private IDownloadListener mListener;
|
||||||
private int mConnectTimeOut = 5000 * 4; //连接超时时间
|
private int mConnectTimeOut = 5000 * 4; //连接超时时间
|
||||||
private int mReadTimeOut = 5000 * 20; //流读取的超时时间
|
private int mReadTimeOut = 5000 * 20; //流读取的超时时间
|
||||||
/**
|
|
||||||
* 已经完成下载任务的线程数量
|
|
||||||
*/
|
|
||||||
private boolean isDownloading = false;
|
|
||||||
private boolean isStop = false;
|
|
||||||
private boolean isCancel = false;
|
|
||||||
private boolean isNewTask = true;
|
private boolean isNewTask = true;
|
||||||
private boolean isSupportBreakpoint = true;
|
private boolean isSupportBreakpoint = true;
|
||||||
private int mCompleteThreadNum = 0;
|
|
||||||
private int mCancelNum = 0;
|
|
||||||
private long mCurrentLocation = 0;
|
|
||||||
private int mStopNum = 0;
|
|
||||||
private int mFailNum = 0;
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private DownloadEntity mDownloadEntity;
|
private DownloadEntity mDownloadEntity;
|
||||||
private ExecutorService mFixedThreadPool;
|
private ExecutorService mFixedThreadPool;
|
||||||
private File mDownloadFile; //下载的文件
|
private File mDownloadFile; //下载的文件
|
||||||
private File mConfigFile;//下载信息配置文件
|
private File mConfigFile;//下载信息配置文件
|
||||||
private SparseArray<Runnable> mTask = new SparseArray<>();
|
private SparseArray<Runnable> mTask = new SparseArray<>();
|
||||||
|
private DownloadStateConstance mConstance;
|
||||||
|
|
||||||
DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) {
|
DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) {
|
||||||
this(context, entity, downloadListener, 3);
|
this(context, entity, downloadListener, 3);
|
||||||
@ -85,6 +65,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
mListener = downloadListener;
|
mListener = downloadListener;
|
||||||
THREAD_NUM = threadNum;
|
THREAD_NUM = threadNum;
|
||||||
mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE);
|
mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE);
|
||||||
|
mConstance = new DownloadStateConstance(THREAD_NUM);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,19 +109,19 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
* 获取当前下载位置
|
* 获取当前下载位置
|
||||||
*/
|
*/
|
||||||
@Override public long getCurrentLocation() {
|
@Override public long getCurrentLocation() {
|
||||||
return mCurrentLocation;
|
return mConstance.CURRENT_LOCATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isDownloading() {
|
@Override public boolean isDownloading() {
|
||||||
return isDownloading;
|
return mConstance.isDownloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
@Override public void cancelDownload() {
|
@Override public void cancelDownload() {
|
||||||
isCancel = true;
|
mConstance.isCancel = true;
|
||||||
isDownloading = false;
|
mConstance.isDownloading = false;
|
||||||
mFixedThreadPool.shutdown();
|
mFixedThreadPool.shutdown();
|
||||||
for (int i = 0; i < THREAD_NUM; i++) {
|
for (int i = 0; i < THREAD_NUM; i++) {
|
||||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||||
@ -154,8 +135,8 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
* 停止下载
|
* 停止下载
|
||||||
*/
|
*/
|
||||||
@Override public void stopDownload() {
|
@Override public void stopDownload() {
|
||||||
isStop = true;
|
mConstance.isStop = true;
|
||||||
isDownloading = false;
|
mConstance.isDownloading = false;
|
||||||
mFixedThreadPool.shutdown();
|
mFixedThreadPool.shutdown();
|
||||||
for (int i = 0; i < THREAD_NUM; i++) {
|
for (int i = 0; i < THREAD_NUM; i++) {
|
||||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||||
@ -195,13 +176,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
* 多线程断点续传下载文件,开始下载
|
* 多线程断点续传下载文件,开始下载
|
||||||
*/
|
*/
|
||||||
@Override public void startDownload() {
|
@Override public void startDownload() {
|
||||||
isDownloading = true;
|
mConstance.cleanState();
|
||||||
mCurrentLocation = 0;
|
|
||||||
isStop = false;
|
|
||||||
isCancel = false;
|
|
||||||
mCancelNum = 0;
|
|
||||||
mStopNum = 0;
|
|
||||||
mFailNum = 0;
|
|
||||||
mListener.onPre();
|
mListener.onPre();
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
}
|
}
|
||||||
@ -212,25 +187,16 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
|
|
||||||
private void failDownload(String msg) {
|
private void failDownload(String msg) {
|
||||||
Log.e(TAG, msg);
|
Log.e(TAG, msg);
|
||||||
isDownloading = false;
|
mConstance.isDownloading = false;
|
||||||
stopDownload();
|
stopDownload();
|
||||||
mListener.onFail();
|
mListener.onFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setConnectParam(HttpURLConnection conn) throws ProtocolException {
|
|
||||||
conn.setRequestMethod("GET");
|
|
||||||
conn.setRequestProperty("Charset", "UTF-8");
|
|
||||||
conn.setRequestProperty("User-Agent",
|
|
||||||
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
|
|
||||||
conn.setRequestProperty("Accept",
|
|
||||||
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
try {
|
try {
|
||||||
URL url = new URL(mDownloadEntity.getDownloadUrl());
|
URL url = new URL(mDownloadEntity.getDownloadUrl());
|
||||||
HttpURLConnection conn = handleConnection(url);
|
HttpURLConnection conn = ConnectionHelp.handleConnection(url);
|
||||||
setConnectParam(conn);
|
conn = ConnectionHelp.setConnectParam(conn);
|
||||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||||
conn.setConnectTimeout(mConnectTimeOut * 4);
|
conn.setConnectTimeout(mConnectTimeOut * 4);
|
||||||
conn.connect();
|
conn.connect();
|
||||||
@ -269,44 +235,23 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理链接
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private HttpURLConnection handleConnection(URL url) throws IOException {
|
|
||||||
HttpURLConnection conn;
|
|
||||||
URLConnection urlConn = url.openConnection();
|
|
||||||
if (urlConn instanceof HttpsURLConnection) {
|
|
||||||
conn = (HttpsURLConnection) urlConn;
|
|
||||||
SSLContext sslContext =
|
|
||||||
SSLContextUtil.getSSLContext(CAConfiguration.CA_ALIAS, CAConfiguration.CA_ALIAS);
|
|
||||||
if (sslContext == null) {
|
|
||||||
sslContext = SSLContextUtil.getDefaultSLLContext();
|
|
||||||
}
|
|
||||||
SSLSocketFactory ssf = sslContext.getSocketFactory();
|
|
||||||
((HttpsURLConnection) conn).setSSLSocketFactory(ssf);
|
|
||||||
((HttpsURLConnection) conn).setHostnameVerifier(SSLContextUtil.HOSTNAME_VERIFIER);
|
|
||||||
} else {
|
|
||||||
conn = (HttpURLConnection) urlConn;
|
|
||||||
}
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理断点
|
* 处理断点
|
||||||
*/
|
*/
|
||||||
private void handleBreakpoint(HttpURLConnection conn) throws IOException {
|
private void handleBreakpoint(HttpURLConnection conn) throws IOException {
|
||||||
|
|
||||||
//不支持断点只能单线程下载
|
//不支持断点只能单线程下载
|
||||||
if (!isSupportBreakpoint) {
|
if (!isSupportBreakpoint) {
|
||||||
ConfigEntity entity = new ConfigEntity();
|
ConfigEntity entity = new ConfigEntity();
|
||||||
entity.fileSize = conn.getContentLength();
|
entity.FILE_SIZE = conn.getContentLength();
|
||||||
entity.downloadUrl = mDownloadEntity.getDownloadUrl();
|
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
|
||||||
entity.tempFile = mDownloadFile;
|
entity.TEMP_FILE = mDownloadFile;
|
||||||
entity.threadId = 0;
|
entity.THREAD_ID = 0;
|
||||||
entity.startLocation = 0;
|
entity.START_LOCATION = 0;
|
||||||
entity.endLocation = entity.fileSize;
|
entity.END_LOCATION = entity.FILE_SIZE;
|
||||||
SingleThreadTask task = new SingleThreadTask(entity);
|
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||||
|
entity.isSupportBreakpoint = isSupportBreakpoint;
|
||||||
|
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
|
||||||
mFixedThreadPool.execute(task);
|
mFixedThreadPool.execute(task);
|
||||||
mListener.onStart(0);
|
mListener.onStart(0);
|
||||||
return;
|
return;
|
||||||
@ -345,17 +290,17 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||||
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
|
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
|
||||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||||
mCurrentLocation += endL - startL;
|
mConstance.CURRENT_LOCATION += endL - startL;
|
||||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||||
mCompleteThreadNum++;
|
mConstance.COMPLETE_THREAD_NUM++;
|
||||||
mStopNum++;
|
mConstance.STOP_NUM++;
|
||||||
mCancelNum++;
|
mConstance.CANCEL_NUM++;
|
||||||
if (mCompleteThreadNum == THREAD_NUM) {
|
if (mConstance.isComplete()) {
|
||||||
if (mConfigFile.exists()) {
|
if (mConfigFile.exists()) {
|
||||||
mConfigFile.delete();
|
mConfigFile.delete();
|
||||||
}
|
}
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
isDownloading = false;
|
mConstance.isDownloading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -365,7 +310,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
//如果有记录,则恢复下载
|
//如果有记录,则恢复下载
|
||||||
if (!isNewTask && record != null && Long.parseLong(record + "") > 0) {
|
if (!isNewTask && record != null && Long.parseLong(record + "") > 0) {
|
||||||
Long r = Long.parseLong(record + "");
|
Long r = Long.parseLong(record + "");
|
||||||
mCurrentLocation += r - startL;
|
mConstance.CURRENT_LOCATION += r - startL;
|
||||||
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
|
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
|
||||||
mListener.onChildResume(r);
|
mListener.onChildResume(r);
|
||||||
startL = r;
|
startL = r;
|
||||||
@ -383,19 +328,21 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
endL = fileLength;
|
endL = fileLength;
|
||||||
}
|
}
|
||||||
ConfigEntity entity = new ConfigEntity();
|
ConfigEntity entity = new ConfigEntity();
|
||||||
entity.fileSize = fileLength;
|
entity.FILE_SIZE = fileLength;
|
||||||
entity.downloadUrl = mDownloadEntity.getDownloadUrl();
|
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
|
||||||
entity.tempFile = mDownloadFile;
|
entity.TEMP_FILE = mDownloadFile;
|
||||||
entity.threadId = i;
|
entity.THREAD_ID = i;
|
||||||
entity.startLocation = startL;
|
entity.START_LOCATION = startL;
|
||||||
entity.endLocation = endL;
|
entity.END_LOCATION = endL;
|
||||||
SingleThreadTask task = new SingleThreadTask(entity);
|
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||||
|
entity.isSupportBreakpoint = isSupportBreakpoint;
|
||||||
|
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
|
||||||
mTask.put(i, task);
|
mTask.put(i, task);
|
||||||
}
|
}
|
||||||
if (mCurrentLocation > 0) {
|
if (mConstance.CURRENT_LOCATION > 0) {
|
||||||
mListener.onResume(mCurrentLocation);
|
mListener.onResume(mConstance.CURRENT_LOCATION);
|
||||||
} else {
|
} else {
|
||||||
mListener.onStart(mCurrentLocation);
|
mListener.onStart(mConstance.CURRENT_LOCATION);
|
||||||
}
|
}
|
||||||
for (int l : recordL) {
|
for (int l : recordL) {
|
||||||
if (l == -1) continue;
|
if (l == -1) continue;
|
||||||
@ -409,229 +356,15 @@ final class DownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
/**
|
/**
|
||||||
* 子线程下载信息类
|
* 子线程下载信息类
|
||||||
*/
|
*/
|
||||||
private static class ConfigEntity {
|
final static class ConfigEntity {
|
||||||
//文件大小
|
//文件大小
|
||||||
long fileSize;
|
long FILE_SIZE;
|
||||||
String downloadUrl;
|
String DOWNLOAD_URL;
|
||||||
int threadId;
|
int THREAD_ID;
|
||||||
long startLocation;
|
long START_LOCATION;
|
||||||
long endLocation;
|
long END_LOCATION;
|
||||||
File tempFile;
|
File TEMP_FILE;
|
||||||
}
|
boolean isSupportBreakpoint = true;
|
||||||
|
String CONFIG_FILE_PATH;
|
||||||
/**
|
|
||||||
* 单个线程的下载任务
|
|
||||||
*/
|
|
||||||
private class SingleThreadTask implements Runnable {
|
|
||||||
private static final String TAG = "SingleThreadTask";
|
|
||||||
private ConfigEntity configEntity;
|
|
||||||
private String configFPath;
|
|
||||||
private long currentLocation = 0;
|
|
||||||
|
|
||||||
private SingleThreadTask(ConfigEntity downloadInfo) {
|
|
||||||
this.configEntity = downloadInfo;
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
configFPath = mContext.getFilesDir().getPath()
|
|
||||||
+ "/temp/"
|
|
||||||
+ configEntity.tempFile.getName()
|
|
||||||
+ ".properties";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void run() {
|
|
||||||
HttpURLConnection conn = null;
|
|
||||||
InputStream is = null;
|
|
||||||
try {
|
|
||||||
URL url = new URL(configEntity.downloadUrl);
|
|
||||||
//conn = (HttpURLConnection) url.openConnection();
|
|
||||||
conn = handleConnection(url);
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
Log.d(TAG, "线程_"
|
|
||||||
+ configEntity.threadId
|
|
||||||
+ "_正在下载【开始位置 : "
|
|
||||||
+ configEntity.startLocation
|
|
||||||
+ ",结束位置:"
|
|
||||||
+ configEntity.endLocation
|
|
||||||
+ "】");
|
|
||||||
//在头里面请求下载开始位置和结束位置
|
|
||||||
conn.setRequestProperty("Range",
|
|
||||||
"bytes=" + configEntity.startLocation + "-" + configEntity.endLocation);
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "该下载不支持断点,即将重新下载");
|
|
||||||
}
|
|
||||||
setConnectParam(conn);
|
|
||||||
conn.setConnectTimeout(mConnectTimeOut);
|
|
||||||
conn.setReadTimeout(mReadTimeOut); //设置读取流的等待时间,必须设置该参数
|
|
||||||
is = conn.getInputStream();
|
|
||||||
//创建可设置位置的文件
|
|
||||||
RandomAccessFile file = new RandomAccessFile(configEntity.tempFile, "rwd");
|
|
||||||
//设置每条线程写入文件的位置
|
|
||||||
file.seek(configEntity.startLocation);
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
int len;
|
|
||||||
//当前子线程的下载位置
|
|
||||||
currentLocation = configEntity.startLocation;
|
|
||||||
while ((len = is.read(buffer)) != -1) {
|
|
||||||
if (isCancel) {
|
|
||||||
Log.d(TAG, "++++++++++ thread_" + configEntity.threadId + "_cancel ++++++++++");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (isStop) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//把下载数据数据写入文件
|
|
||||||
file.write(buffer, 0, len);
|
|
||||||
progress(len);
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
//close 为阻塞的,需要使用线程池来处理
|
|
||||||
is.close();
|
|
||||||
conn.disconnect();
|
|
||||||
|
|
||||||
if (isCancel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//停止状态不需要删除记录文件
|
|
||||||
if (isStop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//支持断点的处理
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
Log.i(TAG, "线程【" + configEntity.threadId + "】下载完毕");
|
|
||||||
writeConfig(configEntity.tempFile.getName() + "_state_" + configEntity.threadId, 1 + "");
|
|
||||||
mListener.onChildComplete(configEntity.endLocation);
|
|
||||||
mCompleteThreadNum++;
|
|
||||||
if (mCompleteThreadNum == THREAD_NUM) {
|
|
||||||
File configFile = new File(configFPath);
|
|
||||||
if (configFile.exists()) {
|
|
||||||
configFile.delete();
|
|
||||||
}
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onComplete();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.i(TAG, "下载任务完成");
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onComplete();
|
|
||||||
}
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
mFailNum++;
|
|
||||||
failDownload(configEntity, currentLocation, "下载链接异常", e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
mFailNum++;
|
|
||||||
failDownload(configEntity, currentLocation, "下载失败【" + configEntity.downloadUrl + "】", e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
mFailNum++;
|
|
||||||
failDownload(configEntity, currentLocation, "获取流失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止下载
|
|
||||||
*/
|
|
||||||
protected void stop() {
|
|
||||||
synchronized (LOCK) {
|
|
||||||
try {
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
mStopNum++;
|
|
||||||
String location = String.valueOf(currentLocation);
|
|
||||||
Log.i(TAG,
|
|
||||||
"thread_" + configEntity.threadId + "_stop, stop location ==> " + currentLocation);
|
|
||||||
writeConfig(configEntity.tempFile.getName() + "_record_" + configEntity.threadId,
|
|
||||||
location);
|
|
||||||
if (mStopNum == THREAD_NUM) {
|
|
||||||
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onStop(mCurrentLocation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onStop(mCurrentLocation);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下载中
|
|
||||||
*/
|
|
||||||
private void progress(long len) {
|
|
||||||
synchronized (LOCK) {
|
|
||||||
currentLocation += len;
|
|
||||||
mCurrentLocation += len;
|
|
||||||
mListener.onProgress(mCurrentLocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消下载
|
|
||||||
*/
|
|
||||||
private void cancel() {
|
|
||||||
synchronized (LOCK) {
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
mCancelNum++;
|
|
||||||
if (mCancelNum == THREAD_NUM) {
|
|
||||||
File configFile = new File(configFPath);
|
|
||||||
if (configFile.exists()) {
|
|
||||||
configFile.delete();
|
|
||||||
}
|
|
||||||
if (configEntity.tempFile.exists()) {
|
|
||||||
configEntity.tempFile.delete();
|
|
||||||
}
|
|
||||||
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onCancel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
|
||||||
isDownloading = false;
|
|
||||||
mListener.onCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下载失败
|
|
||||||
*/
|
|
||||||
private void failDownload(ConfigEntity dEntity, long currentLocation, String msg,
|
|
||||||
Exception ex) {
|
|
||||||
synchronized (LOCK) {
|
|
||||||
try {
|
|
||||||
isDownloading = false;
|
|
||||||
isStop = true;
|
|
||||||
if (ex != null) {
|
|
||||||
Log.e(TAG, CommonUtil.getPrintException(ex));
|
|
||||||
}
|
|
||||||
if (isSupportBreakpoint) {
|
|
||||||
if (currentLocation != -1) {
|
|
||||||
String location = String.valueOf(currentLocation);
|
|
||||||
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
|
||||||
}
|
|
||||||
if (mFailNum == THREAD_NUM) {
|
|
||||||
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
|
||||||
mListener.onFail();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
|
||||||
mListener.onFail();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将记录写入到配置文件
|
|
||||||
*/
|
|
||||||
private void writeConfig(String key, String record) throws IOException {
|
|
||||||
File configFile = new File(configFPath);
|
|
||||||
Properties pro = CommonUtil.loadConfig(configFile);
|
|
||||||
pro.setProperty(key, record);
|
|
||||||
CommonUtil.saveConfig(configFile, pro);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
*
|
||||||
|
* 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.arialyy.aria.core.task;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lyy on 2017/1/18.
|
||||||
|
* 下载线程
|
||||||
|
*/
|
||||||
|
final class SingleThreadTask implements Runnable {
|
||||||
|
private static final String TAG = "SingleThreadTask";
|
||||||
|
private DownloadUtil.ConfigEntity mConfigEntity;
|
||||||
|
private String mConfigFPath;
|
||||||
|
private long mChildCurrentLocation = 0;
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
private IDownloadListener mListener;
|
||||||
|
private DownloadStateConstance mConstance;
|
||||||
|
|
||||||
|
SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener,
|
||||||
|
DownloadUtil.ConfigEntity downloadInfo) {
|
||||||
|
mConstance = constance;
|
||||||
|
mListener = listener;
|
||||||
|
this.mConfigEntity = downloadInfo;
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
mConfigFPath = downloadInfo.CONFIG_FILE_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
HttpURLConnection conn = null;
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(mConfigEntity.DOWNLOAD_URL);
|
||||||
|
//conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn = ConnectionHelp.handleConnection(url);
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
Log.d(TAG, "线程_"
|
||||||
|
+ mConfigEntity.THREAD_ID
|
||||||
|
+ "_正在下载【开始位置 : "
|
||||||
|
+ mConfigEntity.START_LOCATION
|
||||||
|
+ ",结束位置:"
|
||||||
|
+ mConfigEntity.END_LOCATION
|
||||||
|
+ "】");
|
||||||
|
//在头里面请求下载开始位置和结束位置
|
||||||
|
conn.setRequestProperty("Range",
|
||||||
|
"bytes=" + mConfigEntity.START_LOCATION + "-" + mConfigEntity.END_LOCATION);
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "该下载不支持断点,即将重新下载");
|
||||||
|
}
|
||||||
|
conn = ConnectionHelp.setConnectParam(conn);
|
||||||
|
conn.setConnectTimeout(mConstance.CONNECT_TIME_OUT);
|
||||||
|
conn.setReadTimeout(mConstance.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
|
||||||
|
is = conn.getInputStream();
|
||||||
|
//创建可设置位置的文件
|
||||||
|
RandomAccessFile file = new RandomAccessFile(mConfigEntity.TEMP_FILE, "rwd");
|
||||||
|
//设置每条线程写入文件的位置
|
||||||
|
file.seek(mConfigEntity.START_LOCATION);
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int len;
|
||||||
|
//当前子线程的下载位置
|
||||||
|
mChildCurrentLocation = mConfigEntity.START_LOCATION;
|
||||||
|
while ((len = is.read(buffer)) != -1) {
|
||||||
|
if (mConstance.isCancel) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mConstance.isStop) {
|
||||||
|
Log.i(TAG, "stop");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//把下载数据数据写入文件
|
||||||
|
file.write(buffer, 0, len);
|
||||||
|
progress(len);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
//close 为阻塞的,需要使用线程池来处理
|
||||||
|
is.close();
|
||||||
|
conn.disconnect();
|
||||||
|
if (mConstance.isCancel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//停止状态不需要删除记录文件
|
||||||
|
if (mConstance.isStop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//支持断点的处理
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
Log.i(TAG, "线程【" + mConfigEntity.THREAD_ID + "】下载完毕");
|
||||||
|
writeConfig(mConfigEntity.TEMP_FILE.getName() + "_state_" + mConfigEntity.THREAD_ID,
|
||||||
|
1 + "");
|
||||||
|
mListener.onChildComplete(mConfigEntity.END_LOCATION);
|
||||||
|
mConstance.COMPLETE_THREAD_NUM++;
|
||||||
|
if (mConstance.isComplete()) {
|
||||||
|
File configFile = new File(mConfigFPath);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
configFile.delete();
|
||||||
|
}
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onComplete();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "下载任务完成");
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onComplete();
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
mConstance.FAIL_NUM++;
|
||||||
|
failDownload(mConfigEntity, mChildCurrentLocation, "下载链接异常", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
mConstance.FAIL_NUM++;
|
||||||
|
failDownload(mConfigEntity, mChildCurrentLocation, "下载失败【" + mConfigEntity.DOWNLOAD_URL + "】",
|
||||||
|
e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
mConstance.FAIL_NUM++;
|
||||||
|
failDownload(mConfigEntity, mChildCurrentLocation, "获取流失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止下载
|
||||||
|
*/
|
||||||
|
protected void stop() {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
try {
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
mConstance.STOP_NUM++;
|
||||||
|
String location = String.valueOf(mChildCurrentLocation);
|
||||||
|
Log.d(TAG, "thread_"
|
||||||
|
+ mConfigEntity.THREAD_ID
|
||||||
|
+ "_stop, stop location ==> "
|
||||||
|
+ mChildCurrentLocation);
|
||||||
|
writeConfig(mConfigEntity.TEMP_FILE.getName() + "_record_" + mConfigEntity.THREAD_ID,
|
||||||
|
location);
|
||||||
|
if (mConstance.isStop()) {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onStop(mConstance.CURRENT_LOCATION);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onStop(mConstance.CURRENT_LOCATION);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载中
|
||||||
|
*/
|
||||||
|
private void progress(long len) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
mChildCurrentLocation += len;
|
||||||
|
mConstance.CURRENT_LOCATION += len;
|
||||||
|
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消下载
|
||||||
|
*/
|
||||||
|
protected void cancel() {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
mConstance.CANCEL_NUM++;
|
||||||
|
Log.d(TAG, "++++++++++ thread_" + mConfigEntity.THREAD_ID + "_cancel ++++++++++");
|
||||||
|
if (mConstance.isCancel()) {
|
||||||
|
File configFile = new File(mConfigFPath);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
configFile.delete();
|
||||||
|
}
|
||||||
|
if (mConfigEntity.TEMP_FILE.exists()) {
|
||||||
|
mConfigEntity.TEMP_FILE.delete();
|
||||||
|
}
|
||||||
|
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onCancel();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mListener.onCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载失败
|
||||||
|
*/
|
||||||
|
private void failDownload(DownloadUtil.ConfigEntity dEntity, long currentLocation, String msg,
|
||||||
|
Exception ex) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
try {
|
||||||
|
mConstance.isDownloading = false;
|
||||||
|
mConstance.isStop = true;
|
||||||
|
if (ex != null) {
|
||||||
|
Log.e(TAG, CommonUtil.getPrintException(ex));
|
||||||
|
}
|
||||||
|
if (mConfigEntity.isSupportBreakpoint) {
|
||||||
|
if (currentLocation != -1) {
|
||||||
|
String location = String.valueOf(currentLocation);
|
||||||
|
writeConfig(dEntity.TEMP_FILE.getName() + "_record_" + dEntity.THREAD_ID, location);
|
||||||
|
}
|
||||||
|
if (mConstance.isFail()) {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
||||||
|
mListener.onFail();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
||||||
|
mListener.onFail();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将记录写入到配置文件
|
||||||
|
*/
|
||||||
|
private void writeConfig(String key, String record) throws IOException {
|
||||||
|
File configFile = new File(mConfigFPath);
|
||||||
|
Properties pro = CommonUtil.loadConfig(configFile);
|
||||||
|
pro.setProperty(key, record);
|
||||||
|
CommonUtil.saveConfig(configFile, pro);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.arialyy.aria.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Aria.Lao on 2017/1/18.
|
||||||
|
* Aria 文件异常
|
||||||
|
*/
|
||||||
|
public class FileException extends NullPointerException {
|
||||||
|
private static final String ARIA_FILE_EXCEPTION = "Aria Exception:";
|
||||||
|
|
||||||
|
public FileException(String detailMessage) {
|
||||||
|
super(ARIA_FILE_EXCEPTION + detailMessage);
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ package com.arialyy.aria.util;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.DownloadEntity;
|
import com.arialyy.aria.core.DownloadEntity;
|
||||||
|
import com.arialyy.aria.exception.FileException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -80,9 +81,9 @@ public class CheckUtil {
|
|||||||
return false;
|
return false;
|
||||||
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
||||||
//Log.w(TAG, "文件名不能为空");
|
//Log.w(TAG, "文件名不能为空");
|
||||||
throw new IllegalArgumentException("文件名不能为null");
|
throw new FileException("文件名不能为null");
|
||||||
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
|
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
|
||||||
throw new IllegalArgumentException("文件保存路径不能为null");
|
throw new FileException("文件保存路径不能为null");
|
||||||
}
|
}
|
||||||
String fileName = entity.getFileName();
|
String fileName = entity.getFileName();
|
||||||
if (fileName.contains(" ")) {
|
if (fileName.contains(" ")) {
|
||||||
|
@ -67,7 +67,6 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
|
|||||||
Set<String> keys = mBtStates.keySet();
|
Set<String> keys = mBtStates.keySet();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
if (key.equals(downloadUrl)) {
|
if (key.equals(downloadUrl)) {
|
||||||
Log.d(TAG, "able ==> " + able);
|
|
||||||
mBtStates.put(downloadUrl, able);
|
mBtStates.put(downloadUrl, able);
|
||||||
notifyItemChanged(indexItem(downloadUrl));
|
notifyItemChanged(indexItem(downloadUrl));
|
||||||
return;
|
return;
|
||||||
@ -80,7 +79,7 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
|
|||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
if (key.equals(url)) {
|
if (key.equals(url)) {
|
||||||
int index = mPositions.get(key);
|
int index = mPositions.get(key);
|
||||||
Log.d(TAG, "index ==> " + index);
|
//Log.d(TAG, "index ==> " + index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user