ftp断点上传
This commit is contained in:
@ -43,7 +43,7 @@ import com.arialyy.aria.core.upload.UploadTask;
|
|||||||
* <code>
|
* <code>
|
||||||
* //下载
|
* //下载
|
||||||
* Aria.download(this)
|
* Aria.download(this)
|
||||||
* .load(DOWNLOAD_URL) //下载地址,必填
|
* .load(URL) //下载地址,必填
|
||||||
* //文件保存路径,必填
|
* //文件保存路径,必填
|
||||||
* .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
* .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
||||||
* .start();
|
* .start();
|
||||||
|
@ -28,6 +28,7 @@ import android.support.v4.app.Fragment;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.PopupWindow;
|
import android.widget.PopupWindow;
|
||||||
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.aria.core.download.DownloadReceiver;
|
import com.arialyy.aria.core.download.DownloadReceiver;
|
||||||
import com.arialyy.aria.core.command.ICmd;
|
import com.arialyy.aria.core.command.ICmd;
|
||||||
import com.arialyy.aria.core.inf.IReceiver;
|
import com.arialyy.aria.core.inf.IReceiver;
|
||||||
@ -88,7 +89,7 @@ import org.xml.sax.SAXException;
|
|||||||
/**
|
/**
|
||||||
* 设置上传任务的执行队列类型
|
* 设置上传任务的执行队列类型
|
||||||
*
|
*
|
||||||
* @param mod {@link com.arialyy.aria.core.QueueMod}
|
* @param mod {@link QueueMod}
|
||||||
*/
|
*/
|
||||||
public AriaManager setUploadQueueMod(QueueMod mod) {
|
public AriaManager setUploadQueueMod(QueueMod mod) {
|
||||||
mUConfig.setQueueMod(mod.tag);
|
mUConfig.setQueueMod(mod.tag);
|
||||||
@ -98,7 +99,7 @@ import org.xml.sax.SAXException;
|
|||||||
/**
|
/**
|
||||||
* 设置下载任务的执行队列类型
|
* 设置下载任务的执行队列类型
|
||||||
*
|
*
|
||||||
* @param mod {@link com.arialyy.aria.core.QueueMod}
|
* @param mod {@link QueueMod}
|
||||||
*/
|
*/
|
||||||
public AriaManager setDownloadQueueMod(QueueMod mod) {
|
public AriaManager setDownloadQueueMod(QueueMod mod) {
|
||||||
mDConfig.setQueueMod(mod.tag);
|
mDConfig.setQueueMod(mod.tag);
|
||||||
|
@ -17,7 +17,7 @@ package com.arialyy.aria.core.command.group;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.QueueMod;
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.aria.core.inf.AbsGroupTask;
|
import com.arialyy.aria.core.inf.AbsGroupTask;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
|
@ -18,7 +18,7 @@ package com.arialyy.aria.core.command.normal;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.QueueMod;
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.aria.core.inf.AbsTask;
|
import com.arialyy.aria.core.inf.AbsTask;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
395
Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
Normal file
395
Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* 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.common;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import com.arialyy.aria.core.AriaManager;
|
||||||
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by AriaL on 2017/7/1.
|
||||||
|
* 文件下载器
|
||||||
|
*/
|
||||||
|
public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>>
|
||||||
|
implements Runnable, IUtil {
|
||||||
|
private final String TAG = "Downloader";
|
||||||
|
protected IEventListener mListener;
|
||||||
|
protected TASK_ENTITY mTaskEntity;
|
||||||
|
protected ENTITY mEntity;
|
||||||
|
protected File mConfigFile;//信息配置文件
|
||||||
|
protected Context mContext;
|
||||||
|
protected File mTempFile; //下载的文件
|
||||||
|
protected boolean isNewTask = true;
|
||||||
|
protected StateConstance mConstance;
|
||||||
|
private ExecutorService mFixedThreadPool;
|
||||||
|
private int mThreadNum, mRealThreadNum;
|
||||||
|
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小于1m的文件不启用多线程
|
||||||
|
*/
|
||||||
|
private static final long SUB_LEN = 1024 * 1024;
|
||||||
|
private Timer mTimer;
|
||||||
|
|
||||||
|
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
||||||
|
mListener = listener;
|
||||||
|
mTaskEntity = taskEntity;
|
||||||
|
mEntity = mTaskEntity.getEntity();
|
||||||
|
mContext = AriaManager.APP;
|
||||||
|
mConstance = new StateConstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setMaxSpeed(double maxSpeed) {
|
||||||
|
for (int i = 0; i < mThreadNum; i++) {
|
||||||
|
AbsThreadTask task = mTask.get(i);
|
||||||
|
if (task != null) {
|
||||||
|
task.setMaxSpeed(maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StateConstance getConstance() {
|
||||||
|
return mConstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
startFlow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始下载流程
|
||||||
|
*/
|
||||||
|
private void startFlow() {
|
||||||
|
checkTask();
|
||||||
|
if (mListener instanceof IDownloadListener) {
|
||||||
|
((IDownloadListener) mListener).onPostPre(mEntity.getFileSize());
|
||||||
|
}
|
||||||
|
mConstance.cleanState();
|
||||||
|
mConstance.isRunning = true;
|
||||||
|
if (!mTaskEntity.isSupportBP) {
|
||||||
|
mThreadNum = 1;
|
||||||
|
mConstance.THREAD_NUM = mThreadNum;
|
||||||
|
handleNoSupportBP();
|
||||||
|
} else {
|
||||||
|
mThreadNum = isNewTask ? (getThreadNum()) : mRealThreadNum;
|
||||||
|
mConstance.THREAD_NUM = mThreadNum;
|
||||||
|
mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum);
|
||||||
|
handleBreakpoint();
|
||||||
|
}
|
||||||
|
startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线程数
|
||||||
|
*/
|
||||||
|
protected int getThreadNum() {
|
||||||
|
return mEntity.getFileSize() <= SUB_LEN || mTaskEntity.requestType == AbsTaskEntity.FTP_DIR ? 1
|
||||||
|
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动进度获取定时器
|
||||||
|
*/
|
||||||
|
private void startTimer() {
|
||||||
|
mTimer = new Timer(true);
|
||||||
|
mTimer.schedule(new TimerTask() {
|
||||||
|
@Override public void run() {
|
||||||
|
if (mConstance.isComplete() || !mConstance.isRunning) {
|
||||||
|
closeTimer();
|
||||||
|
} else if (mConstance.CURRENT_LOCATION >= 0) {
|
||||||
|
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeTimer() {
|
||||||
|
if (mTimer != null) {
|
||||||
|
mTimer.purge();
|
||||||
|
mTimer.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public long getFileSize() {
|
||||||
|
return mEntity.getFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前下载位置
|
||||||
|
*/
|
||||||
|
@Override public long getCurrentLocation() {
|
||||||
|
return mConstance.CURRENT_LOCATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean isRunning() {
|
||||||
|
return mConstance.isRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void cancel() {
|
||||||
|
closeTimer();
|
||||||
|
mConstance.isCancel = true;
|
||||||
|
mConstance.isRunning = false;
|
||||||
|
if (mFixedThreadPool != null) {
|
||||||
|
mFixedThreadPool.shutdown();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mThreadNum; i++) {
|
||||||
|
AbsThreadTask task = mTask.get(i);
|
||||||
|
if (task != null) {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mTaskEntity instanceof DownloadTaskEntity) {
|
||||||
|
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, (DownloadTaskEntity) mTaskEntity);
|
||||||
|
} else if (mTaskEntity instanceof UploadTaskEntity) {
|
||||||
|
CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile, (UploadTaskEntity) mTaskEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void stop() {
|
||||||
|
closeTimer();
|
||||||
|
if (mConstance.isComplete()) return;
|
||||||
|
mConstance.isStop = true;
|
||||||
|
mConstance.isRunning = false;
|
||||||
|
if (mFixedThreadPool != null) {
|
||||||
|
mFixedThreadPool.shutdown();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mThreadNum; i++) {
|
||||||
|
AbsThreadTask task = mTask.get(i);
|
||||||
|
if (task != null) {
|
||||||
|
task.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接调用的时候会自动启动线程执行
|
||||||
|
*/
|
||||||
|
@Override public void start() {
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void resume() {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回该下载器的
|
||||||
|
*/
|
||||||
|
public IEventListener getListener() {
|
||||||
|
return mListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查任务是否是新任务,新任务条件:
|
||||||
|
* 1、文件不存在
|
||||||
|
* 2、下载记录文件不存在
|
||||||
|
* 3、下载记录文件缺失或不匹配
|
||||||
|
* 4、数据库记录不存在
|
||||||
|
* 5、不支持断点,则是新任务
|
||||||
|
*/
|
||||||
|
protected abstract void checkTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查记录文件,如果是新任务返回{@code true},否则返回{@code false}
|
||||||
|
*/
|
||||||
|
protected boolean checkConfigFile() {
|
||||||
|
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
||||||
|
if (pro.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Set<Object> keys = pro.keySet();
|
||||||
|
int num = 0;
|
||||||
|
for (Object key : keys) {
|
||||||
|
if (String.valueOf(key).contains("_record_")) {
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mRealThreadNum = num;
|
||||||
|
for (int i = 0; i < mRealThreadNum; i++) {
|
||||||
|
if (pro.getProperty(mTempFile.getName() + "_record_" + i) == null) {
|
||||||
|
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
||||||
|
if (state != null && Integer.parseInt(state + "") == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复记录地址
|
||||||
|
*
|
||||||
|
* @return true 表示下载完成
|
||||||
|
*/
|
||||||
|
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
||||||
|
mConstance.CURRENT_LOCATION += endL - startL;
|
||||||
|
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||||
|
mConstance.COMPLETE_THREAD_NUM++;
|
||||||
|
mConstance.STOP_NUM++;
|
||||||
|
mConstance.CANCEL_NUM++;
|
||||||
|
if (mConstance.isComplete()) {
|
||||||
|
if (mConfigFile.exists()) {
|
||||||
|
mConfigFile.delete();
|
||||||
|
}
|
||||||
|
mListener.onComplete();
|
||||||
|
mConstance.isRunning = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动断点任务时,创建单线程任务
|
||||||
|
*
|
||||||
|
* @param i 线程id
|
||||||
|
* @param startL 该任务起始位置
|
||||||
|
* @param endL 该任务结束位置
|
||||||
|
* @param fileLength 该任务需要处理的文件长度
|
||||||
|
*/
|
||||||
|
private AbsThreadTask createSingThreadTask(int i, long startL, long endL, long fileLength) {
|
||||||
|
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
||||||
|
config.FILE_SIZE = fileLength;
|
||||||
|
config.URL = mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getUrl();
|
||||||
|
config.TEMP_FILE = mTempFile;
|
||||||
|
config.THREAD_ID = i;
|
||||||
|
config.START_LOCATION = startL;
|
||||||
|
config.END_LOCATION = endL;
|
||||||
|
config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||||
|
config.SUPPORT_BP = mTaskEntity.isSupportBP;
|
||||||
|
config.TASK_ENTITY = mTaskEntity;
|
||||||
|
return selectThreadTask(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动单线程下载任务
|
||||||
|
*/
|
||||||
|
private void startSingleTask(int[] recordL) {
|
||||||
|
if (mConstance.CURRENT_LOCATION > 0) {
|
||||||
|
mListener.onResume(mConstance.CURRENT_LOCATION);
|
||||||
|
} else {
|
||||||
|
mListener.onStart(mConstance.CURRENT_LOCATION);
|
||||||
|
}
|
||||||
|
mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
|
||||||
|
for (int l : recordL) {
|
||||||
|
if (l == -1) continue;
|
||||||
|
Runnable task = mTask.get(l);
|
||||||
|
if (task != null) {
|
||||||
|
mFixedThreadPool.execute(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理断点
|
||||||
|
*/
|
||||||
|
private void handleBreakpoint() {
|
||||||
|
long fileLength = mEntity.getFileSize();
|
||||||
|
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
||||||
|
int blockSize = (int) (fileLength / mThreadNum);
|
||||||
|
int[] recordL = new int[mThreadNum];
|
||||||
|
for (int i = 0; i < mThreadNum; i++) {
|
||||||
|
recordL[i] = -1;
|
||||||
|
}
|
||||||
|
int rl = 0;
|
||||||
|
if (isNewTask) {
|
||||||
|
handleNewTask();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mThreadNum; i++) {
|
||||||
|
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||||
|
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
||||||
|
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||||
|
if (resumeRecordLocation(i, startL, endL)) return;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//分配下载位置
|
||||||
|
Object record = pro.getProperty(mTempFile.getName() + "_record_" + i);
|
||||||
|
//如果有记录,则恢复下载
|
||||||
|
if (!isNewTask && record != null && Long.parseLong(record + "") >= 0) {
|
||||||
|
Long r = Long.parseLong(record + "");
|
||||||
|
mConstance.CURRENT_LOCATION += r - startL;
|
||||||
|
Log.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
||||||
|
startL = r;
|
||||||
|
recordL[rl] = i;
|
||||||
|
rl++;
|
||||||
|
} else {
|
||||||
|
recordL[rl] = i;
|
||||||
|
rl++;
|
||||||
|
}
|
||||||
|
if (i == (mThreadNum - 1)) {
|
||||||
|
//最后一个线程的结束位置即为文件的总长度
|
||||||
|
endL = fileLength;
|
||||||
|
}
|
||||||
|
AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength);
|
||||||
|
if (task == null) return;
|
||||||
|
mTask.put(i, task);
|
||||||
|
}
|
||||||
|
startSingleTask(recordL);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void handleNewTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理不支持断点的下载
|
||||||
|
*/
|
||||||
|
private void handleNoSupportBP() {
|
||||||
|
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
||||||
|
config.FILE_SIZE = mEntity.getFileSize();
|
||||||
|
config.URL = mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getUrl();
|
||||||
|
config.TEMP_FILE = mTempFile;
|
||||||
|
config.THREAD_ID = 0;
|
||||||
|
config.START_LOCATION = 0;
|
||||||
|
config.END_LOCATION = config.FILE_SIZE;
|
||||||
|
config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||||
|
config.SUPPORT_BP = mTaskEntity.isSupportBP;
|
||||||
|
config.TASK_ENTITY = mTaskEntity;
|
||||||
|
AbsThreadTask task = selectThreadTask(config);
|
||||||
|
if (task == null) return;
|
||||||
|
mTask.put(0, task);
|
||||||
|
mFixedThreadPool.execute(task);
|
||||||
|
mListener.onStart(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择单任务线程的类型
|
||||||
|
*/
|
||||||
|
protected abstract AbsThreadTask selectThreadTask(SubThreadConfig<TASK_ENTITY> config);
|
||||||
|
|
||||||
|
protected void failDownload(String errorMsg) {
|
||||||
|
closeTimer();
|
||||||
|
Log.e(TAG, errorMsg);
|
||||||
|
mConstance.isRunning = false;
|
||||||
|
mListener.onFail();
|
||||||
|
}
|
||||||
|
}
|
@ -13,14 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.inf.AbsEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -31,35 +32,40 @@ import java.util.Properties;
|
|||||||
* Created by lyy on 2017/1/18.
|
* Created by lyy on 2017/1/18.
|
||||||
* 下载线程
|
* 下载线程
|
||||||
*/
|
*/
|
||||||
abstract class AbsThreadTask implements Runnable {
|
public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>>
|
||||||
|
implements Runnable {
|
||||||
private final String TAG = "AbsThreadTask";
|
private final String TAG = "AbsThreadTask";
|
||||||
long mChildCurrentLocation = 0, mSleepTime = 0;
|
protected long mChildCurrentLocation = 0, mSleepTime = 0;
|
||||||
int mBufSize;
|
protected int mBufSize;
|
||||||
String mConfigFPath;
|
protected String mConfigFPath;
|
||||||
SubThreadConfig mConfig;
|
protected IEventListener mListener;
|
||||||
IDownloadListener mListener;
|
protected StateConstance STATE;
|
||||||
StateConstance STATE;
|
protected SubThreadConfig<TASK_ENTITY> mConfig;
|
||||||
DownloadEntity mEntity;
|
protected ENTITY mEntity;
|
||||||
DownloadTaskEntity mTaskEntity;
|
protected TASK_ENTITY mTaskEntity;
|
||||||
|
/**
|
||||||
|
* FTP 服务器编码
|
||||||
|
*/
|
||||||
|
public static String SERVER_CHARSET = "ISO-8859-1";
|
||||||
|
|
||||||
AbsThreadTask(StateConstance constance, IDownloadListener listener,
|
protected AbsThreadTask(StateConstance constance, IEventListener listener,
|
||||||
SubThreadConfig downloadInfo) {
|
SubThreadConfig<TASK_ENTITY> info) {
|
||||||
AriaManager manager = AriaManager.getInstance(AriaManager.APP);
|
AriaManager manager = AriaManager.getInstance(AriaManager.APP);
|
||||||
STATE = constance;
|
STATE = constance;
|
||||||
STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut();
|
STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut();
|
||||||
STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut();
|
STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut();
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
mConfig = downloadInfo;
|
mConfig = info;
|
||||||
mTaskEntity = mConfig.DOWNLOAD_TASK_ENTITY;
|
mTaskEntity = mConfig.TASK_ENTITY;
|
||||||
mEntity = mTaskEntity.getEntity();
|
mEntity = mTaskEntity.getEntity();
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
mConfigFPath = downloadInfo.CONFIG_FILE_PATH;
|
mConfigFPath = info.CONFIG_FILE_PATH;
|
||||||
}
|
}
|
||||||
mBufSize = manager.getDownloadConfig().getBuffSize();
|
mBufSize = manager.getDownloadConfig().getBuffSize();
|
||||||
setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed());
|
setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMaxSpeed(double maxSpeed) {
|
public void setMaxSpeed(double maxSpeed) {
|
||||||
if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
|
if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
|
||||||
mSleepTime = 0;
|
mSleepTime = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -76,10 +82,10 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* 停止下载
|
* 停止下载
|
||||||
*/
|
*/
|
||||||
void stop() {
|
public void stop() {
|
||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
try {
|
try {
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
STATE.STOP_NUM++;
|
STATE.STOP_NUM++;
|
||||||
Log.d(TAG, "任务【"
|
Log.d(TAG, "任务【"
|
||||||
+ mConfig.TEMP_FILE.getName()
|
+ mConfig.TEMP_FILE.getName()
|
||||||
@ -90,12 +96,12 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
writeConfig(false, mChildCurrentLocation);
|
writeConfig(false, mChildCurrentLocation);
|
||||||
if (STATE.isStop()) {
|
if (STATE.isStop()) {
|
||||||
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -107,7 +113,7 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* 下载中
|
* 下载中
|
||||||
*/
|
*/
|
||||||
void progress(long len) {
|
protected void progress(long len) {
|
||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
mChildCurrentLocation += len;
|
mChildCurrentLocation += len;
|
||||||
STATE.CURRENT_LOCATION += len;
|
STATE.CURRENT_LOCATION += len;
|
||||||
@ -117,9 +123,9 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
void cancel() {
|
public void cancel() {
|
||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
STATE.CANCEL_NUM++;
|
STATE.CANCEL_NUM++;
|
||||||
Log.d(TAG,
|
Log.d(TAG,
|
||||||
"任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__取消下载");
|
"任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__取消下载");
|
||||||
@ -132,39 +138,39 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
mConfig.TEMP_FILE.delete();
|
mConfig.TEMP_FILE.delete();
|
||||||
}
|
}
|
||||||
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载失败
|
* 任务失败
|
||||||
*/
|
*/
|
||||||
void failDownload(long currentLocation, String msg, Exception ex) {
|
protected void fail(long currentLocation, String msg, Exception ex) {
|
||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
try {
|
try {
|
||||||
STATE.FAIL_NUM++;
|
STATE.FAIL_NUM++;
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
STATE.isStop = true;
|
STATE.isStop = true;
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex));
|
Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex));
|
||||||
}else {
|
} else {
|
||||||
Log.e(TAG, msg);
|
Log.e(TAG, msg);
|
||||||
}
|
}
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
writeConfig(false, currentLocation);
|
writeConfig(false, currentLocation);
|
||||||
if (STATE.isFail()) {
|
if (STATE.isFail()) {
|
||||||
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】下载失败");
|
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败");
|
||||||
mListener.onFail();
|
mListener.onFail();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】下载失败");
|
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败");
|
||||||
mListener.onFail();
|
mListener.onFail();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -176,7 +182,7 @@ abstract class AbsThreadTask implements Runnable {
|
|||||||
/**
|
/**
|
||||||
* 将记录写入到配置文件
|
* 将记录写入到配置文件
|
||||||
*/
|
*/
|
||||||
void writeConfig(boolean isComplete, long record) throws IOException {
|
protected void writeConfig(boolean isComplete, long record) throws IOException {
|
||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
String key = null, value = null;
|
String key = null, value = null;
|
||||||
if (0 < record && record < mConfig.END_LOCATION) {
|
if (0 < record && record < mConfig.END_LOCATION) {
|
@ -14,13 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2016/10/31.
|
* Created by lyy on 2016/10/31.
|
||||||
* 抽象的下载接口
|
* 抽象的下载接口
|
||||||
*/
|
*/
|
||||||
public interface IDownloadUtil {
|
public interface IUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件大小
|
* 获取文件大小
|
||||||
@ -37,27 +37,27 @@ public interface IDownloadUtil {
|
|||||||
*
|
*
|
||||||
* @return true, 正在下载
|
* @return true, 正在下载
|
||||||
*/
|
*/
|
||||||
boolean isDownloading();
|
boolean isRunning();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
void cancelDownload();
|
void cancel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止下载
|
* 停止下载
|
||||||
*/
|
*/
|
||||||
void stopDownload();
|
void stop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始下载
|
* 开始下载
|
||||||
*/
|
*/
|
||||||
void startDownload();
|
void start();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从上次断点恢复下载
|
* 从上次断点恢复下载
|
||||||
*/
|
*/
|
||||||
void resumeDownload();
|
void resume();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置最大下载速度
|
* 设置最大下载速度
|
@ -13,8 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
@ -1,4 +1,4 @@
|
|||||||
package com.arialyy.aria.core;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/6/21.
|
* Created by Aria.Lao on 2017/6/21.
|
||||||
@ -19,7 +19,7 @@ public enum QueueMod {
|
|||||||
*/
|
*/
|
||||||
NOW("now");
|
NOW("now");
|
||||||
|
|
||||||
String tag;
|
public String tag;
|
||||||
|
|
||||||
public String getTag() {
|
public String getTag() {
|
||||||
return tag;
|
return tag;
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/1/23.
|
* Created by lyy on 2017/1/23.
|
@ -13,32 +13,32 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/1/18.
|
* Created by lyy on 2017/1/18.
|
||||||
* 下载状态常量
|
* 下载状态常量
|
||||||
*/
|
*/
|
||||||
class StateConstance {
|
public class StateConstance {
|
||||||
int CANCEL_NUM = 0;
|
public int CANCEL_NUM = 0;
|
||||||
int STOP_NUM = 0;
|
public int STOP_NUM = 0;
|
||||||
int FAIL_NUM = 0;
|
public int FAIL_NUM = 0;
|
||||||
int CONNECT_TIME_OUT; //连接超时时间
|
public int CONNECT_TIME_OUT; //连接超时时间
|
||||||
int READ_TIME_OUT; //流读取的超时时间
|
public int READ_TIME_OUT; //流读取的超时时间
|
||||||
int COMPLETE_THREAD_NUM = 0;
|
public int COMPLETE_THREAD_NUM = 0;
|
||||||
int THREAD_NUM;
|
public int THREAD_NUM;
|
||||||
long CURRENT_LOCATION = 0;
|
public long CURRENT_LOCATION = 0;
|
||||||
boolean isDownloading = false;
|
public boolean isRunning = false;
|
||||||
boolean isCancel = false;
|
public boolean isCancel = false;
|
||||||
boolean isStop = false;
|
public boolean isStop = false;
|
||||||
|
|
||||||
StateConstance() {
|
public StateConstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanState() {
|
public void cleanState() {
|
||||||
isCancel = false;
|
isCancel = false;
|
||||||
isStop = false;
|
isStop = false;
|
||||||
isDownloading = true;
|
isRunning = true;
|
||||||
CURRENT_LOCATION = 0;
|
CURRENT_LOCATION = 0;
|
||||||
CANCEL_NUM = 0;
|
CANCEL_NUM = 0;
|
||||||
STOP_NUM = 0;
|
STOP_NUM = 0;
|
||||||
@ -48,28 +48,28 @@ class StateConstance {
|
|||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经停止下载
|
* 所有子线程是否都已经停止下载
|
||||||
*/
|
*/
|
||||||
boolean isStop() {
|
public boolean isStop() {
|
||||||
return STOP_NUM == THREAD_NUM;
|
return STOP_NUM == THREAD_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经下载失败
|
* 所有子线程是否都已经下载失败
|
||||||
*/
|
*/
|
||||||
boolean isFail() {
|
public boolean isFail() {
|
||||||
return FAIL_NUM == THREAD_NUM;
|
return FAIL_NUM == THREAD_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经完成下载
|
* 所有子线程是否都已经完成下载
|
||||||
*/
|
*/
|
||||||
boolean isComplete() {
|
public boolean isComplete() {
|
||||||
return COMPLETE_THREAD_NUM == THREAD_NUM;
|
return COMPLETE_THREAD_NUM == THREAD_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经取消下载
|
* 所有子线程是否都已经取消下载
|
||||||
*/
|
*/
|
||||||
boolean isCancel() {
|
public boolean isCancel() {
|
||||||
return CANCEL_NUM == THREAD_NUM;
|
return CANCEL_NUM == THREAD_NUM;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子线程下载信息类
|
||||||
|
*/
|
||||||
|
public class SubThreadConfig<TASK_ENTITY extends AbsTaskEntity> {
|
||||||
|
//线程Id
|
||||||
|
public int THREAD_ID;
|
||||||
|
//下载文件大小
|
||||||
|
public long FILE_SIZE;
|
||||||
|
//子线程启动下载位置
|
||||||
|
public long START_LOCATION;
|
||||||
|
//子线程结束下载位置
|
||||||
|
public long END_LOCATION;
|
||||||
|
//下载文件或上传的文件路径
|
||||||
|
public File TEMP_FILE;
|
||||||
|
//服务器地址
|
||||||
|
public String URL;
|
||||||
|
public String CONFIG_FILE_PATH;
|
||||||
|
public TASK_ENTITY TASK_ENTITY;
|
||||||
|
public boolean SUPPORT_BP = true;
|
||||||
|
}
|
@ -186,8 +186,8 @@ abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends Abs
|
|||||||
List<DownloadEntity> list = new ArrayList<>();
|
List<DownloadEntity> list = new ArrayList<>();
|
||||||
for (int i = 0, len = mUrls.size(); i < len; i++) {
|
for (int i = 0, len = mUrls.size(); i < len; i++) {
|
||||||
DownloadEntity entity = new DownloadEntity();
|
DownloadEntity entity = new DownloadEntity();
|
||||||
entity.setDownloadUrl(mUrls.get(i));
|
entity.setUrl(mUrls.get(i));
|
||||||
String fileName = mSubTaskFileName.isEmpty() ? createFileName(entity.getDownloadUrl())
|
String fileName = mSubTaskFileName.isEmpty() ? createFileName(entity.getUrl())
|
||||||
: mSubTaskFileName.get(i);
|
: mSubTaskFileName.get(i);
|
||||||
entity.setDownloadPath(mEntity.getDirPath() + "/" + fileName);
|
entity.setDownloadPath(mEntity.getDirPath() + "/" + fileName);
|
||||||
entity.setGroupName(mGroupName);
|
entity.setGroupName(mGroupName);
|
||||||
|
@ -20,6 +20,7 @@ import android.util.Log;
|
|||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.inf.AbsEntity;
|
import com.arialyy.aria.core.inf.AbsEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsTask;
|
import com.arialyy.aria.core.inf.AbsTask;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.core.inf.IEventListener;
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||||
@ -30,7 +31,7 @@ import java.lang.ref.WeakReference;
|
|||||||
* 下载监听类
|
* 下载监听类
|
||||||
*/
|
*/
|
||||||
class BaseListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
|
class BaseListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
|
||||||
implements IEventListener {
|
implements IDownloadListener {
|
||||||
private WeakReference<Handler> outHandler;
|
private WeakReference<Handler> outHandler;
|
||||||
private long mLastLen = 0; //上一次发送长度
|
private long mLastLen = 0; //上一次发送长度
|
||||||
private boolean isFirst = true;
|
private boolean isFirst = true;
|
||||||
@ -60,6 +61,10 @@ class BaseListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
|
|||||||
sendInState2Target(ISchedulers.POST_PRE);
|
sendInState2Target(ISchedulers.POST_PRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void supportBreakpoint(boolean support) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void onStart(long startLocation) {
|
@Override public void onStart(long startLocation) {
|
||||||
saveData(IEntity.STATE_RUNNING, startLocation);
|
saveData(IEntity.STATE_RUNNING, startLocation);
|
||||||
sendInState2Target(ISchedulers.START);
|
sendInState2Target(ISchedulers.START);
|
||||||
|
@ -27,10 +27,7 @@ import com.arialyy.aria.orm.Primary;
|
|||||||
* 下载实体
|
* 下载实体
|
||||||
*/
|
*/
|
||||||
public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
||||||
private String downloadUrl = ""; //下载路径
|
|
||||||
@Primary private String downloadPath = ""; //保存路径
|
@Primary private String downloadPath = ""; //保存路径
|
||||||
private boolean isRedirect = false; //是否重定向
|
|
||||||
private String redirectUrl = ""; //重定向链接
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所属任务组
|
* 所属任务组
|
||||||
@ -54,40 +51,12 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
private String serverFileName = "";
|
private String serverFileName = "";
|
||||||
|
|
||||||
@Override public String getKey() {
|
@Override public String getKey() {
|
||||||
return downloadUrl;
|
return getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadEntity() {
|
public DownloadEntity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
|
||||||
return "DownloadEntity{"
|
|
||||||
+ "downloadUrl='"
|
|
||||||
+ downloadUrl
|
|
||||||
+ '\''
|
|
||||||
+ ", downloadPath='"
|
|
||||||
+ downloadPath
|
|
||||||
+ '\''
|
|
||||||
+ ", isRedirect="
|
|
||||||
+ isRedirect
|
|
||||||
+ ", redirectUrl='"
|
|
||||||
+ redirectUrl
|
|
||||||
+ '\''
|
|
||||||
+ ", groupName='"
|
|
||||||
+ groupName
|
|
||||||
+ '\''
|
|
||||||
+ ", md5Code='"
|
|
||||||
+ md5Code
|
|
||||||
+ '\''
|
|
||||||
+ ", disposition='"
|
|
||||||
+ disposition
|
|
||||||
+ '\''
|
|
||||||
+ ", serverFileName='"
|
|
||||||
+ serverFileName
|
|
||||||
+ '\''
|
|
||||||
+ '}';
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMd5Code() {
|
public String getMd5Code() {
|
||||||
return md5Code;
|
return md5Code;
|
||||||
}
|
}
|
||||||
@ -120,13 +89,11 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
this.groupName = groupName;
|
this.groupName = groupName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDownloadUrl() {
|
/**
|
||||||
return downloadUrl;
|
* @see {@link #getUrl()}
|
||||||
}
|
*/
|
||||||
|
@Deprecated public String getDownloadUrl() {
|
||||||
public DownloadEntity setDownloadUrl(String downloadUrl) {
|
return getUrl();
|
||||||
this.downloadUrl = downloadUrl;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDownloadPath() {
|
public String getDownloadPath() {
|
||||||
@ -142,44 +109,42 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
return (DownloadEntity) super.clone();
|
return (DownloadEntity) super.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRedirect() {
|
|
||||||
return isRedirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedirect(boolean redirect) {
|
|
||||||
isRedirect = redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRedirectUrl() {
|
|
||||||
return redirectUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedirectUrl(String redirectUrl) {
|
|
||||||
this.redirectUrl = redirectUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public int describeContents() {
|
@Override public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||||
super.writeToParcel(dest, flags);
|
super.writeToParcel(dest, flags);
|
||||||
dest.writeString(this.downloadUrl);
|
|
||||||
dest.writeString(this.downloadPath);
|
dest.writeString(this.downloadPath);
|
||||||
dest.writeByte(this.isRedirect ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeString(this.redirectUrl);
|
|
||||||
dest.writeString(this.groupName);
|
dest.writeString(this.groupName);
|
||||||
dest.writeString(this.md5Code);
|
dest.writeString(this.md5Code);
|
||||||
dest.writeString(this.disposition);
|
dest.writeString(this.disposition);
|
||||||
dest.writeString(this.serverFileName);
|
dest.writeString(this.serverFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public String toString() {
|
||||||
|
return "DownloadEntity{"
|
||||||
|
+ "downloadPath='"
|
||||||
|
+ downloadPath
|
||||||
|
+ '\''
|
||||||
|
+ ", groupName='"
|
||||||
|
+ groupName
|
||||||
|
+ '\''
|
||||||
|
+ ", md5Code='"
|
||||||
|
+ md5Code
|
||||||
|
+ '\''
|
||||||
|
+ ", disposition='"
|
||||||
|
+ disposition
|
||||||
|
+ '\''
|
||||||
|
+ ", serverFileName='"
|
||||||
|
+ serverFileName
|
||||||
|
+ '\''
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
|
||||||
protected DownloadEntity(Parcel in) {
|
protected DownloadEntity(Parcel in) {
|
||||||
super(in);
|
super(in);
|
||||||
this.downloadUrl = in.readString();
|
|
||||||
this.downloadPath = in.readString();
|
this.downloadPath = in.readString();
|
||||||
this.isRedirect = in.readByte() != 0;
|
|
||||||
this.redirectUrl = in.readString();
|
|
||||||
this.groupName = in.readString();
|
this.groupName = in.readString();
|
||||||
this.md5Code = in.readString();
|
this.md5Code = in.readString();
|
||||||
this.disposition = in.readString();
|
this.disposition = in.readString();
|
||||||
|
@ -19,7 +19,7 @@ import android.os.Handler;
|
|||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.download.downloader.DownloadGroupUtil;
|
import com.arialyy.aria.core.download.downloader.DownloadGroupUtil;
|
||||||
import com.arialyy.aria.core.download.downloader.FtpDirDownloadUtil;
|
import com.arialyy.aria.core.download.downloader.FtpDirDownloadUtil;
|
||||||
import com.arialyy.aria.core.download.downloader.IDownloadUtil;
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
import com.arialyy.aria.core.inf.AbsGroupTask;
|
import com.arialyy.aria.core.inf.AbsGroupTask;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||||
@ -32,7 +32,7 @@ import com.arialyy.aria.util.CheckUtil;
|
|||||||
public class DownloadGroupTask extends AbsGroupTask<DownloadGroupTaskEntity, DownloadGroupEntity> {
|
public class DownloadGroupTask extends AbsGroupTask<DownloadGroupTaskEntity, DownloadGroupEntity> {
|
||||||
private final String TAG = "DownloadGroupTask";
|
private final String TAG = "DownloadGroupTask";
|
||||||
private DownloadGroupListener mListener;
|
private DownloadGroupListener mListener;
|
||||||
private IDownloadUtil mUtil;
|
private IUtil mUtil;
|
||||||
|
|
||||||
private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) {
|
private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) {
|
||||||
mTaskEntity = taskEntity;
|
mTaskEntity = taskEntity;
|
||||||
@ -51,29 +51,29 @@ public class DownloadGroupTask extends AbsGroupTask<DownloadGroupTaskEntity, Dow
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isRunning() {
|
@Override public boolean isRunning() {
|
||||||
return mUtil.isDownloading();
|
return mUtil.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void start() {
|
@Override public void start() {
|
||||||
mUtil.startDownload();
|
mUtil.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void stop() {
|
@Override public void stop() {
|
||||||
if (!mUtil.isDownloading()) {
|
if (!mUtil.isRunning()) {
|
||||||
if (mOutHandler != null) {
|
if (mOutHandler != null) {
|
||||||
mOutHandler.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
mOutHandler.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mUtil.stopDownload();
|
mUtil.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void cancel() {
|
@Override public void cancel() {
|
||||||
if (!mUtil.isDownloading()) {
|
if (!mUtil.isRunning()) {
|
||||||
if (mOutHandler != null) {
|
if (mOutHandler != null) {
|
||||||
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mUtil.cancelDownload();
|
mUtil.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.arialyy.aria.core.download;
|
package com.arialyy.aria.core.download;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import com.arialyy.aria.core.download.downloader.IDownloadListener;
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/7/20.
|
* Created by Aria.Lao on 2017/7/20.
|
||||||
|
@ -24,7 +24,7 @@ import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
|||||||
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
|
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
|
||||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||||
import com.arialyy.aria.core.scheduler.ISchedulerListener;
|
import com.arialyy.aria.core.scheduler.ISchedulerListener;
|
||||||
import com.arialyy.aria.core.ProxyHelper;
|
import com.arialyy.aria.core.common.ProxyHelper;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
@ -163,7 +163,7 @@ public class DownloadReceiver extends AbsReceiver {
|
|||||||
*/
|
*/
|
||||||
public DownloadEntity getDownloadEntity(String downloadUrl) {
|
public DownloadEntity getDownloadEntity(String downloadUrl) {
|
||||||
CheckUtil.checkDownloadUrl(downloadUrl);
|
CheckUtil.checkDownloadUrl(downloadUrl);
|
||||||
return DbEntity.findFirst(DownloadEntity.class, "downloadUrl=? and isGroupChild='false'",
|
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'",
|
||||||
downloadUrl);
|
downloadUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ public class DownloadReceiver extends AbsReceiver {
|
|||||||
* 下载任务是否存在
|
* 下载任务是否存在
|
||||||
*/
|
*/
|
||||||
@Override public boolean taskExists(String downloadUrl) {
|
@Override public boolean taskExists(String downloadUrl) {
|
||||||
return DownloadEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null;
|
return DownloadEntity.findFirst(DownloadEntity.class, "url=?", downloadUrl) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +32,7 @@ public class DownloadTarget
|
|||||||
extends AbsDownloadTarget<DownloadTarget, DownloadEntity, DownloadTaskEntity> {
|
extends AbsDownloadTarget<DownloadTarget, DownloadEntity, DownloadTaskEntity> {
|
||||||
protected String url;
|
protected String url;
|
||||||
DownloadTarget(DownloadEntity entity, String targetName) {
|
DownloadTarget(DownloadEntity entity, String targetName) {
|
||||||
this(entity.getDownloadUrl(), targetName);
|
this(entity.getUrl(), targetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadTarget(String url, String targetName) {
|
DownloadTarget(String url, String targetName) {
|
||||||
@ -60,11 +60,11 @@ public class DownloadTarget
|
|||||||
*/
|
*/
|
||||||
private DownloadEntity getEntity(String downloadUrl) {
|
private DownloadEntity getEntity(String downloadUrl) {
|
||||||
DownloadEntity entity =
|
DownloadEntity entity =
|
||||||
DownloadEntity.findFirst(DownloadEntity.class, "downloadUrl=? and isGroupChild='false'",
|
DownloadEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'",
|
||||||
downloadUrl);
|
downloadUrl);
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
entity = new DownloadEntity();
|
entity = new DownloadEntity();
|
||||||
entity.setDownloadUrl(downloadUrl);
|
entity.setUrl(downloadUrl);
|
||||||
entity.setGroupChild(false);
|
entity.setGroupChild(false);
|
||||||
entity.save();
|
entity.save();
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ public class DownloadTarget
|
|||||||
* 下载任务是否存在
|
* 下载任务是否存在
|
||||||
*/
|
*/
|
||||||
@Override public boolean taskExists() {
|
@Override public boolean taskExists() {
|
||||||
return DownloadTaskQueue.getInstance().getTask(mEntity.getDownloadUrl()) != null;
|
return DownloadTaskQueue.getInstance().getTask(mEntity.getUrl()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +19,7 @@ package com.arialyy.aria.core.download;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.download.downloader.IDownloadUtil;
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
import com.arialyy.aria.core.download.downloader.SimpleDownloadUtil;
|
import com.arialyy.aria.core.download.downloader.SimpleDownloadUtil;
|
||||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
@ -34,7 +34,7 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
public static final String TAG = "DownloadTask";
|
public static final String TAG = "DownloadTask";
|
||||||
|
|
||||||
private DownloadListener mListener;
|
private DownloadListener mListener;
|
||||||
private IDownloadUtil mUtil;
|
private IUtil mUtil;
|
||||||
|
|
||||||
private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) {
|
private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) {
|
||||||
mEntity = taskEntity.getEntity();
|
mEntity = taskEntity.getEntity();
|
||||||
@ -63,11 +63,11 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
* @see DownloadTask#getKey()
|
* @see DownloadTask#getKey()
|
||||||
*/
|
*/
|
||||||
@Deprecated public String getDownloadUrl() {
|
@Deprecated public String getDownloadUrl() {
|
||||||
return mEntity.getDownloadUrl();
|
return mEntity.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String getKey() {
|
@Override public String getKey() {
|
||||||
return getDownloadUrl();
|
return mEntity.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +76,7 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
* @see DownloadTask#isRunning()
|
* @see DownloadTask#isRunning()
|
||||||
*/
|
*/
|
||||||
@Deprecated public boolean isDownloading() {
|
@Deprecated public boolean isDownloading() {
|
||||||
return mUtil.isDownloading();
|
return mUtil.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isRunning() {
|
@Override public boolean isRunning() {
|
||||||
@ -108,10 +108,10 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
*/
|
*/
|
||||||
@Override public void start() {
|
@Override public void start() {
|
||||||
mListener.isWait = false;
|
mListener.isWait = false;
|
||||||
if (mUtil.isDownloading()) {
|
if (mUtil.isRunning()) {
|
||||||
Log.d(TAG, "任务正在下载");
|
Log.d(TAG, "任务正在下载");
|
||||||
} else {
|
} else {
|
||||||
mUtil.startDownload();
|
mUtil.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +124,8 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
|
|
||||||
private void stop(boolean isWait) {
|
private void stop(boolean isWait) {
|
||||||
mListener.isWait = isWait;
|
mListener.isWait = isWait;
|
||||||
if (mUtil.isDownloading()) {
|
if (mUtil.isRunning()) {
|
||||||
mUtil.stopDownload();
|
mUtil.stop();
|
||||||
} else {
|
} else {
|
||||||
mEntity.setState(isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP);
|
mEntity.setState(isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP);
|
||||||
mEntity.update();
|
mEntity.update();
|
||||||
@ -140,12 +140,12 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
|||||||
*/
|
*/
|
||||||
@Override public void cancel() {
|
@Override public void cancel() {
|
||||||
if (!mEntity.isComplete()) {
|
if (!mEntity.isComplete()) {
|
||||||
if (!mUtil.isDownloading()) {
|
if (!mUtil.isRunning()) {
|
||||||
if (mOutHandler != null) {
|
if (mOutHandler != null) {
|
||||||
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mUtil.cancelDownload();
|
mUtil.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ package com.arialyy.aria.core.download.downloader;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
import com.arialyy.aria.core.inf.AbsEntity;
|
import com.arialyy.aria.core.inf.AbsEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
@ -80,7 +81,7 @@ abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
|||||||
client.enterLocalPassiveMode();
|
client.enterLocalPassiveMode();
|
||||||
client.setFileType(FTP.BINARY_FILE_TYPE);
|
client.setFileType(FTP.BINARY_FILE_TYPE);
|
||||||
FTPFile[] files =
|
FTPFile[] files =
|
||||||
client.listFiles(new String(remotePath.getBytes(charSet), ConnectionHelp.SERVER_CHARSET));
|
client.listFiles(new String(remotePath.getBytes(charSet), AbsThreadTask.SERVER_CHARSET));
|
||||||
long size = getFileSize(files, client, remotePath);
|
long size = getFileSize(files, client, remotePath);
|
||||||
mEntity.setFileSize(size);
|
mEntity.setFileSize(size);
|
||||||
reply = client.getReplyCode();
|
reply = client.getReplyCode();
|
||||||
|
@ -16,9 +16,11 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
@ -36,7 +38,7 @@ import java.util.concurrent.Executors;
|
|||||||
* Created by AriaL on 2017/6/30.
|
* Created by AriaL on 2017/6/30.
|
||||||
* 任务组核心逻辑
|
* 任务组核心逻辑
|
||||||
*/
|
*/
|
||||||
abstract class AbsGroupUtil implements IDownloadUtil {
|
abstract class AbsGroupUtil implements IUtil {
|
||||||
private final String TAG = "DownloadGroupUtil";
|
private final String TAG = "DownloadGroupUtil";
|
||||||
/**
|
/**
|
||||||
* 任务组所有任务总大小
|
* 任务组所有任务总大小
|
||||||
@ -90,7 +92,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key);
|
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key);
|
||||||
if (tasks != null && !tasks.isEmpty()) {
|
if (tasks != null && !tasks.isEmpty()) {
|
||||||
for (DownloadTaskEntity te : tasks) {
|
for (DownloadTaskEntity te : tasks) {
|
||||||
mTasksMap.put(te.getEntity().getDownloadUrl(), te);
|
mTasksMap.put(te.getEntity().getUrl(), te);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (DownloadEntity entity : mTaskEntity.entity.getSubTask()) {
|
for (DownloadEntity entity : mTaskEntity.entity.getSubTask()) {
|
||||||
@ -100,7 +102,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
mInitNum++;
|
mInitNum++;
|
||||||
mCurrentLocation += entity.getFileSize();
|
mCurrentLocation += entity.getFileSize();
|
||||||
} else {
|
} else {
|
||||||
mExeMap.put(entity.getDownloadUrl(), createChildDownloadTask(entity));
|
mExeMap.put(entity.getUrl(), createChildDownloadTask(entity));
|
||||||
mCurrentLocation += entity.getCurrentProgress();
|
mCurrentLocation += entity.getCurrentProgress();
|
||||||
mActualTaskNum++;
|
mActualTaskNum++;
|
||||||
}
|
}
|
||||||
@ -116,11 +118,11 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
return mCurrentLocation;
|
return mCurrentLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isDownloading() {
|
@Override public boolean isRunning() {
|
||||||
return isRunning;
|
return isRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void cancelDownload() {
|
@Override public void cancel() {
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
onCancel();
|
onCancel();
|
||||||
@ -132,7 +134,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
Downloader dt = mDownloaderMap.get(key);
|
Downloader dt = mDownloaderMap.get(key);
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
dt.cancelDownload();
|
dt.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delDownloadInfo();
|
delDownloadInfo();
|
||||||
@ -155,7 +157,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void stopDownload() {
|
@Override public void stop() {
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
mListener.onStop(mCurrentLocation);
|
mListener.onStop(mCurrentLocation);
|
||||||
onStop();
|
onStop();
|
||||||
@ -167,7 +169,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
Downloader dt = mDownloaderMap.get(key);
|
Downloader dt = mDownloaderMap.get(key);
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
dt.stopDownload();
|
dt.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,7 +178,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void startDownload() {
|
@Override public void start() {
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
mFailNum = 0;
|
mFailNum = 0;
|
||||||
mListener.onPre();
|
mListener.onPre();
|
||||||
@ -187,8 +189,8 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void resumeDownload() {
|
@Override public void resume() {
|
||||||
startDownload();
|
start();
|
||||||
mListener.onResume(mCurrentLocation);
|
mListener.onResume(mCurrentLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +231,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
void startChildDownload(DownloadTaskEntity taskEntity) {
|
void startChildDownload(DownloadTaskEntity taskEntity) {
|
||||||
ChildDownloadListener listener = new ChildDownloadListener(taskEntity);
|
ChildDownloadListener listener = new ChildDownloadListener(taskEntity);
|
||||||
Downloader dt = new Downloader(listener, taskEntity);
|
Downloader dt = new Downloader(listener, taskEntity);
|
||||||
mDownloaderMap.put(taskEntity.getEntity().getDownloadUrl(), dt);
|
mDownloaderMap.put(taskEntity.getEntity().getUrl(), dt);
|
||||||
if (mExePool.isShutdown()) return;
|
if (mExePool.isShutdown()) return;
|
||||||
mExePool.execute(dt);
|
mExePool.execute(dt);
|
||||||
}
|
}
|
||||||
@ -238,7 +240,7 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
* 创建子任务下载信息
|
* 创建子任务下载信息
|
||||||
*/
|
*/
|
||||||
DownloadTaskEntity createChildDownloadTask(DownloadEntity entity) {
|
DownloadTaskEntity createChildDownloadTask(DownloadEntity entity) {
|
||||||
DownloadTaskEntity taskEntity = mTasksMap.get(entity.getDownloadUrl());
|
DownloadTaskEntity taskEntity = mTasksMap.get(entity.getUrl());
|
||||||
if (taskEntity != null) {
|
if (taskEntity != null) {
|
||||||
taskEntity.entity = entity;
|
taskEntity.entity = entity;
|
||||||
//ftp登录的
|
//ftp登录的
|
||||||
@ -367,8 +369,8 @@ abstract class AbsGroupUtil implements IDownloadUtil {
|
|||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
timer.schedule(new TimerTask() {
|
timer.schedule(new TimerTask() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
Downloader dt = mDownloaderMap.get(entity.getDownloadUrl());
|
Downloader dt = mDownloaderMap.get(entity.getUrl());
|
||||||
dt.startDownload();
|
dt.start();
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,6 @@ import org.apache.commons.net.ftp.FTPClient;
|
|||||||
* 链接帮助类
|
* 链接帮助类
|
||||||
*/
|
*/
|
||||||
class ConnectionHelp {
|
class ConnectionHelp {
|
||||||
/**
|
|
||||||
* FTP 服务器编码
|
|
||||||
*/
|
|
||||||
static String SERVER_CHARSET = "ISO-8859-1";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理链接
|
* 处理链接
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
@ -27,7 +28,7 @@ import java.util.concurrent.Executors;
|
|||||||
* Created by AriaL on 2017/6/30.
|
* Created by AriaL on 2017/6/30.
|
||||||
* 任务组下载工具
|
* 任务组下载工具
|
||||||
*/
|
*/
|
||||||
public class DownloadGroupUtil extends AbsGroupUtil implements IDownloadUtil {
|
public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||||
private final String TAG = "DownloadGroupUtil";
|
private final String TAG = "DownloadGroupUtil";
|
||||||
private ExecutorService mInfoPool;
|
private ExecutorService mInfoPool;
|
||||||
|
|
||||||
|
@ -15,195 +15,31 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
|
import com.arialyy.aria.core.common.AbsFileer;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by AriaL on 2017/7/1.
|
* Created by AriaL on 2017/7/1.
|
||||||
* 文件下载器
|
* 文件下载器
|
||||||
*/
|
*/
|
||||||
class Downloader implements Runnable, IDownloadUtil {
|
class Downloader extends AbsFileer<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "Downloader";
|
|
||||||
private IDownloadListener mListener;
|
|
||||||
private DownloadTaskEntity mTaskEntity;
|
|
||||||
private DownloadEntity mEntity;
|
|
||||||
private ExecutorService mFixedThreadPool;
|
|
||||||
private File mConfigFile;//下载信息配置文件
|
|
||||||
private Context mContext;
|
|
||||||
private File mTempFile; //下载的文件
|
|
||||||
private boolean isNewTask = true;
|
|
||||||
private int mThreadNum, mRealThreadNum;
|
|
||||||
private StateConstance mConstance;
|
|
||||||
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小于1m的文件不启用多线程
|
|
||||||
*/
|
|
||||||
private static final long SUB_LEN = 1024 * 1024;
|
|
||||||
private Timer mTimer;
|
|
||||||
|
|
||||||
Downloader(IDownloadListener listener, DownloadTaskEntity taskEntity) {
|
Downloader(IDownloadListener listener, DownloadTaskEntity taskEntity) {
|
||||||
mListener = listener;
|
super(listener, taskEntity);
|
||||||
mTaskEntity = taskEntity;
|
|
||||||
mEntity = mTaskEntity.getEntity();
|
|
||||||
mContext = AriaManager.APP;
|
|
||||||
mConstance = new StateConstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void setMaxSpeed(double maxSpeed) {
|
@Override protected void checkTask() {
|
||||||
for (int i = 0; i < mThreadNum; i++) {
|
|
||||||
AbsThreadTask task = mTask.get(i);
|
|
||||||
if (task != null) {
|
|
||||||
task.setMaxSpeed(maxSpeed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StateConstance getConstance() {
|
|
||||||
return mConstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void run() {
|
|
||||||
startFlow();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始下载流程
|
|
||||||
*/
|
|
||||||
private void startFlow() {
|
|
||||||
checkTask();
|
|
||||||
mListener.onPostPre(mEntity.getFileSize());
|
|
||||||
mConstance.cleanState();
|
|
||||||
mConstance.isDownloading = true;
|
|
||||||
if (!mTaskEntity.isSupportBP) {
|
|
||||||
mThreadNum = 1;
|
|
||||||
mConstance.THREAD_NUM = mThreadNum;
|
|
||||||
handleNoSupportBreakpointDownload();
|
|
||||||
} else {
|
|
||||||
mThreadNum = isNewTask ? (
|
|
||||||
mEntity.getFileSize() <= SUB_LEN || mTaskEntity.requestType == AbsTaskEntity.FTP_DIR ? 1
|
|
||||||
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum())
|
|
||||||
: mRealThreadNum;
|
|
||||||
mConstance.THREAD_NUM = mThreadNum;
|
|
||||||
mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum);
|
|
||||||
handleBreakpoint();
|
|
||||||
}
|
|
||||||
startTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动进度获取定时器
|
|
||||||
*/
|
|
||||||
private void startTimer() {
|
|
||||||
mTimer = new Timer(true);
|
|
||||||
mTimer.schedule(new TimerTask() {
|
|
||||||
@Override public void run() {
|
|
||||||
if (mConstance.isComplete() || !mConstance.isDownloading) {
|
|
||||||
closeTimer();
|
|
||||||
} else if (mConstance.CURRENT_LOCATION >= 0) {
|
|
||||||
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void closeTimer() {
|
|
||||||
if (mTimer != null) {
|
|
||||||
mTimer.purge();
|
|
||||||
mTimer.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long getFileSize() {
|
|
||||||
return mEntity.getFileSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前下载位置
|
|
||||||
*/
|
|
||||||
@Override public long getCurrentLocation() {
|
|
||||||
return mConstance.CURRENT_LOCATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean isDownloading() {
|
|
||||||
return mConstance.isDownloading;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void cancelDownload() {
|
|
||||||
closeTimer();
|
|
||||||
mConstance.isCancel = true;
|
|
||||||
mConstance.isDownloading = false;
|
|
||||||
if (mFixedThreadPool != null) {
|
|
||||||
mFixedThreadPool.shutdown();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < mThreadNum; i++) {
|
|
||||||
AbsThreadTask task = mTask.get(i);
|
|
||||||
if (task != null) {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, mTaskEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void stopDownload() {
|
|
||||||
closeTimer();
|
|
||||||
if (mConstance.isComplete()) return;
|
|
||||||
mConstance.isStop = true;
|
|
||||||
mConstance.isDownloading = false;
|
|
||||||
if (mFixedThreadPool != null) {
|
|
||||||
mFixedThreadPool.shutdown();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < mThreadNum; i++) {
|
|
||||||
AbsThreadTask task = mTask.get(i);
|
|
||||||
if (task != null) {
|
|
||||||
task.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 直接调用的时候会自动启动线程执行
|
|
||||||
*/
|
|
||||||
@Override public void startDownload() {
|
|
||||||
new Thread(this).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void resumeDownload() {
|
|
||||||
startDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回该下载器的
|
|
||||||
*/
|
|
||||||
public IDownloadListener getListener() {
|
|
||||||
return mListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查任务是否是新任务,新任务条件:
|
|
||||||
* 1、文件不存在
|
|
||||||
* 2、下载记录文件不存在
|
|
||||||
* 3、下载记录文件缺失或不匹配
|
|
||||||
* 4、数据库记录不存在
|
|
||||||
* 5、不支持断点,则是新任务
|
|
||||||
*/
|
|
||||||
private void checkTask() {
|
|
||||||
if (!mTaskEntity.isSupportBP) {
|
if (!mTaskEntity.isSupportBP) {
|
||||||
isNewTask = true;
|
isNewTask = true;
|
||||||
return;
|
return;
|
||||||
@ -218,7 +54,7 @@ class Downloader implements Runnable, IDownloadUtil {
|
|||||||
CommonUtil.createFile(mConfigFile.getPath());
|
CommonUtil.createFile(mConfigFile.getPath());
|
||||||
} else if (!mTempFile.exists()) {
|
} else if (!mTempFile.exists()) {
|
||||||
isNewTask = true;
|
isNewTask = true;
|
||||||
} else if (DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", mEntity.getDownloadUrl())
|
} else if (DbEntity.findFirst(DownloadEntity.class, "url=?", mEntity.getDownloadUrl())
|
||||||
== null) {
|
== null) {
|
||||||
isNewTask = true;
|
isNewTask = true;
|
||||||
} else {
|
} else {
|
||||||
@ -226,156 +62,16 @@ class Downloader implements Runnable, IDownloadUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override protected void handleNewTask() {
|
||||||
* 检查记录文件,如果是新任务返回{@code true},否则返回{@code false}
|
|
||||||
*/
|
|
||||||
private boolean checkConfigFile() {
|
|
||||||
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
|
||||||
if (pro.isEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Set<Object> keys = pro.keySet();
|
|
||||||
int num = 0;
|
|
||||||
for (Object key : keys) {
|
|
||||||
if (String.valueOf(key).contains("_record_")) {
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
mRealThreadNum = num;
|
|
||||||
for (int i = 0; i < mRealThreadNum; i++) {
|
|
||||||
if (pro.getProperty(mTempFile.getName() + "_record_" + i) == null) {
|
|
||||||
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
|
||||||
if (state != null && Integer.parseInt(state + "") == 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复记录地址
|
|
||||||
*
|
|
||||||
* @return true 表示下载完成
|
|
||||||
*/
|
|
||||||
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
|
||||||
mConstance.CURRENT_LOCATION += endL - startL;
|
|
||||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
|
||||||
mConstance.COMPLETE_THREAD_NUM++;
|
|
||||||
mConstance.STOP_NUM++;
|
|
||||||
mConstance.CANCEL_NUM++;
|
|
||||||
if (mConstance.isComplete()) {
|
|
||||||
if (mConfigFile.exists()) {
|
|
||||||
mConfigFile.delete();
|
|
||||||
}
|
|
||||||
mListener.onComplete();
|
|
||||||
mConstance.isDownloading = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建单线程任务
|
|
||||||
*/
|
|
||||||
private void addSingleTask(int i, long startL, long endL, long fileLength) {
|
|
||||||
SubThreadConfig config = new SubThreadConfig();
|
|
||||||
config.FILE_SIZE = fileLength;
|
|
||||||
config.DOWNLOAD_URL =
|
|
||||||
mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getDownloadUrl();
|
|
||||||
config.TEMP_FILE = mTempFile;
|
|
||||||
config.THREAD_ID = i;
|
|
||||||
config.START_LOCATION = startL;
|
|
||||||
config.END_LOCATION = endL;
|
|
||||||
config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
|
||||||
config.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
|
|
||||||
config.DOWNLOAD_TASK_ENTITY = mTaskEntity;
|
|
||||||
AbsThreadTask task = createThreadTask(config);
|
|
||||||
if (task == null) return;
|
|
||||||
mTask.put(i, task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动单线程下载任务
|
|
||||||
*/
|
|
||||||
private void startSingleTask(int[] recordL) {
|
|
||||||
if (mConstance.CURRENT_LOCATION > 0) {
|
|
||||||
mListener.onResume(mConstance.CURRENT_LOCATION);
|
|
||||||
} else {
|
|
||||||
mListener.onStart(mConstance.CURRENT_LOCATION);
|
|
||||||
}
|
|
||||||
mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
|
|
||||||
for (int l : recordL) {
|
|
||||||
if (l == -1) continue;
|
|
||||||
Runnable task = mTask.get(l);
|
|
||||||
if (task != null) {
|
|
||||||
mFixedThreadPool.execute(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理断点
|
|
||||||
*/
|
|
||||||
private void handleBreakpoint() {
|
|
||||||
long fileLength = mEntity.getFileSize();
|
|
||||||
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
|
||||||
int blockSize = (int) (fileLength / mThreadNum);
|
|
||||||
int[] recordL = new int[mThreadNum];
|
|
||||||
for (int i = 0; i < mThreadNum; i++) {
|
|
||||||
recordL[i] = -1;
|
|
||||||
}
|
|
||||||
int rl = 0;
|
|
||||||
if (isNewTask) {
|
|
||||||
createNewFile(fileLength);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < mThreadNum; i++) {
|
|
||||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
|
||||||
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
|
||||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
|
||||||
if (resumeRecordLocation(i, startL, endL)) return;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//分配下载位置
|
|
||||||
Object record = pro.getProperty(mTempFile.getName() + "_record_" + i);
|
|
||||||
//如果有记录,则恢复下载
|
|
||||||
if (!isNewTask && record != null && Long.parseLong(record + "") >= 0) {
|
|
||||||
Long r = Long.parseLong(record + "");
|
|
||||||
mConstance.CURRENT_LOCATION += r - startL;
|
|
||||||
Log.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
|
||||||
startL = r;
|
|
||||||
recordL[rl] = i;
|
|
||||||
rl++;
|
|
||||||
} else {
|
|
||||||
recordL[rl] = i;
|
|
||||||
rl++;
|
|
||||||
}
|
|
||||||
if (i == (mThreadNum - 1)) {
|
|
||||||
//最后一个线程的结束位置即为文件的总长度
|
|
||||||
endL = fileLength;
|
|
||||||
}
|
|
||||||
addSingleTask(i, startL, endL, fileLength);
|
|
||||||
}
|
|
||||||
startSingleTask(recordL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建新的下载文件
|
|
||||||
*/
|
|
||||||
private void createNewFile(long fileLength) {
|
|
||||||
CommonUtil.createFile(mTempFile.getPath());
|
CommonUtil.createFile(mTempFile.getPath());
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
try {
|
try {
|
||||||
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
||||||
//设置文件长度
|
//设置文件长度
|
||||||
file.setLength(fileLength);
|
file.setLength(mEntity.getFileSize());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload("下载失败【downloadUrl:"
|
failDownload("下载失败【downloadUrl:"
|
||||||
+ mEntity.getDownloadUrl()
|
+ mEntity.getUrl()
|
||||||
+ "】\n【filePath:"
|
+ "】\n【filePath:"
|
||||||
+ mEntity.getDownloadPath()
|
+ mEntity.getDownloadPath()
|
||||||
+ "】\n"
|
+ "】\n"
|
||||||
@ -391,45 +87,14 @@ class Downloader implements Runnable, IDownloadUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override protected AbsThreadTask selectThreadTask(SubThreadConfig<DownloadTaskEntity> config) {
|
||||||
* 处理不支持断点的下载
|
|
||||||
*/
|
|
||||||
private void handleNoSupportBreakpointDownload() {
|
|
||||||
SubThreadConfig config = new SubThreadConfig();
|
|
||||||
long len = mEntity.getFileSize();
|
|
||||||
config.FILE_SIZE = len;
|
|
||||||
config.DOWNLOAD_URL =
|
|
||||||
mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getDownloadUrl();
|
|
||||||
config.TEMP_FILE = mTempFile;
|
|
||||||
config.THREAD_ID = 0;
|
|
||||||
config.START_LOCATION = 0;
|
|
||||||
config.END_LOCATION = config.FILE_SIZE;
|
|
||||||
config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
|
||||||
config.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
|
|
||||||
config.DOWNLOAD_TASK_ENTITY = mTaskEntity;
|
|
||||||
AbsThreadTask task = createThreadTask(config);
|
|
||||||
if (task == null) return;
|
|
||||||
mTask.put(0, task);
|
|
||||||
mFixedThreadPool.execute(task);
|
|
||||||
mListener.onPostPre(len);
|
|
||||||
mListener.onStart(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AbsThreadTask createThreadTask(SubThreadConfig config) {
|
|
||||||
switch (mTaskEntity.requestType) {
|
switch (mTaskEntity.requestType) {
|
||||||
case AbsTaskEntity.FTP:
|
case AbsTaskEntity.FTP:
|
||||||
case AbsTaskEntity.FTP_DIR:
|
case AbsTaskEntity.FTP_DIR:
|
||||||
return new FtpThreadTask(mConstance, mListener, config);
|
return new FtpThreadTask(mConstance, (IDownloadListener) mListener, config);
|
||||||
case AbsTaskEntity.HTTP:
|
case AbsTaskEntity.HTTP:
|
||||||
return new HttpThreadTask(mConstance, mListener, config);
|
return new HttpThreadTask(mConstance, (IDownloadListener) mListener, config);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void failDownload(String errorMsg) {
|
|
||||||
closeTimer();
|
|
||||||
Log.e(TAG, errorMsg);
|
|
||||||
mConstance.isDownloading = false;
|
|
||||||
mListener.onFail();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -32,17 +32,17 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
|
|||||||
@Override protected void onStart() {
|
@Override protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
if (mTaskEntity.getEntity().getFileSize() > 1) {
|
if (mTaskEntity.getEntity().getFileSize() > 1) {
|
||||||
start();
|
startDownload();
|
||||||
} else {
|
} else {
|
||||||
new FtpDirInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
new FtpDirInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
||||||
@Override public void onComplete(String url, int code) {
|
@Override public void onComplete(String url, int code) {
|
||||||
if (code >= 200 && code < 300) {
|
if (code >= 200 && code < 300) {
|
||||||
mTotalSize = mTaskEntity.getEntity().getFileSize();
|
mTotalSize = mTaskEntity.getEntity().getFileSize();
|
||||||
for (DownloadEntity entity : mTaskEntity.entity.getSubTask()) {
|
for (DownloadEntity entity : mTaskEntity.entity.getSubTask()) {
|
||||||
mExeMap.put(entity.getDownloadUrl(), createChildDownloadTask(entity));
|
mExeMap.put(entity.getUrl(), createChildDownloadTask(entity));
|
||||||
}
|
}
|
||||||
mActualTaskNum = mTaskEntity.entity.getSubTask().size();
|
mActualTaskNum = mTaskEntity.entity.getSubTask().size();
|
||||||
start();
|
startDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() {
|
private void startDownload() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
Set<String> keys = mExeMap.keySet();
|
Set<String> keys = mExeMap.keySet();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
|
@ -47,7 +47,7 @@ class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DownloadGro
|
|||||||
|
|
||||||
private void addEntity(String remotePath, FTPFile ftpFile) {
|
private void addEntity(String remotePath, FTPFile ftpFile) {
|
||||||
DownloadEntity entity = new DownloadEntity();
|
DownloadEntity entity = new DownloadEntity();
|
||||||
entity.setDownloadUrl("ftp://" + mTaskEntity.serverIp + ":" + mTaskEntity.port + remotePath);
|
entity.setUrl("ftp://" + mTaskEntity.serverIp + ":" + mTaskEntity.port + remotePath);
|
||||||
entity.setDownloadPath(mEntity.getDirPath() + "/" + remotePath);
|
entity.setDownloadPath(mEntity.getDirPath() + "/" + remotePath);
|
||||||
int lastIndex = remotePath.lastIndexOf("/");
|
int lastIndex = remotePath.lastIndexOf("/");
|
||||||
String fileName = lastIndex < 0 ? CommonUtil.keyToHashKey(remotePath)
|
String fileName = lastIndex < 0 ? CommonUtil.keyToHashKey(remotePath)
|
||||||
|
@ -17,6 +17,12 @@ package com.arialyy.aria.core.download.downloader;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
|
import com.arialyy.aria.core.common.StateConstance;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -29,11 +35,11 @@ import org.apache.commons.net.ftp.FTPReply;
|
|||||||
* Created by Aria.Lao on 2017/7/24.
|
* Created by Aria.Lao on 2017/7/24.
|
||||||
* Ftp下载任务
|
* Ftp下载任务
|
||||||
*/
|
*/
|
||||||
class FtpThreadTask extends AbsThreadTask {
|
class FtpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "FtpThreadTask";
|
private final String TAG = "FtpThreadTask";
|
||||||
|
|
||||||
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
SubThreadConfig downloadInfo) {
|
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
||||||
super(constance, listener, downloadInfo);
|
super(constance, listener, downloadInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +57,7 @@ class FtpThreadTask extends AbsThreadTask {
|
|||||||
+ ",结束位置:"
|
+ ",结束位置:"
|
||||||
+ mConfig.END_LOCATION
|
+ mConfig.END_LOCATION
|
||||||
+ "】");
|
+ "】");
|
||||||
String url = mEntity.getDownloadUrl();
|
String url = mEntity.getUrl();
|
||||||
String[] pp = url.split("/")[2].split(":");
|
String[] pp = url.split("/")[2].split(":");
|
||||||
String serverIp = pp[0];
|
String serverIp = pp[0];
|
||||||
int port = Integer.parseInt(pp[1]);
|
int port = Integer.parseInt(pp[1]);
|
||||||
@ -66,7 +72,7 @@ class FtpThreadTask extends AbsThreadTask {
|
|||||||
int reply = client.getReplyCode();
|
int reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
failDownload(STATE.CURRENT_LOCATION, "无法连接到ftp服务器,错误码为:" + reply, null);
|
fail(STATE.CURRENT_LOCATION, "无法连接到ftp服务器,错误码为:" + reply, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String charSet = "UTF-8";
|
String charSet = "UTF-8";
|
||||||
@ -82,12 +88,12 @@ class FtpThreadTask extends AbsThreadTask {
|
|||||||
client.setRestartOffset(mConfig.START_LOCATION);
|
client.setRestartOffset(mConfig.START_LOCATION);
|
||||||
client.allocate(mBufSize);
|
client.allocate(mBufSize);
|
||||||
is = client.retrieveFileStream(
|
is = client.retrieveFileStream(
|
||||||
new String(remotePath.getBytes(charSet), ConnectionHelp.SERVER_CHARSET));
|
new String(remotePath.getBytes(charSet), SERVER_CHARSET));
|
||||||
//发送第二次指令时,还需要再做一次判断
|
//发送第二次指令时,还需要再做一次判断
|
||||||
reply = client.getReplyCode();
|
reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositivePreliminary(reply)) {
|
if (!FTPReply.isPositivePreliminary(reply)) {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
failDownload(mChildCurrentLocation, "获取文件信息错误,错误码为:" + reply, null);
|
fail(mChildCurrentLocation, "获取文件信息错误,错误码为:" + reply, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
||||||
@ -119,13 +125,13 @@ class FtpThreadTask extends AbsThreadTask {
|
|||||||
if (configFile.exists()) {
|
if (configFile.exists()) {
|
||||||
configFile.delete();
|
configFile.delete();
|
||||||
}
|
}
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload(mChildCurrentLocation, "下载失败【" + mConfig.DOWNLOAD_URL + "】", e);
|
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
failDownload(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
@ -49,7 +49,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
HttpURLConnection conn = null;
|
HttpURLConnection conn = null;
|
||||||
try {
|
try {
|
||||||
URL url = new URL(mEntity.getDownloadUrl());
|
URL url = new URL(mEntity.getUrl());
|
||||||
conn = ConnectionHelp.handleConnection(url);
|
conn = ConnectionHelp.handleConnection(url);
|
||||||
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);
|
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);
|
||||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||||
@ -58,7 +58,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
handleConnect(conn);
|
handleConnect(conn);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload("下载失败【downloadUrl:"
|
failDownload("下载失败【downloadUrl:"
|
||||||
+ mEntity.getDownloadUrl()
|
+ mEntity.getUrl()
|
||||||
+ "】\n【filePath:"
|
+ "】\n【filePath:"
|
||||||
+ mEntity.getDownloadPath()
|
+ mEntity.getDownloadPath()
|
||||||
+ "】\n"
|
+ "】\n"
|
||||||
@ -103,7 +103,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
mTaskEntity.isSupportBP = false;
|
mTaskEntity.isSupportBP = false;
|
||||||
isComplete = true;
|
isComplete = true;
|
||||||
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
|
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,错误码:404");
|
failDownload("任务【" + mEntity.getUrl() + "】下载失败,错误码:404");
|
||||||
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
||||||
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|| code == HttpURLConnection.HTTP_SEE_OTHER) {
|
|| code == HttpURLConnection.HTTP_SEE_OTHER) {
|
||||||
@ -112,11 +112,11 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
mEntity.setRedirectUrl(mTaskEntity.redirectUrl);
|
mEntity.setRedirectUrl(mTaskEntity.redirectUrl);
|
||||||
handle302Turn(conn);
|
handle302Turn(conn);
|
||||||
} else {
|
} else {
|
||||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,错误码:" + code);
|
failDownload("任务【" + mEntity.getUrl() + "】下载失败,错误码:" + code);
|
||||||
}
|
}
|
||||||
if (isComplete) {
|
if (isComplete) {
|
||||||
if (onFileInfoListener != null) {
|
if (onFileInfoListener != null) {
|
||||||
onFileInfoListener.onComplete(mEntity.getDownloadUrl(), code);
|
onFileInfoListener.onComplete(mEntity.getUrl(), code);
|
||||||
}
|
}
|
||||||
mEntity.update();
|
mEntity.update();
|
||||||
mTaskEntity.update();
|
mTaskEntity.update();
|
||||||
@ -131,7 +131,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
Log.d(TAG, "30x跳转,location【 " + mTaskEntity.redirectUrlKey + "】" + "新url为【" + newUrl + "】");
|
Log.d(TAG, "30x跳转,location【 " + mTaskEntity.redirectUrlKey + "】" + "新url为【" + newUrl + "】");
|
||||||
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
|
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
|
||||||
if (onFileInfoListener != null) {
|
if (onFileInfoListener != null) {
|
||||||
onFileInfoListener.onFail(mEntity.getDownloadUrl(), "获取重定向链接失败");
|
onFileInfoListener.onFail(mEntity.getUrl(), "获取重定向链接失败");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private boolean checkLen(long len) {
|
private boolean checkLen(long len) {
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,文件长度小于0");
|
failDownload("任务【" + mEntity.getUrl() + "】下载失败,文件长度小于0");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -163,7 +163,7 @@ class HttpFileInfoThread implements Runnable {
|
|||||||
private void failDownload(String errorMsg) {
|
private void failDownload(String errorMsg) {
|
||||||
Log.e(TAG, errorMsg);
|
Log.e(TAG, errorMsg);
|
||||||
if (onFileInfoListener != null) {
|
if (onFileInfoListener != null) {
|
||||||
onFileInfoListener.onFail(mEntity.getDownloadUrl(), errorMsg);
|
onFileInfoListener.onFail(mEntity.getUrl(), errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,6 +16,12 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
|
import com.arialyy.aria.core.common.StateConstance;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -28,11 +34,11 @@ import java.net.URL;
|
|||||||
* Created by lyy on 2017/1/18.
|
* Created by lyy on 2017/1/18.
|
||||||
* 下载线程
|
* 下载线程
|
||||||
*/
|
*/
|
||||||
final class HttpThreadTask extends AbsThreadTask {
|
final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "HttpThreadTask";
|
private final String TAG = "HttpThreadTask";
|
||||||
|
|
||||||
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
SubThreadConfig downloadInfo) {
|
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
||||||
super(constance, listener, downloadInfo);
|
super(constance, listener, downloadInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +47,9 @@ final class HttpThreadTask extends AbsThreadTask {
|
|||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
try {
|
try {
|
||||||
URL url = new URL(mConfig.DOWNLOAD_URL);
|
URL url = new URL(mConfig.URL);
|
||||||
conn = ConnectionHelp.handleConnection(url);
|
conn = ConnectionHelp.handleConnection(url);
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
Log.d(TAG, "任务【"
|
Log.d(TAG, "任务【"
|
||||||
+ mConfig.TEMP_FILE.getName()
|
+ mConfig.TEMP_FILE.getName()
|
||||||
+ "】线程__"
|
+ "】线程__"
|
||||||
@ -59,7 +65,7 @@ final class HttpThreadTask extends AbsThreadTask {
|
|||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "该下载不支持断点");
|
Log.w(TAG, "该下载不支持断点");
|
||||||
}
|
}
|
||||||
conn = ConnectionHelp.setConnectParam(mConfig.DOWNLOAD_TASK_ENTITY, conn);
|
conn = ConnectionHelp.setConnectParam(mConfig.TASK_ENTITY, conn);
|
||||||
conn.setConnectTimeout(STATE.CONNECT_TIME_OUT);
|
conn.setConnectTimeout(STATE.CONNECT_TIME_OUT);
|
||||||
conn.setReadTimeout(STATE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
|
conn.setReadTimeout(STATE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
|
||||||
is = conn.getInputStream();
|
is = conn.getInputStream();
|
||||||
@ -80,7 +86,7 @@ final class HttpThreadTask extends AbsThreadTask {
|
|||||||
}
|
}
|
||||||
if (STATE.isCancel || STATE.isStop) return;
|
if (STATE.isCancel || STATE.isStop) return;
|
||||||
//支持断点的处理
|
//支持断点的处理
|
||||||
if (mConfig.IS_SUPPORT_BREAK_POINT) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
||||||
writeConfig(true, 1);
|
writeConfig(true, 1);
|
||||||
STATE.COMPLETE_THREAD_NUM++;
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
@ -89,20 +95,20 @@ final class HttpThreadTask extends AbsThreadTask {
|
|||||||
if (configFile.exists()) {
|
if (configFile.exists()) {
|
||||||
configFile.delete();
|
configFile.delete();
|
||||||
}
|
}
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "下载任务完成");
|
Log.i(TAG, "下载任务完成");
|
||||||
STATE.isDownloading = false;
|
STATE.isRunning = false;
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
failDownload(mChildCurrentLocation, "下载链接异常", e);
|
fail(mChildCurrentLocation, "下载链接异常", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload(mChildCurrentLocation, "下载失败【" + mConfig.DOWNLOAD_URL + "】", e);
|
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
failDownload(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.core.inf.IEventListener;
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/7/20.
|
* Created by Aria.Lao on 2017/7/20.
|
||||||
* 下载任务组事件
|
* 下载任务组事件
|
||||||
*/
|
*/
|
||||||
public interface IDownloadGroupListener extends IEventListener {
|
public interface IDownloadGroupListener extends IDownloadListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子任务支持断点回调
|
* 子任务支持断点回调
|
||||||
|
@ -17,68 +17,70 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.download.downloader;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2015/8/25.
|
* Created by lyy on 2015/8/25.
|
||||||
* HTTP单任务下载工具
|
* HTTP单任务下载工具
|
||||||
*/
|
*/
|
||||||
public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
|
public class SimpleDownloadUtil implements IUtil, Runnable {
|
||||||
private static final String TAG = "SimpleDownloadUtil";
|
private static final String TAG = "SimpleDownloadUtil";
|
||||||
private IDownloadListener mListener;
|
private IDownloadListener mListener;
|
||||||
private Downloader mDT;
|
private Downloader mDownloader;
|
||||||
private DownloadTaskEntity mTaskEntity;
|
private DownloadTaskEntity mTaskEntity;
|
||||||
|
|
||||||
public SimpleDownloadUtil(DownloadTaskEntity entity, IDownloadListener downloadListener) {
|
public SimpleDownloadUtil(DownloadTaskEntity entity, IDownloadListener downloadListener) {
|
||||||
mTaskEntity = entity;
|
mTaskEntity = entity;
|
||||||
mListener = downloadListener;
|
mListener = downloadListener;
|
||||||
mDT = new Downloader(downloadListener, entity);
|
mDownloader = new Downloader(downloadListener, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public long getFileSize() {
|
@Override public long getFileSize() {
|
||||||
return mDT.getFileSize();
|
return mDownloader.getFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前下载位置
|
* 获取当前下载位置
|
||||||
*/
|
*/
|
||||||
@Override public long getCurrentLocation() {
|
@Override public long getCurrentLocation() {
|
||||||
return mDT.getCurrentLocation();
|
return mDownloader.getCurrentLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isDownloading() {
|
@Override public boolean isRunning() {
|
||||||
return mDT.isDownloading();
|
return mDownloader.isRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
@Override public void cancelDownload() {
|
@Override public void cancel() {
|
||||||
mDT.cancelDownload();
|
mDownloader.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止下载
|
* 停止下载
|
||||||
*/
|
*/
|
||||||
@Override public void stopDownload() {
|
@Override public void stop() {
|
||||||
mDT.stopDownload();
|
mDownloader.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多线程断点续传下载文件,开始下载
|
* 多线程断点续传下载文件,开始下载
|
||||||
*/
|
*/
|
||||||
@Override public void startDownload() {
|
@Override public void start() {
|
||||||
mListener.onPre();
|
mListener.onPre();
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void resumeDownload() {
|
@Override public void resume() {
|
||||||
startDownload();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMaxSpeed(double maxSpeed) {
|
public void setMaxSpeed(double maxSpeed) {
|
||||||
mDT.setMaxSpeed(maxSpeed);
|
mDownloader.setMaxSpeed(maxSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void failDownload(String msg) {
|
private void failDownload(String msg) {
|
||||||
@ -90,7 +92,7 @@ public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
if (mTaskEntity.getEntity().getFileSize() <= 1) {
|
if (mTaskEntity.getEntity().getFileSize() <= 1) {
|
||||||
new Thread(createInfoThread()).start();
|
new Thread(createInfoThread()).start();
|
||||||
} else {
|
} else {
|
||||||
mDT.startDownload();
|
mDownloader.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
case AbsTaskEntity.FTP:
|
case AbsTaskEntity.FTP:
|
||||||
return new FtpFileInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
return new FtpFileInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
||||||
@Override public void onComplete(String url, int code) {
|
@Override public void onComplete(String url, int code) {
|
||||||
mDT.startDownload();
|
mDownloader.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onFail(String url, String errorMsg) {
|
@Override public void onFail(String url, String errorMsg) {
|
||||||
@ -112,7 +114,7 @@ public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
|
|||||||
case AbsTaskEntity.HTTP:
|
case AbsTaskEntity.HTTP:
|
||||||
return new HttpFileInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
return new HttpFileInfoThread(mTaskEntity, new OnFileInfoCallback() {
|
||||||
@Override public void onComplete(String url, int code) {
|
@Override public void onComplete(String url, int code) {
|
||||||
mDT.startDownload();
|
mDownloader.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onFail(String url, String errorMsg) {
|
@Override public void onFail(String url, String errorMsg) {
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package com.arialyy.aria.core.download.downloader;
|
|
||||||
|
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
|
||||||
import java.io.File;
|
|
||||||
import org.apache.commons.net.ftp.FTPClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 子线程下载信息类
|
|
||||||
*/
|
|
||||||
class SubThreadConfig {
|
|
||||||
//线程Id
|
|
||||||
int THREAD_ID;
|
|
||||||
//下载文件大小
|
|
||||||
long FILE_SIZE;
|
|
||||||
//子线程启动下载位置
|
|
||||||
long START_LOCATION;
|
|
||||||
//子线程结束下载位置
|
|
||||||
long END_LOCATION;
|
|
||||||
//下载路径
|
|
||||||
File TEMP_FILE;
|
|
||||||
String DOWNLOAD_URL;
|
|
||||||
String CONFIG_FILE_PATH;
|
|
||||||
DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
|
|
||||||
boolean IS_SUPPORT_BREAK_POINT = true;
|
|
||||||
}
|
|
@ -25,6 +25,11 @@ import com.arialyy.aria.orm.Ignore;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器地址
|
||||||
|
*/
|
||||||
|
private String url = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件名
|
* 文件名
|
||||||
*/
|
*/
|
||||||
@ -35,6 +40,16 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
private boolean isGroupChild = false;
|
private boolean isGroupChild = false;
|
||||||
|
|
||||||
|
private boolean isRedirect = false; //是否重定向
|
||||||
|
private String redirectUrl = ""; //重定向链接
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isGroupChild() {
|
public boolean isGroupChild() {
|
||||||
return isGroupChild;
|
return isGroupChild;
|
||||||
@ -52,6 +67,22 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
|||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRedirect() {
|
||||||
|
return isRedirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirect(boolean redirect) {
|
||||||
|
isRedirect = redirect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRedirectUrl() {
|
||||||
|
return redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectUrl(String redirectUrl) {
|
||||||
|
this.redirectUrl = redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public AbsNormalEntity() {
|
public AbsNormalEntity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,13 +92,19 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
|||||||
|
|
||||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||||
super.writeToParcel(dest, flags);
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeString(this.url);
|
||||||
dest.writeString(this.fileName);
|
dest.writeString(this.fileName);
|
||||||
dest.writeByte(this.isGroupChild ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.isGroupChild ? (byte) 1 : (byte) 0);
|
||||||
|
dest.writeByte(this.isRedirect ? (byte) 1 : (byte) 0);
|
||||||
|
dest.writeString(this.redirectUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbsNormalEntity(Parcel in) {
|
protected AbsNormalEntity(Parcel in) {
|
||||||
super(in);
|
super(in);
|
||||||
|
this.url = in.readString();
|
||||||
this.fileName = in.readString();
|
this.fileName = in.readString();
|
||||||
this.isGroupChild = in.readByte() != 0;
|
this.isGroupChild = in.readByte() != 0;
|
||||||
|
this.isRedirect = in.readByte() != 0;
|
||||||
|
this.redirectUrl = in.readString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import android.support.annotation.NonNull;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.RequestEnum;
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.inf;
|
package com.arialyy.aria.core.inf;
|
||||||
|
|
||||||
import com.arialyy.aria.core.RequestEnum;
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import com.arialyy.aria.orm.Ignore;
|
import com.arialyy.aria.orm.Ignore;
|
||||||
import com.arialyy.aria.orm.Primary;
|
import com.arialyy.aria.orm.Primary;
|
||||||
|
@ -37,8 +37,8 @@ public abstract class AbsUploadTarget<TARGET extends AbsUploadTarget, ENTITY ext
|
|||||||
*/
|
*/
|
||||||
public TARGET setUploadUrl(@NonNull String uploadUrl) {
|
public TARGET setUploadUrl(@NonNull String uploadUrl) {
|
||||||
CheckUtil.checkDownloadUrl(uploadUrl);
|
CheckUtil.checkDownloadUrl(uploadUrl);
|
||||||
if (mEntity.getUploadUrl().equals(uploadUrl)) return (TARGET) this;
|
if (mEntity.getUrl().equals(uploadUrl)) return (TARGET) this;
|
||||||
mEntity.setUploadUrl(uploadUrl);
|
mEntity.setUrl(uploadUrl);
|
||||||
mEntity.update();
|
mEntity.update();
|
||||||
return (TARGET) this;
|
return (TARGET) this;
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.arialyy.aria.core.download.downloader;
|
package com.arialyy.aria.core.inf;
|
||||||
|
|
||||||
import com.arialyy.aria.core.inf.IEventListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载监听
|
* 下载监听
|
||||||
*/
|
*/
|
||||||
public interface IDownloadListener extends IEventListener {
|
public interface IDownloadListener extends IEventListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预处理完成,准备下载---开始下载之间
|
||||||
|
*/
|
||||||
|
void onPostPre(long fileSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持断点回调
|
* 支持断点回调
|
||||||
*
|
*
|
@ -26,11 +26,6 @@ public interface IEventListener {
|
|||||||
*/
|
*/
|
||||||
void onPre();
|
void onPre();
|
||||||
|
|
||||||
/**
|
|
||||||
* 预处理完成,准备下载---开始下载之间
|
|
||||||
*/
|
|
||||||
void onPostPre(long fileSize);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始
|
* 开始
|
||||||
*/
|
*/
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.arialyy.aria.core.inf;
|
package com.arialyy.aria.core.inf;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import com.arialyy.aria.core.RequestEnum;
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.upload.uploader;
|
package com.arialyy.aria.core.inf;
|
||||||
|
|
||||||
import com.arialyy.aria.core.inf.IEventListener;
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
|
|
||||||
@ -23,4 +23,8 @@ import com.arialyy.aria.core.inf.IEventListener;
|
|||||||
*/
|
*/
|
||||||
public interface IUploadListener extends IEventListener {
|
public interface IUploadListener extends IEventListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传完成,服务器返回的状态码
|
||||||
|
*/
|
||||||
|
void onComplete(int state);
|
||||||
}
|
}
|
@ -60,7 +60,7 @@ public class DownloadTaskQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public String getKey(DownloadEntity entity) {
|
@Override public String getKey(DownloadEntity entity) {
|
||||||
return entity.getDownloadUrl();
|
return entity.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getConfigMaxNum() {
|
@Override public int getConfigMaxNum() {
|
||||||
|
@ -17,8 +17,10 @@ package com.arialyy.aria.core.upload;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/7/27.
|
* Created by Aria.Lao on 2017/7/27.
|
||||||
@ -38,7 +40,11 @@ public class FtpUploadTarget
|
|||||||
if (mTaskEntity.entity == null) {
|
if (mTaskEntity.entity == null) {
|
||||||
mTaskEntity.entity = getUploadEntity(filePath);
|
mTaskEntity.entity = getUploadEntity(filePath);
|
||||||
}
|
}
|
||||||
|
mTaskEntity.requestType = AbsTaskEntity.FTP;
|
||||||
mEntity = mTaskEntity.entity;
|
mEntity = mTaskEntity.entity;
|
||||||
|
File file = new File(filePath);
|
||||||
|
mEntity.setFileName(file.getName());
|
||||||
|
mEntity.setFileSize(file.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,8 +29,6 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
@Primary
|
@Primary
|
||||||
private String filePath; //文件路径
|
private String filePath; //文件路径
|
||||||
|
|
||||||
private String uploadUrl; //文件上传地址
|
|
||||||
|
|
||||||
|
|
||||||
public String getFilePath() {
|
public String getFilePath() {
|
||||||
return filePath;
|
return filePath;
|
||||||
@ -44,14 +42,6 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUploadUrl() {
|
|
||||||
return uploadUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUploadUrl(String uploadUrl) {
|
|
||||||
this.uploadUrl = uploadUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UploadEntity() {
|
public UploadEntity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +52,11 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||||
super.writeToParcel(dest, flags);
|
super.writeToParcel(dest, flags);
|
||||||
dest.writeString(this.filePath);
|
dest.writeString(this.filePath);
|
||||||
dest.writeString(this.uploadUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UploadEntity(Parcel in) {
|
protected UploadEntity(Parcel in) {
|
||||||
super(in);
|
super(in);
|
||||||
this.filePath = in.readString();
|
this.filePath = in.readString();
|
||||||
this.uploadUrl = in.readString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<UploadEntity> CREATOR = new Creator<UploadEntity>() {
|
public static final Creator<UploadEntity> CREATOR = new Creator<UploadEntity>() {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.upload;
|
package com.arialyy.aria.core.upload;
|
||||||
|
|
||||||
import com.arialyy.aria.core.upload.uploader.IUploadListener;
|
import com.arialyy.aria.core.inf.IUploadListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/2/23.
|
* Created by lyy on 2017/2/23.
|
||||||
@ -25,10 +25,6 @@ class UploadListener implements IUploadListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onPostPre(long fileSize) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onStart(long startLocation) {
|
@Override public void onStart(long startLocation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -56,4 +52,8 @@ class UploadListener implements IUploadListener {
|
|||||||
@Override public void onFail() {
|
@Override public void onFail() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void onComplete(int state) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ package com.arialyy.aria.core.upload;
|
|||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.ProxyHelper;
|
import com.arialyy.aria.core.common.ProxyHelper;
|
||||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsReceiver;
|
import com.arialyy.aria.core.inf.AbsReceiver;
|
||||||
@ -39,15 +39,25 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
|
|||||||
public ISchedulerListener<UploadTask> listener;
|
public ISchedulerListener<UploadTask> listener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载任务
|
* 加载HTTP单文件上传任务
|
||||||
*
|
*
|
||||||
* @param filePath 文件地址
|
* @param filePath 文件路径
|
||||||
*/
|
*/
|
||||||
public UploadTarget load(@NonNull String filePath) {
|
public UploadTarget load(@NonNull String filePath) {
|
||||||
CheckUtil.checkUploadPath(filePath);
|
CheckUtil.checkUploadPath(filePath);
|
||||||
return new UploadTarget(filePath, targetName);
|
return new UploadTarget(filePath, targetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载FTP单文件上传任务
|
||||||
|
*
|
||||||
|
* @param filePath 文件路径
|
||||||
|
*/
|
||||||
|
public FtpUploadTarget loadFtp(@NonNull String filePath) {
|
||||||
|
CheckUtil.checkUploadPath(filePath);
|
||||||
|
return new FtpUploadTarget(filePath, targetName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过上传路径获取上传实体
|
* 通过上传路径获取上传实体
|
||||||
*/
|
*/
|
||||||
|
@ -20,6 +20,7 @@ import com.arialyy.aria.core.inf.AbsDownloadTarget;
|
|||||||
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
||||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
|
import java.io.File;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +39,11 @@ public class UploadTarget extends AbsUploadTarget<UploadTarget, UploadEntity, Up
|
|||||||
if (mTaskEntity.entity == null) {
|
if (mTaskEntity.entity == null) {
|
||||||
mTaskEntity.entity = getUploadEntity(filePath);
|
mTaskEntity.entity = getUploadEntity(filePath);
|
||||||
}
|
}
|
||||||
|
File file = new File(filePath);
|
||||||
|
mEntity.setFileSize(file.length());
|
||||||
mEntity = mTaskEntity.entity;
|
mEntity = mTaskEntity.entity;
|
||||||
|
//http暂时不支持断点上传
|
||||||
|
mTaskEntity.isSupportBP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* 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.upload.uploader;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
|
import com.arialyy.aria.core.common.StateConstance;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.inf.IEventListener;
|
||||||
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import org.apache.commons.net.ftp.FTP;
|
||||||
|
import org.apache.commons.net.ftp.FTPClient;
|
||||||
|
import org.apache.commons.net.ftp.FTPFile;
|
||||||
|
import org.apache.commons.net.ftp.FTPReply;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Aria.Lao on 2017/7/28.
|
||||||
|
* FTP 单线程下载器
|
||||||
|
*/
|
||||||
|
class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
|
||||||
|
private final String TAG = "FtpThreadTask";
|
||||||
|
private String remotePath, charSet;
|
||||||
|
|
||||||
|
FtpThreadTask(StateConstance constance, IEventListener listener,
|
||||||
|
SubThreadConfig<UploadTaskEntity> info) {
|
||||||
|
super(constance, listener, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
FTPClient client = null;
|
||||||
|
OutputStream os = null;
|
||||||
|
BufferedRandomAccessFile file = null;
|
||||||
|
try {
|
||||||
|
Log.d(TAG, "任务【"
|
||||||
|
+ mConfig.TEMP_FILE.getName()
|
||||||
|
+ "】线程__"
|
||||||
|
+ mConfig.THREAD_ID
|
||||||
|
+ "__开始上传【开始位置 : "
|
||||||
|
+ mConfig.START_LOCATION
|
||||||
|
+ ",结束位置:"
|
||||||
|
+ mConfig.END_LOCATION
|
||||||
|
+ "】");
|
||||||
|
//当前子线程的下载位置
|
||||||
|
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||||
|
client = createClient();
|
||||||
|
if (client == null) return;
|
||||||
|
client.makeDirectory(remotePath);
|
||||||
|
client.changeWorkingDirectory(remotePath);
|
||||||
|
client.setRestartOffset(mConfig.START_LOCATION);
|
||||||
|
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
||||||
|
file.seek(mConfig.START_LOCATION);
|
||||||
|
if (!isRemoteComplete(client)) {
|
||||||
|
os = client.storeFileStream(new String(remotePath.getBytes(charSet), SERVER_CHARSET));
|
||||||
|
//发送第二次指令时,还需要再做一次判断
|
||||||
|
int reply = client.getReplyCode();
|
||||||
|
if (!FTPReply.isPositivePreliminary(reply)) {
|
||||||
|
client.disconnect();
|
||||||
|
fail(mChildCurrentLocation, "上传文件错误,错误码为:" + reply, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
upload(file, os);
|
||||||
|
}
|
||||||
|
if (STATE.isCancel || STATE.isStop) return;
|
||||||
|
Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__上传完毕");
|
||||||
|
writeConfig(true, 1);
|
||||||
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
|
if (STATE.isComplete()) {
|
||||||
|
File configFile = new File(mConfigFPath);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
configFile.delete();
|
||||||
|
}
|
||||||
|
STATE.isRunning = false;
|
||||||
|
mListener.onComplete();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(mChildCurrentLocation, "上传失败【" + mConfig.URL + "】", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (file != null) {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
if (os != null) {
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
if (client != null && client.isConnected()) {
|
||||||
|
client.disconnect();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 远程文件是否已经玩飞车
|
||||||
|
*
|
||||||
|
* @return true 任务已经完成
|
||||||
|
*/
|
||||||
|
private boolean isRemoteComplete(FTPClient client) throws IOException {
|
||||||
|
FTPFile[] files = client.listFiles(new String(remotePath.getBytes(charSet), SERVER_CHARSET));
|
||||||
|
return files.length != 0 && files[0].getSize() == mEntity.getFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行上传操作
|
||||||
|
*/
|
||||||
|
private void upload(BufferedRandomAccessFile file, OutputStream os)
|
||||||
|
throws IOException, InterruptedException {
|
||||||
|
int len;
|
||||||
|
byte[] buffer = new byte[mBufSize];
|
||||||
|
while ((len = file.read(buffer)) != -1) {
|
||||||
|
if (STATE.isCancel) break;
|
||||||
|
if (STATE.isStop) break;
|
||||||
|
if (mSleepTime > 0) Thread.sleep(mSleepTime);
|
||||||
|
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
||||||
|
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
||||||
|
os.write(buffer, 0, len);
|
||||||
|
progress(len);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
os.write(buffer, 0, len);
|
||||||
|
progress(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建FTP客户端
|
||||||
|
*/
|
||||||
|
private FTPClient createClient() throws IOException {
|
||||||
|
String url = mEntity.getUrl();
|
||||||
|
String[] pp = url.split("/")[2].split(":");
|
||||||
|
String serverIp = pp[0];
|
||||||
|
int port = Integer.parseInt(pp[1]);
|
||||||
|
remotePath = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length())
|
||||||
|
+ "/"
|
||||||
|
+ mEntity.getFileName();
|
||||||
|
FTPClient client = new FTPClient();
|
||||||
|
client.connect(serverIp, port);
|
||||||
|
if (!TextUtils.isEmpty(mTaskEntity.account)) {
|
||||||
|
client.login(mTaskEntity.userName, mTaskEntity.userPw);
|
||||||
|
} else {
|
||||||
|
client.login(mTaskEntity.userName, mTaskEntity.userPw, mTaskEntity.account);
|
||||||
|
}
|
||||||
|
int reply = client.getReplyCode();
|
||||||
|
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||||
|
client.disconnect();
|
||||||
|
fail(STATE.CURRENT_LOCATION, "无法连接到ftp服务器,错误码为:" + reply, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
charSet = "UTF-8";
|
||||||
|
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
||||||
|
if (!TextUtils.isEmpty(mTaskEntity.charSet) || !FTPReply.isPositiveCompletion(
|
||||||
|
client.sendCommand("OPTS UTF8", "ON"))) {
|
||||||
|
charSet = mTaskEntity.charSet;
|
||||||
|
}
|
||||||
|
client.setControlEncoding(charSet);
|
||||||
|
client.setDataTimeout(STATE.READ_TIME_OUT);
|
||||||
|
client.enterLocalPassiveMode();
|
||||||
|
client.setFileType(FTP.BINARY_FILE_TYPE);
|
||||||
|
client.allocate(mBufSize);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
@ -13,11 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.upload;
|
package com.arialyy.aria.core.upload.uploader;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.upload.uploader.IUploadListener;
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
import com.arialyy.aria.core.common.StateConstance;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.inf.IUploadListener;
|
||||||
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -33,55 +37,34 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/2/9.
|
* Created by Aria.Lao on 2017/7/28.
|
||||||
* 上传工具
|
* 不支持断点的HTTP上传任务
|
||||||
*/
|
*/
|
||||||
final class UploadUtil implements Runnable {
|
class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
|
||||||
private static final String TAG = "UploadUtil";
|
private final String TAG = "HttpThreadTask";
|
||||||
|
|
||||||
private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
|
private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
|
||||||
private final String PREFIX = "--", LINE_END = "\r\n";
|
private final String PREFIX = "--", LINE_END = "\r\n";
|
||||||
private UploadEntity mUploadEntity;
|
|
||||||
private UploadTaskEntity mTaskEntity;
|
|
||||||
private IUploadListener mListener;
|
|
||||||
private HttpURLConnection mHttpConn;
|
private HttpURLConnection mHttpConn;
|
||||||
private long mCurrentLocation = 0;
|
private long mCurrentLocation = 0;
|
||||||
private boolean isCancel = false;
|
|
||||||
private boolean isRunning = false;
|
|
||||||
private OutputStream mOutputStream;
|
private OutputStream mOutputStream;
|
||||||
|
|
||||||
UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
|
public HttpThreadTask(StateConstance constance, IUploadListener listener,
|
||||||
mTaskEntity = taskEntity;
|
SubThreadConfig<UploadTaskEntity> uploadInfo) {
|
||||||
CheckUtil.checkTaskEntity(taskEntity);
|
super(constance, listener, uploadInfo);
|
||||||
mUploadEntity = taskEntity.getEntity();
|
|
||||||
if (listener == null) {
|
|
||||||
throw new IllegalArgumentException("上传监听不能为空");
|
|
||||||
}
|
|
||||||
mListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
isCancel = false;
|
|
||||||
isRunning = false;
|
|
||||||
new Thread(this).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
isCancel = true;
|
|
||||||
isRunning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
File uploadFile = new File(mUploadEntity.getFilePath());
|
File uploadFile = new File(mEntity.getFilePath());
|
||||||
if (!uploadFile.exists()) {
|
if (!uploadFile.exists()) {
|
||||||
Log.e(TAG, "【" + mUploadEntity.getFilePath() + "】,文件不存在。");
|
Log.e(TAG, "【" + mEntity.getFilePath() + "】,文件不存在。");
|
||||||
fail();
|
fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mListener.onPre();
|
mListener.onPre();
|
||||||
URL url;
|
URL url;
|
||||||
try {
|
try {
|
||||||
url = new URL(mUploadEntity.getUploadUrl());
|
url = new URL(mEntity.getUrl());
|
||||||
mHttpConn = (HttpURLConnection) url.openConnection();
|
mHttpConn = (HttpURLConnection) url.openConnection();
|
||||||
mHttpConn.setUseCaches(false);
|
mHttpConn.setUseCaches(false);
|
||||||
mHttpConn.setDoOutput(true);
|
mHttpConn.setDoOutput(true);
|
||||||
@ -98,13 +81,9 @@ final class UploadUtil implements Runnable {
|
|||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
mHttpConn.setRequestProperty(key, mTaskEntity.headers.get(key));
|
mHttpConn.setRequestProperty(key, mTaskEntity.headers.get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
mOutputStream = mHttpConn.getOutputStream();
|
mOutputStream = mHttpConn.getOutputStream();
|
||||||
mListener.onPostPre(uploadFile.length());
|
|
||||||
|
|
||||||
PrintWriter writer =
|
PrintWriter writer =
|
||||||
new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskEntity.charSet), true);
|
new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskEntity.charSet), true);
|
||||||
|
|
||||||
//添加文件上传表单字段
|
//添加文件上传表单字段
|
||||||
keys = mTaskEntity.formFields.keySet();
|
keys = mTaskEntity.formFields.keySet();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
@ -119,10 +98,6 @@ final class UploadUtil implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isRunning() {
|
|
||||||
return isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fail() {
|
private void fail() {
|
||||||
try {
|
try {
|
||||||
mListener.onFail();
|
mListener.onFail();
|
||||||
@ -179,10 +154,9 @@ final class UploadUtil implements Runnable {
|
|||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
mCurrentLocation += bytesRead;
|
mCurrentLocation += bytesRead;
|
||||||
mOutputStream.write(buffer, 0, bytesRead);
|
mOutputStream.write(buffer, 0, bytesRead);
|
||||||
if (isCancel) {
|
if (STATE.isCancel) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
isRunning = true;
|
|
||||||
mListener.onProgress(mCurrentLocation);
|
mListener.onProgress(mCurrentLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +165,7 @@ final class UploadUtil implements Runnable {
|
|||||||
inputStream.close();
|
inputStream.close();
|
||||||
writer.append(LINE_END);
|
writer.append(LINE_END);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
isRunning = false;
|
if (STATE.isCancel) {
|
||||||
if (isCancel) {
|
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.upload.uploader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by lyy on 2016/10/31.
|
|
||||||
* 抽象的下载接口
|
|
||||||
*/
|
|
||||||
public interface IUploadUtil {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文件大小
|
|
||||||
*/
|
|
||||||
long getFileSize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前上传位置
|
|
||||||
*/
|
|
||||||
long getCurrentLocation();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否正在下载
|
|
||||||
*
|
|
||||||
* @return true, 正在下载
|
|
||||||
*/
|
|
||||||
boolean isUploading();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消下载
|
|
||||||
*/
|
|
||||||
void cancelUpload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止下载
|
|
||||||
*/
|
|
||||||
void stopUpload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始下载
|
|
||||||
*/
|
|
||||||
void startUpload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从上次断点恢复下载
|
|
||||||
*/
|
|
||||||
void resumeUpload();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置最大下载速度
|
|
||||||
*/
|
|
||||||
void setMaxSpeed(double maxSpeed);
|
|
||||||
}
|
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.upload.uploader;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.common.IUtil;
|
||||||
|
import com.arialyy.aria.core.inf.IUploadListener;
|
||||||
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lyy on 2017/2/9.
|
||||||
|
* 简单的http文件上传工具
|
||||||
|
*/
|
||||||
|
public class SimpleHttpUploadUtil implements IUtil, Runnable {
|
||||||
|
private static final String TAG = "SimpleHttpUploadUtil";
|
||||||
|
|
||||||
|
private UploadEntity mUploadEntity;
|
||||||
|
private UploadTaskEntity mTaskEntity;
|
||||||
|
private IUploadListener mListener;
|
||||||
|
private Uploader mUploader;
|
||||||
|
|
||||||
|
public SimpleHttpUploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
|
||||||
|
mTaskEntity = taskEntity;
|
||||||
|
CheckUtil.checkTaskEntity(taskEntity);
|
||||||
|
mUploadEntity = taskEntity.getEntity();
|
||||||
|
if (listener == null) {
|
||||||
|
throw new IllegalArgumentException("上传监听不能为空");
|
||||||
|
}
|
||||||
|
mListener = listener;
|
||||||
|
mUploader = new Uploader(mListener, taskEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
mUploader.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public long getFileSize() {
|
||||||
|
return mUploader.getFileSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public long getCurrentLocation() {
|
||||||
|
return mUploader.getCurrentLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean isRunning() {
|
||||||
|
return mUploader.isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void cancel() {
|
||||||
|
mUploader.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void stop() {
|
||||||
|
mUploader.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void start() {
|
||||||
|
mUploader.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void resume() {
|
||||||
|
mUploader.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void setMaxSpeed(double maxSpeed) {
|
||||||
|
mUploader.setMaxSpeed(maxSpeed);
|
||||||
|
}
|
||||||
|
}
|
@ -15,87 +15,73 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.upload.uploader;
|
package com.arialyy.aria.core.upload.uploader;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.AriaManager;
|
||||||
|
import com.arialyy.aria.core.common.AbsFileer;
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||||
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IUploadListener;
|
||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
import java.util.Timer;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import java.util.TimerTask;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/7/27.
|
* Created by Aria.Lao on 2017/7/27.
|
||||||
* 文件上传器
|
* 文件上传器
|
||||||
*/
|
*/
|
||||||
public class Uploader implements Runnable, IUploadUtil {
|
class Uploader extends AbsFileer<UploadEntity, UploadTaskEntity> {
|
||||||
|
|
||||||
private IUploadListener mListener;
|
|
||||||
private UploadTaskEntity mTaskEntity;
|
|
||||||
private UploadEntity mEntity;
|
|
||||||
private long mCurrentLocation = 0;
|
|
||||||
|
|
||||||
private Timer mTimer;
|
|
||||||
private boolean isRunning;
|
|
||||||
|
|
||||||
Uploader(IUploadListener listener, UploadTaskEntity taskEntity) {
|
Uploader(IUploadListener listener, UploadTaskEntity taskEntity) {
|
||||||
mListener = listener;
|
super(listener, taskEntity);
|
||||||
mTaskEntity = taskEntity;
|
mTempFile = new File(mEntity.getFilePath());
|
||||||
mEntity = mTaskEntity.getEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long getFileSize() {
|
|
||||||
return mEntity.getFileSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long getCurrentLocation() {
|
|
||||||
return mCurrentLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean isUploading() {
|
|
||||||
return isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void cancelUpload() {
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void stopUpload() {
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void startUpload() {
|
|
||||||
new Thread(this).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void resumeUpload() {
|
|
||||||
startUpload();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void setMaxSpeed(double maxSpeed) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void run() {
|
|
||||||
isRunning = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动进度获取定时器
|
* 检查任务是否是新任务,新任务条件:
|
||||||
|
* 1、文件不存在
|
||||||
|
* 2、记录文件不存在
|
||||||
|
* 3、记录文件缺失或不匹配
|
||||||
|
* 4、数据库记录不存在
|
||||||
|
* 5、不支持断点,则是新任务
|
||||||
*/
|
*/
|
||||||
private void startTimer() {
|
protected void checkTask() {
|
||||||
mTimer = new Timer(true);
|
if (!mTaskEntity.isSupportBP) {
|
||||||
mTimer.schedule(new TimerTask() {
|
isNewTask = true;
|
||||||
@Override public void run() {
|
return;
|
||||||
//if (mConstance.isComplete() || !mConstance.isDownloading) {
|
}
|
||||||
// closeTimer();
|
mConfigFile = new File(mContext.getFilesDir().getPath()
|
||||||
//} else if (mConstance.CURRENT_LOCATION >= 0) {
|
+ AriaManager.UPLOAD_TEMP_DIR
|
||||||
// mListener.onProgress(mConstance.CURRENT_LOCATION);
|
+ mEntity.getFileName()
|
||||||
//}
|
+ ".properties");
|
||||||
}
|
if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
|
||||||
}, 0, 1000);
|
isNewTask = true;
|
||||||
}
|
CommonUtil.createFile(mConfigFile.getPath());
|
||||||
|
} else if (DbEntity.findFirst(UploadEntity.class, "filePath=?", mEntity.getFilePath())
|
||||||
private void closeTimer() {
|
== null) {
|
||||||
if (mTimer != null) {
|
isNewTask = true;
|
||||||
mTimer.purge();
|
} else {
|
||||||
mTimer.cancel();
|
isNewTask = checkConfigFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override protected void handleNewTask() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected int getThreadNum() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected AbsThreadTask selectThreadTask(SubThreadConfig<UploadTaskEntity> config) {
|
||||||
|
switch (mTaskEntity.requestType) {
|
||||||
|
case AbsTaskEntity.FTP:
|
||||||
|
case AbsTaskEntity.FTP_DIR:
|
||||||
|
return new FtpThreadTask(mConstance, mListener, config);
|
||||||
|
case AbsTaskEntity.HTTP:
|
||||||
|
return new HttpThreadTask(mConstance, (IUploadListener) mListener, config);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
|
|||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||||
import com.arialyy.aria.exception.FileException;
|
import com.arialyy.aria.exception.FileException;
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -108,6 +109,8 @@ public class CheckUtil {
|
|||||||
*/
|
*/
|
||||||
public static void checkUploadPath(String uploadPath) {
|
public static void checkUploadPath(String uploadPath) {
|
||||||
if (TextUtils.isEmpty(uploadPath)) throw new IllegalArgumentException("上传地址不能为null");
|
if (TextUtils.isEmpty(uploadPath)) throw new IllegalArgumentException("上传地址不能为null");
|
||||||
|
File file = new File(uploadPath);
|
||||||
|
if (!file.exists()) throw new IllegalArgumentException("上传文件不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +136,7 @@ public class CheckUtil {
|
|||||||
DownloadEntity entity1 = ((DownloadTaskEntity) entity).getEntity();
|
DownloadEntity entity1 = ((DownloadTaskEntity) entity).getEntity();
|
||||||
if (entity1 == null) {
|
if (entity1 == null) {
|
||||||
Log.e(TAG, "下载实体不能为空");
|
Log.e(TAG, "下载实体不能为空");
|
||||||
} else if (checkType && TextUtils.isEmpty(entity1.getDownloadUrl())) {
|
} else if (checkType && TextUtils.isEmpty(entity1.getUrl())) {
|
||||||
Log.e(TAG, "下载链接不能为空");
|
Log.e(TAG, "下载链接不能为空");
|
||||||
} else if (checkType && TextUtils.isEmpty(entity1.getDownloadPath())) {
|
} else if (checkType && TextUtils.isEmpty(entity1.getDownloadPath())) {
|
||||||
Log.e(TAG, "保存路径不能为空");
|
Log.e(TAG, "保存路径不能为空");
|
||||||
@ -175,7 +178,7 @@ public class CheckUtil {
|
|||||||
private static void checkDownloadTaskEntity(DownloadEntity entity) {
|
private static void checkDownloadTaskEntity(DownloadEntity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new NullPointerException("下载实体不能为空");
|
throw new NullPointerException("下载实体不能为空");
|
||||||
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
|
} else if (TextUtils.isEmpty(entity.getUrl())) {
|
||||||
throw new IllegalArgumentException("下载链接不能为空");
|
throw new IllegalArgumentException("下载链接不能为空");
|
||||||
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
||||||
throw new FileException("文件名不能为null");
|
throw new FileException("文件名不能为null");
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<activity android:name=".download.group.DownloadGroupActivity"/>
|
<activity android:name=".download.group.DownloadGroupActivity"/>
|
||||||
<activity android:name=".download.FtpDownloadActivity"/>
|
<activity android:name=".download.FtpDownloadActivity"/>
|
||||||
<activity android:name=".download.group.FTPDirDownloadActivity"/>
|
<activity android:name=".download.group.FTPDirDownloadActivity"/>
|
||||||
|
<activity android:name=".upload.FtpUploadActivity"/>
|
||||||
|
|
||||||
<service android:name=".download.service_download.DownloadService"/>
|
<service android:name=".download.service_download.DownloadService"/>
|
||||||
</application>
|
</application>
|
||||||
|
@ -26,7 +26,7 @@ import com.arialyy.simple.download.DownloadActivity;
|
|||||||
import com.arialyy.simple.download.FtpDownloadActivity;
|
import com.arialyy.simple.download.FtpDownloadActivity;
|
||||||
import com.arialyy.simple.download.group.DownloadGroupActivity;
|
import com.arialyy.simple.download.group.DownloadGroupActivity;
|
||||||
import com.arialyy.simple.download.group.FTPDirDownloadActivity;
|
import com.arialyy.simple.download.group.FTPDirDownloadActivity;
|
||||||
import com.arialyy.simple.test.TestMutilTaskSysDownload;
|
import com.arialyy.simple.upload.FtpUploadActivity;
|
||||||
import com.arialyy.simple.upload.UploadActivity;
|
import com.arialyy.simple.upload.UploadActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,8 +45,10 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
|
|||||||
return R.layout.activity_main;
|
return R.layout.activity_main;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick({ R.id.download, R.id.upload, R.id.download_task_group, R.id.ftp, R.id.ftp_dir })
|
@OnClick({
|
||||||
public void funcation(View view) {
|
R.id.download, R.id.upload, R.id.download_task_group, R.id.ftp_download,
|
||||||
|
R.id.ftp_dir_download, R.id.ftp_upload
|
||||||
|
}) public void funcation(View view) {
|
||||||
switch (view.getId()) {
|
switch (view.getId()) {
|
||||||
case R.id.download:
|
case R.id.download:
|
||||||
startActivity(new Intent(this, DownloadActivity.class));
|
startActivity(new Intent(this, DownloadActivity.class));
|
||||||
@ -57,12 +59,15 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
|
|||||||
case R.id.download_task_group:
|
case R.id.download_task_group:
|
||||||
startActivity(new Intent(this, DownloadGroupActivity.class));
|
startActivity(new Intent(this, DownloadGroupActivity.class));
|
||||||
break;
|
break;
|
||||||
case R.id.ftp:
|
case R.id.ftp_download:
|
||||||
startActivity(new Intent(this, FtpDownloadActivity.class));
|
startActivity(new Intent(this, FtpDownloadActivity.class));
|
||||||
break;
|
break;
|
||||||
case R.id.ftp_dir:
|
case R.id.ftp_dir_download:
|
||||||
startActivity(new Intent(this, FTPDirDownloadActivity.class));
|
startActivity(new Intent(this, FTPDirDownloadActivity.class));
|
||||||
break;
|
break;
|
||||||
|
case R.id.ftp_upload:
|
||||||
|
startActivity(new Intent(this, FtpUploadActivity.class));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ public class DownloadModule extends BaseModule {
|
|||||||
String path = Environment.getExternalStorageDirectory() + "/download/" + name + ".apk";
|
String path = Environment.getExternalStorageDirectory() + "/download/" + name + ".apk";
|
||||||
DownloadEntity entity = new DownloadEntity();
|
DownloadEntity entity = new DownloadEntity();
|
||||||
entity.setFileName(name);
|
entity.setFileName(name);
|
||||||
entity.setDownloadUrl(downloadUrl);
|
entity.setUrl(downloadUrl);
|
||||||
entity.setDownloadPath(path);
|
entity.setDownloadPath(path);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
@ -87,9 +87,9 @@ public class HighestPriorityActivity extends BaseActivity<ActivityHighestPriorit
|
|||||||
List<DownloadEntity> temp = Aria.download(this).getSimpleTaskList();
|
List<DownloadEntity> temp = Aria.download(this).getSimpleTaskList();
|
||||||
if (temp != null && !temp.isEmpty()) {
|
if (temp != null && !temp.isEmpty()) {
|
||||||
for (DownloadEntity entity : temp) {
|
for (DownloadEntity entity : temp) {
|
||||||
if (entity.getDownloadUrl().equals(DOWNLOAD_URL)) continue;
|
if (entity.getUrl().equals(DOWNLOAD_URL)) continue;
|
||||||
mData.add(entity);
|
mData.add(entity);
|
||||||
mRecord.add(entity.getDownloadUrl());
|
mRecord.add(entity.getUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mAdapter = new DownloadAdapter(this, mData);
|
mAdapter = new DownloadAdapter(this, mData);
|
||||||
@ -112,7 +112,7 @@ public class HighestPriorityActivity extends BaseActivity<ActivityHighestPriorit
|
|||||||
case R.id.add_task:
|
case R.id.add_task:
|
||||||
List<DownloadEntity> temp = getModule(DownloadModule.class).getHighestTestList();
|
List<DownloadEntity> temp = getModule(DownloadModule.class).getHighestTestList();
|
||||||
for (DownloadEntity entity : temp) {
|
for (DownloadEntity entity : temp) {
|
||||||
String url = entity.getDownloadUrl();
|
String url = entity.getUrl();
|
||||||
if (mRecord.contains(url)) {
|
if (mRecord.contains(url)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
|||||||
msg = "一些小知识点:\n"
|
msg = "一些小知识点:\n"
|
||||||
+ "1、你可以在注解中增加链接,用于指定被注解的方法只能被特定的下载任务回调,以防止progress乱跳\n"
|
+ "1、你可以在注解中增加链接,用于指定被注解的方法只能被特定的下载任务回调,以防止progress乱跳\n"
|
||||||
+ "2、当遇到网络慢的情况时,你可以先使用onPre()更新UI界面,待连接成功时,再在onTaskPre()获取完整的task数据,然后给UI界面设置正确的数据\n"
|
+ "2、当遇到网络慢的情况时,你可以先使用onPre()更新UI界面,待连接成功时,再在onTaskPre()获取完整的task数据,然后给UI界面设置正确的数据\n"
|
||||||
+ "3、你可以在界面初始化时通过Aria.download(this).load(DOWNLOAD_URL).getPercent()等方法快速获取相关任务的一些数据";
|
+ "3、你可以在界面初始化时通过Aria.download(this).load(URL).getPercent()等方法快速获取相关任务的一些数据";
|
||||||
showMsgDialog("tip", msg);
|
showMsgDialog("tip", msg);
|
||||||
break;
|
break;
|
||||||
case R.id.speed_0:
|
case R.id.speed_0:
|
||||||
@ -188,13 +188,13 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
|||||||
//String text = ((TextView) view).getText().toString();
|
//String text = ((TextView) view).getText().toString();
|
||||||
//if (text.equals("重新开始?") || text.equals("开始")) {
|
//if (text.equals("重新开始?") || text.equals("开始")) {
|
||||||
// Aria.download(this)
|
// Aria.download(this)
|
||||||
// .load(DOWNLOAD_URL)
|
// .load(URL)
|
||||||
// .addHeader("groupName", "value")
|
// .addHeader("groupName", "value")
|
||||||
// .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
// .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
||||||
// .setFileName("hehe.apk")
|
// .setFileName("hehe.apk")
|
||||||
// .start();
|
// .start();
|
||||||
//} else if (text.equals("恢复")) {
|
//} else if (text.equals("恢复")) {
|
||||||
// Aria.download(this).load(DOWNLOAD_URL).resume();
|
// Aria.download(this).load(URL).resume();
|
||||||
//}
|
//}
|
||||||
Aria.download(this)
|
Aria.download(this)
|
||||||
.load(DOWNLOAD_URL)
|
.load(DOWNLOAD_URL)
|
||||||
|
@ -58,7 +58,7 @@ public class DownloadAdapter extends AbsRVAdapter<AbsEntity, DownloadAdapter.Sim
|
|||||||
|
|
||||||
private String getKey(AbsEntity entity) {
|
private String getKey(AbsEntity entity) {
|
||||||
if (entity instanceof DownloadEntity) {
|
if (entity instanceof DownloadEntity) {
|
||||||
return ((DownloadEntity) entity).getDownloadUrl();
|
return ((DownloadEntity) entity).getUrl();
|
||||||
} else if (entity instanceof DownloadGroupEntity) {
|
} else if (entity instanceof DownloadGroupEntity) {
|
||||||
return ((DownloadGroupEntity) entity).getGroupName();
|
return ((DownloadGroupEntity) entity).getGroupName();
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ public class DownloadAdapter extends AbsRVAdapter<AbsEntity, DownloadAdapter.Sim
|
|||||||
|
|
||||||
public void addDownloadEntity(DownloadEntity entity) {
|
public void addDownloadEntity(DownloadEntity entity) {
|
||||||
mData.add(entity);
|
mData.add(entity);
|
||||||
mPositions.put(entity.getDownloadUrl(), mPositions.size());
|
mPositions.put(entity.getUrl(), mPositions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getItemViewType(int position) {
|
@Override public int getItemViewType(int position) {
|
||||||
|
@ -3,7 +3,7 @@ package com.arialyy.simple.test;
|
|||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import com.arialyy.aria.core.Aria;
|
import com.arialyy.aria.core.Aria;
|
||||||
import com.arialyy.aria.core.QueueMod;
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.simple.R;
|
import com.arialyy.simple.R;
|
||||||
import com.arialyy.simple.base.BaseActivity;
|
import com.arialyy.simple.base.BaseActivity;
|
||||||
import com.arialyy.simple.databinding.TestActivityMultiBinding;
|
import com.arialyy.simple.databinding.TestActivityMultiBinding;
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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.simple.upload;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import com.arialyy.annotations.Upload;
|
||||||
|
import com.arialyy.aria.core.Aria;
|
||||||
|
import com.arialyy.aria.core.upload.UploadTask;
|
||||||
|
import com.arialyy.frame.util.show.L;
|
||||||
|
import com.arialyy.frame.util.show.T;
|
||||||
|
import com.arialyy.simple.R;
|
||||||
|
import com.arialyy.simple.base.BaseActivity;
|
||||||
|
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Aria.Lao on 2017/7/28.
|
||||||
|
* Ftp 文件上传demo
|
||||||
|
*/
|
||||||
|
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
|
||||||
|
private final String FILE_PATH = "/mnt/sdcard/王者军团.apk";
|
||||||
|
private final String URL = "ftp://172.18.104.129:21/upload/";
|
||||||
|
|
||||||
|
@Override protected void init(Bundle savedInstanceState) {
|
||||||
|
super.init(savedInstanceState);
|
||||||
|
Aria.upload(this).register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected int setLayoutId() {
|
||||||
|
return R.layout.activity_ftp_upload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onClick(View view) {
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.start:
|
||||||
|
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start();
|
||||||
|
break;
|
||||||
|
case R.id.stop:
|
||||||
|
Aria.upload(this).loadFtp(FILE_PATH).stop();
|
||||||
|
break;
|
||||||
|
case R.id.cancel:
|
||||||
|
Aria.upload(this).load(FILE_PATH).cancel();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onPre public void onPre(UploadTask task) {
|
||||||
|
getBinding().setFileSize(task.getConvertFileSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskPre public void taskPre(UploadTask task) {
|
||||||
|
L.d(TAG, "fileSize = " + task.getConvertFileSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskStart public void taskStart(UploadTask task) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskStop public void taskStop(UploadTask task) {
|
||||||
|
getBinding().setSpeed("");
|
||||||
|
Log.d(TAG, "停止上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskCancel public void taskCancel(UploadTask task) {
|
||||||
|
getBinding().setSpeed("");
|
||||||
|
Log.d(TAG, "取消上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskRunning public void taskRunning(UploadTask task) {
|
||||||
|
getBinding().setProgress(task.getPercent());
|
||||||
|
getBinding().setSpeed(task.getConvertSpeed());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Upload.onTaskComplete public void taskComplete(UploadTask task) {
|
||||||
|
getBinding().setProgress(100);
|
||||||
|
getBinding().setSpeed("");
|
||||||
|
T.showShort(this, "上传完成");
|
||||||
|
}
|
||||||
|
}
|
@ -29,14 +29,13 @@ import com.arialyy.frame.util.show.L;
|
|||||||
import com.arialyy.frame.util.show.T;
|
import com.arialyy.frame.util.show.T;
|
||||||
import com.arialyy.simple.R;
|
import com.arialyy.simple.R;
|
||||||
import com.arialyy.simple.base.BaseActivity;
|
import com.arialyy.simple.base.BaseActivity;
|
||||||
import com.arialyy.simple.databinding.ActivityUploadMeanBinding;
|
import com.arialyy.simple.databinding.ActivityUploadBinding;
|
||||||
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
|
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/2/9.
|
* Created by Aria.Lao on 2017/2/9.
|
||||||
*/
|
*/
|
||||||
public class UploadActivity extends BaseActivity<ActivityUploadMeanBinding> {
|
public class UploadActivity extends BaseActivity<ActivityUploadBinding> {
|
||||||
private static final String TAG = "UploadActivity";
|
private static final String TAG = "UploadActivity";
|
||||||
@Bind(R.id.pb) HorizontalProgressBarWithNumber mPb;
|
@Bind(R.id.pb) HorizontalProgressBarWithNumber mPb;
|
||||||
private static final int START = 0;
|
private static final int START = 0;
|
||||||
@ -74,7 +73,7 @@ public class UploadActivity extends BaseActivity<ActivityUploadMeanBinding> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override protected int setLayoutId() {
|
@Override protected int setLayoutId() {
|
||||||
return R.layout.activity_upload_mean;
|
return R.layout.activity_upload;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void init(Bundle savedInstanceState) {
|
@Override protected void init(Bundle savedInstanceState) {
|
||||||
|
36
app/src/main/res/layout/activity_ftp_upload.xml
Normal file
36
app/src/main/res/layout/activity_ftp_upload.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:bind="http://schemas.android.com/apk/res-auto"
|
||||||
|
>
|
||||||
|
<data>
|
||||||
|
<variable
|
||||||
|
name="fileSize"
|
||||||
|
type="String"
|
||||||
|
/>
|
||||||
|
<variable
|
||||||
|
name="speed"
|
||||||
|
type="String"
|
||||||
|
/>
|
||||||
|
<variable
|
||||||
|
name="progress"
|
||||||
|
type="int"
|
||||||
|
/>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<include layout="@layout/layout_bar"/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/content_single"
|
||||||
|
bind:fileSize="@{fileSize}"
|
||||||
|
bind:progress="@{progress}"
|
||||||
|
bind:speed="@{speed}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
@ -34,7 +34,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/ftp"
|
android:id="@+id/ftp_download"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="FTP 下载"
|
android:text="FTP 下载"
|
||||||
@ -42,12 +42,20 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/ftp_dir"
|
android:id="@+id/ftp_dir_download"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="FTP 文件夹下载"
|
android:text="FTP 文件夹下载"
|
||||||
style="?buttonBarButtonStyle"
|
style="?buttonBarButtonStyle"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/ftp_upload"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="FTP 文件上传"
|
||||||
|
style="?buttonBarButtonStyle"
|
||||||
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.arialyy.aria.core;
|
package com.arialyy.aria.core;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -22,6 +22,7 @@ import com.arialyy.aria.core.AriaManager;
|
|||||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||||
|
import com.arialyy.aria.core.upload.uploader.SimpleHttpUploadUtil;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
@ -32,14 +33,14 @@ import java.lang.ref.WeakReference;
|
|||||||
public class UploadTask extends AbsNormalTask<UploadEntity> {
|
public class UploadTask extends AbsNormalTask<UploadEntity> {
|
||||||
private static final String TAG = "UploadTask";
|
private static final String TAG = "UploadTask";
|
||||||
|
|
||||||
private UploadUtil mUtil;
|
private SimpleHttpUploadUtil mUtil;
|
||||||
private UListener mListener;
|
private UListener mListener;
|
||||||
|
|
||||||
private UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
|
private UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
|
||||||
mOutHandler = outHandler;
|
mOutHandler = outHandler;
|
||||||
mEntity = taskEntity.getEntity();
|
mEntity = taskEntity.getEntity();
|
||||||
mListener = new UListener(mOutHandler, this);
|
mListener = new UListener(mOutHandler, this);
|
||||||
mUtil = new UploadUtil(taskEntity, mListener);
|
mUtil = new SimpleHttpUploadUtil(taskEntity, mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String getKey() {
|
@Override public String getKey() {
|
||||||
@ -62,7 +63,15 @@ public class UploadTask extends AbsNormalTask<UploadEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public void stop() {
|
@Override public void stop() {
|
||||||
|
if (mUtil.isRunning()) {
|
||||||
|
mUtil.stop();
|
||||||
|
} else {
|
||||||
|
mEntity.setState(IEntity.STATE_STOP);
|
||||||
|
mEntity.update();
|
||||||
|
if (mOutHandler != null) {
|
||||||
|
mOutHandler.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void cancel() {
|
@Override public void cancel() {
|
||||||
@ -102,14 +111,6 @@ public class UploadTask extends AbsNormalTask<UploadEntity> {
|
|||||||
saveData(IEntity.STATE_PRE, -1);
|
saveData(IEntity.STATE_PRE, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onPostPre(long fileSize) {
|
|
||||||
super.onPostPre(fileSize);
|
|
||||||
entity.setFileSize(fileSize);
|
|
||||||
entity.setConvertFileSize(CommonUtil.formatFileSize(fileSize));
|
|
||||||
sendInState2Target(ISchedulers.POST_PRE);
|
|
||||||
saveData(IEntity.STATE_POST_PRE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onStart(long startLocation) {
|
@Override public void onStart(long startLocation) {
|
||||||
sendInState2Target(ISchedulers.START);
|
sendInState2Target(ISchedulers.START);
|
||||||
saveData(IEntity.STATE_RUNNING, 0);
|
saveData(IEntity.STATE_RUNNING, 0);
|
||||||
|
Reference in New Issue
Block a user