laoyuyu 6 years ago
parent 15978cd2b6
commit d40f8fa385
  1. 10
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  2. 24
      Aria/src/main/java/com/arialyy/aria/core/command/normal/AbsNormalCmd.java
  3. 7
      Aria/src/main/java/com/arialyy/aria/core/command/normal/NormalCmdFactory.java
  4. 41
      Aria/src/main/java/com/arialyy/aria/core/command/normal/ReStartCmd.java
  5. 37
      Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
  6. 6
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  7. 9
      Aria/src/main/java/com/arialyy/aria/core/common/BaseListener.java
  8. 41
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java
  9. 100
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpInterceptHandler.java
  10. 137
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpTaskDelegate.java
  11. 54
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/IFtpUploadInterceptor.java
  12. 4
      Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java
  13. 4
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java
  14. 19
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java
  15. 6
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
  16. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java
  17. 2
      Aria/src/main/java/com/arialyy/aria/core/download/group/FtpDirInfoThread.java
  18. 8
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java
  19. 17
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  20. 51
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java
  21. 23
      Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java
  22. 14
      Aria/src/main/java/com/arialyy/aria/core/inf/TaskSchedulerType.java
  23. 124
      Aria/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java
  24. 14
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java
  25. 4
      Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java
  26. 10
      Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java
  27. 17
      Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java
  28. 72
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpFileInfoThread.java
  29. 6
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleUploadUtil.java
  30. 32
      Aria/src/main/java/com/arialyy/aria/exception/FileNotFoundException.java
  31. 11
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  32. 2
      DEV_LOG.md
  33. 5
      app/build.gradle
  34. 1
      app/src/main/AndroidManifest.xml
  35. 1
      app/src/main/java/com/arialyy/simple/core/download/DownloadActivity.java
  36. 241
      app/src/main/java/com/arialyy/simple/core/download/KotlinDownloadActivity.kt
  37. 6
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  38. 239
      app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java
  39. 1
      app/src/main/java/com/arialyy/simple/modlue/CommonModule.java
  40. 4
      app/src/main/res/drawable/ic_kotlin.xml
  41. 1
      app/src/main/res/values/strings.xml
  42. 2
      build.gradle

@ -23,6 +23,8 @@ import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.widget.PopupWindow; import android.widget.PopupWindow;
@ -80,6 +82,7 @@ import org.xml.sax.SAXException;
private UploadConfig mUConfig; private UploadConfig mUConfig;
private AppConfig mAConfig; private AppConfig mAConfig;
private DGroupConfig mDGConfig; private DGroupConfig mDGConfig;
private Handler mAriaHandler;
private File[] files; private File[] files;
private AriaManager(Context context) { private AriaManager(Context context) {
@ -141,6 +144,13 @@ import org.xml.sax.SAXException;
} }
} }
public synchronized Handler getAriaHandler() {
if (mAriaHandler == null){
mAriaHandler = new Handler(Looper.getMainLooper());
}
return mAriaHandler;
}
public Map<String, AbsReceiver> getReceiver() { public Map<String, AbsReceiver> getReceiver() {
return mReceivers; return mReceivers;
} }

@ -42,7 +42,6 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
*/ */
boolean canExeCmd = true; boolean canExeCmd = true;
private AbsTask tempTask = null;
int taskType; int taskType;
/** /**
@ -82,9 +81,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* 发送等待状态 * 发送等待状态
*/ */
void sendWaitState() { void sendWaitState() {
if (tempTask != null) { sendWaitState(getTask());
sendWaitState(tempTask);
}
} }
/** /**
@ -108,16 +105,14 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* 停止任务 * 停止任务
*/ */
void stopTask() { void stopTask() {
if (tempTask == null) createTask(); mQueue.stopTask(getTask());
mQueue.stopTask(tempTask);
} }
/** /**
* 删除任务 * 删除任务
*/ */
void removeTask() { void removeTask() {
if (tempTask == null) createTask(); mQueue.cancelTask(getTask());
mQueue.cancelTask(tempTask);
} }
/** /**
@ -135,14 +130,14 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* 启动任务 * 启动任务
*/ */
void startTask() { void startTask() {
mQueue.startTask(tempTask); mQueue.startTask(getTask());
} }
/** /**
* 恢复任务 * 恢复任务
*/ */
void resumeTask() { void resumeTask() {
mQueue.resumeTask(tempTask); mQueue.resumeTask(getTask());
} }
/** /**
@ -160,8 +155,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* @return 执行任务 * @return 执行任务
*/ */
AbsTask getTask() { AbsTask getTask() {
tempTask = mQueue.getTask(mTaskWrapper.getEntity().getKey()); return mQueue.getTask(mTaskWrapper.getEntity().getKey());
return tempTask;
} }
/** /**
@ -170,8 +164,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* @return 执行任务 * @return 执行任务
*/ */
AbsTask getTask(AbsEntity entity) { AbsTask getTask(AbsEntity entity) {
tempTask = mQueue.getTask(entity.getKey()); return mQueue.getTask(entity.getKey());
return tempTask;
} }
/** /**
@ -180,8 +173,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* @return 创建的任务 * @return 创建的任务
*/ */
AbsTask createTask() { AbsTask createTask() {
tempTask = mQueue.createTask(mTaskWrapper); return mQueue.createTask(mTaskWrapper);
return tempTask;
} }
/** /**

@ -62,6 +62,11 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
* 删除所有任务 * 删除所有任务
*/ */
public static final int TASK_CANCEL_ALL = 0xb9; public static final int TASK_CANCEL_ALL = 0xb9;
/**
* 重启任务
*/
public static final int TASK_RESTART = 0xba;
private static volatile NormalCmdFactory INSTANCE = null; private static volatile NormalCmdFactory INSTANCE = null;
private NormalCmdFactory() { private NormalCmdFactory() {
@ -103,6 +108,8 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
return new ResumeAllCmd<>(entity, taskType); return new ResumeAllCmd<>(entity, taskType);
case TASK_CANCEL_ALL: case TASK_CANCEL_ALL:
return new CancelAllCmd<>(entity, taskType); return new CancelAllCmd<>(entity, taskType);
case TASK_RESTART:
return new ReStartCmd<>(entity, taskType);
default: default:
return null; return null;
} }

@ -0,0 +1,41 @@
/*
* 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.command.normal;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.TaskSchedulerType;
/**
* 重新开始任务命令
*/
public class ReStartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
ReStartCmd(T entity, int taskType) {
super(entity, taskType);
}
@Override public void executeCmd() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
if (task != null) {
task.cancel(TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
task.start(TaskSchedulerType.TYPE_START_AND_RESET_STATE);
}
}
}

@ -258,23 +258,20 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
} }
public synchronized void cancel() { public synchronized void cancel() {
ALog.d(TAG, "constance hash: " + mConstance.hashCode());
if (mConstance.isCancel) { if (mConstance.isCancel) {
ALog.d(TAG, String.format("任务【%s】正在删除,删除任务失败", mTaskWrapper.getKey()));
return; return;
} }
closeTimer(); closeTimer();
mConstance.isCancel = true; mConstance.isCancel = true;
new Thread(new Runnable() { for (int i = 0; i < mTask.size(); i++) {
@Override public void run() { AbsThreadTask task = mTask.get(i);
if (task != null) {
for (int i = 0; i < mTask.size(); i++) { task.cancel();
AbsThreadTask task = mTask.get(i);
if (task != null) {
task.cancel();
}
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
} }
}).start(); }
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
} }
public synchronized void stop() { public synchronized void stop() {
@ -284,18 +281,13 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
closeTimer(); closeTimer();
mConstance.isStop = true; mConstance.isStop = true;
if (mConstance.isComplete()) return; if (mConstance.isComplete()) return;
new Thread(new Runnable() { for (int i = 0; i < mTask.size(); i++) {
@Override public void run() { AbsThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
for (int i = 0; i < mTask.size(); i++) { task.stop();
AbsThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
task.stop();
}
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
} }
}).start(); }
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
} }
/** /**
@ -303,6 +295,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
*/ */
public synchronized void start() { public synchronized void start() {
if (isRunning()) { if (isRunning()) {
ALog.d(TAG, String.format("任务【%s】正在执行,启动任务失败", mTaskWrapper.getKey()));
return; return;
} }
new Thread(this).start(); new Thread(this).start();

@ -359,6 +359,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
ALog.d(TAG, ALog.d(TAG,
String.format("任务【%s】thread__%s__取消", getConfig().TEMP_FILE.getName(), String.format("任务【%s】thread__%s__取消", getConfig().TEMP_FILE.getName(),
getConfig().THREAD_ID)); getConfig().THREAD_ID));
//ALog.d(TAG, "cancel_num = "
// + getState().CANCEL_NUM
// + ", start_thread_num = "
// + getState().START_THREAD_NUM);
if (getState().isCancel()) { if (getState().isCancel()) {
if (getConfig().TEMP_FILE.exists() && !(getEntity() instanceof UploadEntity)) { if (getConfig().TEMP_FILE.exists() && !(getEntity() instanceof UploadEntity)) {
getConfig().TEMP_FILE.delete(); getConfig().TEMP_FILE.delete();
@ -413,6 +417,8 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
} }
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP) if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP)
|| isNotNetRetry) && !isBreak()) { || isNotNetRetry) && !isBreak()) {
ALog.d(TAG, String.format("isCancel: %s, isStop: %s, isBreak: %s", getState().isCancel,
getState().isStop, taskBreak));
ALog.w(TAG, String.format("任务【%s】正在重试", getConfig().TEMP_FILE.getName())); ALog.w(TAG, String.format("任务【%s】正在重试", getConfig().TEMP_FILE.getName()));
mFailTimes++; mFailTimes++;
handleRetryRecord(); handleRetryRecord();

@ -55,6 +55,10 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
mLastSaveTime = System.currentTimeMillis(); mLastSaveTime = System.currentTimeMillis();
} }
protected TASK getTask() {
return mTask;
}
@Override public void onPre() { @Override public void onPre() {
saveData(IEntity.STATE_PRE, -1); saveData(IEntity.STATE_PRE, -1);
sendInState2Target(ISchedulers.PRE); sendInState2Target(ISchedulers.PRE);
@ -103,7 +107,10 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
@Override public void onCancel() { @Override public void onCancel() {
saveData(IEntity.STATE_CANCEL, -1); saveData(IEntity.STATE_CANCEL, -1);
handleSpeed(0); handleSpeed(0);
sendInState2Target(ISchedulers.CANCEL); if (mTask.getSchedulerType() != TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
ALog.d(TAG, "删除任务完成");
sendInState2Target(ISchedulers.CANCEL);
}
} }
@Override public void onFail(boolean needRetry, BaseException e) { @Override public void onFail(boolean needRetry, BaseException e) {

@ -34,7 +34,7 @@ import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.AriaIOException; import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.FileException; import com.arialyy.aria.exception.FileNotFoundException;
import com.arialyy.aria.exception.TaskException; import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.Regular; import com.arialyy.aria.util.Regular;
@ -79,11 +79,11 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
} }
/** /**
* 设置请求的远程文件路径 * 获取请求的远程文件路径
* *
* @return 远程文件路径 * @return 远程文件路径
*/ */
protected abstract String setRemotePath(); protected abstract String getRemotePath();
@Override @Override
public void run() { public void run() {
@ -97,7 +97,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
return; return;
} }
String remotePath = String remotePath =
new String(setRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET); new String(getRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
if (mTaskDelegate.getUrlEntity().isFtps) { if (mTaskDelegate.getUrlEntity().isFtps) {
((FTPSClient) client).execPROT("P"); ((FTPSClient) client).execPROT("P");
//((FTPSClient) client).enterLocalActiveMode(); //((FTPSClient) client).enterLocalActiveMode();
@ -105,9 +105,6 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
FTPFile[] files = client.listFiles(remotePath); FTPFile[] files = client.listFiles(remotePath);
boolean isExist = files.length != 0; boolean isExist = files.length != 0;
if (!isExist && !isUpload) { if (!isExist && !isUpload) {
failDownload(new FileException(TAG,
String.format("文件不存在,url: %s, remotePath:%s", mTaskDelegate.getUrlEntity().url,
remotePath)), false);
int i = remotePath.lastIndexOf(File.separator); int i = remotePath.lastIndexOf(File.separator);
FTPFile[] files1; FTPFile[] files1;
if (i == -1) { if (i == -1) {
@ -117,7 +114,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
} }
if (files1.length > 0) { if (files1.length > 0) {
ALog.i(TAG, ALog.i(TAG,
String.format("路径【%s】下的文件列表 ===================================", setRemotePath())); String.format("路径【%s】下的文件列表 ===================================", getRemotePath()));
for (FTPFile file : files1) { for (FTPFile file : files1) {
ALog.d(TAG, file.toString()); ALog.d(TAG, file.toString());
} }
@ -127,13 +124,22 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString())); ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString()));
} }
client.disconnect(); client.disconnect();
failDownload(new FileNotFoundException(TAG,
String.format("文件不存在,url: %s, remotePath:%s", mTaskDelegate.getUrlEntity().url,
remotePath)), false);
return; return;
} }
// 检查ftp文件是否被打开 // 处理拦截功能
if (!onInterceptor(client, files)) {
client.disconnect();
failDownload(new AriaIOException(TAG, "拦截器处理任务失败"), false);
return;
}
//为了防止编码错乱,需要使用原始字符串 //为了防止编码错乱,需要使用原始字符串
mSize = getFileSize(files, client, setRemotePath()); mSize = getFileSize(files, client, getRemotePath());
int reply = client.getReplyCode(); int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) { if (!FTPReply.isPositiveCompletion(reply)) {
if (isUpload) { if (isUpload) {
@ -162,6 +168,16 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
} }
} }
/**
* 处理拦截
*
* @param ftpFiles remotePath路径下的所有文件
* @return {@code false} 拦截器处理任务失败{@code} 拦截器处理任务成功
*/
protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
return true;
}
/** /**
* 检查文件是否存在 * 检查文件是否存在
* *
@ -249,7 +265,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
client.disconnect(); client.disconnect();
failDownload(new AriaIOException(TAG, failDownload(new AriaIOException(TAG,
String.format("无法连接到ftp服务器,filePath: %s, url: %s, errorCode: %s, errorMsg:%s", String.format("无法连接到ftp服务器,filePath: %s, url: %s, errorCode: %s, errorMsg:%s",
mEntity.getKey(), mTaskDelegate.getUrlEntity().url, reply, client.getReplyString())), mEntity.getKey(), mTaskDelegate.getUrlEntity().url, reply,
client.getReplyString())),
true); true);
return null; return null;
} }
@ -367,7 +384,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
* 处理FTP文件信息 * 处理FTP文件信息
* *
* @param remotePath ftp服务器文件夹路径 * @param remotePath ftp服务器文件夹路径
* @param ftpFile ftp服务器上对应的文件 * @param ftpFile ftp服务器上对应的文件
*/ */
protected void handleFile(String remotePath, FTPFile ftpFile) { protected void handleFile(String remotePath, FTPFile ftpFile) {
} }

@ -0,0 +1,100 @@
/*
* 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.ftp;
import android.text.TextUtils;
/**
* Ftp上传拦截器处理
*
* 如果使用者同时实现{@link Builder#resetFileName(String)}{@link Builder#coverServerFile}
* 将默认使用{@link Builder#coverServerFile}
*/
public class FtpInterceptHandler {
private boolean coverServerFile;
private String newFileName;
private boolean stopUpload;
private FtpInterceptHandler() {
}
public boolean isCoverServerFile() {
return coverServerFile;
}
public String getNewFileName() {
return newFileName;
}
public boolean isStopUpload() {
return stopUpload;
}
public static final class Builder {
private boolean coverServerFile = false;
private String newFileName;
private boolean stopUpload = false;
/**
* 如果ftp服务器端已经有同名文件控制是否覆盖远端的同名文件
* 如果你不希望覆盖远端文件可以使用{@link #resetFileName(String)}
*
* @return {@code true} 如果ftp服务器端已经有同名文件覆盖服务器端的同名文件
*/
public Builder coverServerFile() {
coverServerFile = true;
return this;
}
/**
* 如果ftp服务器端已经有同名文件修改该文件上传到远端的文件名该操作不会修改本地文件名
* 如果你希望覆盖远端的同名文件可以使用{@link #coverServerFile()}
*/
public Builder resetFileName(String newFileName) {
this.newFileName = newFileName;
return this;
}
/**
* 如果你希望停止上传任务可以调用该方法
*/
public Builder stopUpload() {
stopUpload = true;
return this;
}
/**
* 如果使用者同时实现{@link Builder#resetFileName(String)}{@link Builder#coverServerFile}
* 将默认使用{@link Builder#coverServerFile}
*/
public FtpInterceptHandler build() {
FtpInterceptHandler handler = new FtpInterceptHandler();
if (stopUpload) {
handler.stopUpload = true;
} else if (coverServerFile) {
handler.coverServerFile = true;
} else if (!TextUtils.isEmpty(newFileName)) {
handler.newFileName = newFileName;
}
return handler;
}
}
}

@ -1,62 +1,75 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* 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.common.ftp; package com.arialyy.aria.core.common.ftp;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.inf.ITargetHeadDelegate; import com.arialyy.aria.core.inf.ITargetHeadDelegate;
import java.net.Proxy; import java.net.Proxy;
/** /**
* fTP任务设置的信息用户名密码端口等信息 * fTP任务设置的信息用户名密码端口等信息
*/ */
public class FtpTaskDelegate implements ITargetHeadDelegate { public class FtpTaskDelegate implements ITargetHeadDelegate {
/** /**
* 账号和密码 * 账号和密码
*/ */
private FtpUrlEntity urlEntity; private FtpUrlEntity urlEntity;
private Proxy proxy; private Proxy proxy;
/** /**
* 字符编码默认为"utf-8" * 字符编码默认为"utf-8"
*/ */
private String charSet = "utf-8"; private String charSet = "utf-8";
public FtpUrlEntity getUrlEntity() { /**
return urlEntity; * 上传拦截器
} */
private IFtpUploadInterceptor uploadInterceptor;
public void setUrlEntity(FtpUrlEntity urlEntity) {
this.urlEntity = urlEntity; public IFtpUploadInterceptor getUploadInterceptor() {
} return uploadInterceptor;
}
public void setProxy(Proxy proxy) {
this.proxy = proxy; public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) {
} this.uploadInterceptor = uploadInterceptor;
}
public Proxy getProxy() {
return proxy; public FtpUrlEntity getUrlEntity() {
} return urlEntity;
}
public String getCharSet() {
return charSet; public void setUrlEntity(FtpUrlEntity urlEntity) {
} this.urlEntity = urlEntity;
}
public void setCharSet(String charSet) {
this.charSet = charSet; public void setProxy(Proxy proxy) {
} this.proxy = proxy;
} }
public Proxy getProxy() {
return proxy;
}
public String getCharSet() {
return charSet;
}
public void setCharSet(String charSet) {
this.charSet = charSet;
}
}

@ -0,0 +1,54 @@
/*
* 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.ftp;
import com.arialyy.aria.core.upload.UploadEntity;
import java.util.List;
/**
* FTP文件上传拦截器如果远端已有同名文件可使用该拦截器控制覆盖文件或修改该文件上传到服务器端端文件名
* simple
* <pre>
* <code>
* Aria.upload(this)
* .loadFtp(FILE_PATH)
* .setUploadUrl(URL)
* .setUploadInterceptor(
* new IFtpUploadInterceptor() {
*
* @Override
* public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
* FtpInterceptHandler.Builder builder = new FtpInterceptHandler.Builder();
* builder.coverServerFile();
* //builder.resetFileName("test");
* return builder.build();
* }
* })
* .start();
* </code>
*
* </pre>
*/
public interface IFtpUploadInterceptor {
/**
* 处理拦截事件
*
* @param entity 上传信息实体
* @param fileList ftp服务器端remotePath下的文件列表
*/
FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList);
}

@ -20,6 +20,7 @@ import android.os.Handler;
import com.arialyy.aria.core.common.BaseListener; import com.arialyy.aria.core.common.BaseListener;
import com.arialyy.aria.core.inf.IDownloadListener; 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.TaskSchedulerType;
import com.arialyy.aria.core.scheduler.ISchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -55,7 +56,8 @@ public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, Do
mEntity.setState(state); mEntity.setState(state);
if (state == IEntity.STATE_CANCEL) { if (state == IEntity.STATE_CANCEL) {
CommonUtil.delTaskRecord(mEntity.getDownloadPath(), 1, mTaskWrapper.isRemoveFile(), true); CommonUtil.delTaskRecord(mEntity.getDownloadPath(), 1, mTaskWrapper.isRemoveFile(),
getTask().getSchedulerType() != TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
return; return;
} else if (state == IEntity.STATE_STOP) { } else if (state == IEntity.STATE_STOP) {
mEntity.setStopTime(System.currentTimeMillis()); mEntity.setStopTime(System.currentTimeMillis());

@ -21,6 +21,7 @@ import com.arialyy.aria.core.common.BaseListener;
import com.arialyy.aria.core.download.group.IDownloadGroupListener; import com.arialyy.aria.core.download.group.IDownloadGroupListener;
import com.arialyy.aria.core.inf.GroupSendParams; import com.arialyy.aria.core.inf.GroupSendParams;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.scheduler.ISchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
@ -134,7 +135,8 @@ class DownloadGroupListener
mTaskWrapper.setState(state); mTaskWrapper.setState(state);
mEntity.setState(state); mEntity.setState(state);
if (state == IEntity.STATE_CANCEL) { if (state == IEntity.STATE_CANCEL) {
CommonUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile()); CommonUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile(),
getTask().getSchedulerType() != TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
return; return;
} else if (state == IEntity.STATE_STOP) { } else if (state == IEntity.STATE_STOP) {
mEntity.setStopTime(System.currentTimeMillis()); mEntity.setStopTime(System.currentTimeMillis());

@ -19,6 +19,7 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
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.common.IUtil;
import com.arialyy.aria.core.download.group.DownloadGroupUtil; import com.arialyy.aria.core.download.group.DownloadGroupUtil;
import com.arialyy.aria.core.download.group.FtpDirDownloadUtil; import com.arialyy.aria.core.download.group.FtpDirDownloadUtil;
import com.arialyy.aria.core.download.group.IDownloadGroupListener; import com.arialyy.aria.core.download.group.IDownloadGroupListener;
@ -38,14 +39,6 @@ public class DownloadGroupTask extends AbsGroupTask<DownloadGroupEntity, DGTaskW
mOutHandler = outHandler; mOutHandler = outHandler;
mContext = AriaManager.APP; mContext = AriaManager.APP;
mListener = new DownloadGroupListener(this, mOutHandler); mListener = new DownloadGroupListener(this, mOutHandler);
switch (taskWrapper.getRequestType()) {
case AbsTaskWrapper.D_HTTP:
mUtil = new DownloadGroupUtil((IDownloadGroupListener) mListener, mTaskWrapper);
break;
case AbsTaskWrapper.D_FTP_DIR:
mUtil = new FtpDirDownloadUtil((IDownloadGroupListener) mListener, mTaskWrapper);
break;
}
} }
public DownloadGroupEntity getEntity() { public DownloadGroupEntity getEntity() {
@ -61,6 +54,16 @@ public class DownloadGroupTask extends AbsGroupTask<DownloadGroupEntity, DGTaskW
return DOWNLOAD_GROUP; return DOWNLOAD_GROUP;
} }
@Override protected synchronized IUtil createUtil() {
switch (mTaskWrapper.getRequestType()) {
case AbsTaskWrapper.D_HTTP:
return new DownloadGroupUtil((IDownloadGroupListener) mListener, mTaskWrapper);
case AbsTaskWrapper.D_FTP_DIR:
return new FtpDirDownloadUtil((IDownloadGroupListener) mListener, mTaskWrapper);
}
return null;
}
public static class Builder { public static class Builder {
DGTaskWrapper taskEntity; DGTaskWrapper taskEntity;
Handler outHandler; Handler outHandler;

@ -19,6 +19,7 @@ package com.arialyy.aria.core.download;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
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.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.IDownloadListener; import com.arialyy.aria.core.inf.IDownloadListener;
@ -37,7 +38,6 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity, DTaskWrapper> {
mOutHandler = outHandler; mOutHandler = outHandler;
mContext = AriaManager.APP; mContext = AriaManager.APP;
mListener = new BaseDListener(this, mOutHandler); mListener = new BaseDListener(this, mOutHandler);
mUtil = new SimpleDownloadUtil(taskWrapper, (IDownloadListener) mListener);
mEntity = taskWrapper.getEntity(); mEntity = taskWrapper.getEntity();
} }
@ -83,6 +83,10 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity, DTaskWrapper> {
return mEntity.getFileName(); return mEntity.getFileName();
} }
@Override protected synchronized IUtil createUtil() {
return new SimpleDownloadUtil(mTaskWrapper, (IDownloadListener) mListener);
}
public static class Builder { public static class Builder {
DTaskWrapper taskEntity; DTaskWrapper taskEntity;
Handler outHandler; Handler outHandler;

@ -44,7 +44,7 @@ class FtpFileInfoThread extends AbsFtpInfoThread<DownloadEntity, DTaskWrapper> {
} }
} }
@Override protected String setRemotePath() { @Override protected String getRemotePath() {
return mTaskWrapper.asFtp().getUrlEntity().remotePath; return mTaskWrapper.asFtp().getUrlEntity().remotePath;
} }

@ -38,7 +38,7 @@ class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTaskWrapp
super(taskEntity, callback); super(taskEntity, callback);
} }
@Override protected String setRemotePath() { @Override protected String getRemotePath() {
return mTaskWrapper.asFtp().getUrlEntity().remotePath; return mTaskWrapper.asFtp().getUrlEntity().remotePath;
} }

@ -34,8 +34,8 @@ public abstract class AbsGroupTask<ENTITY extends AbsEntity, TASK_ENTITY extends
* @param url 子任务下载地址 * @param url 子任务下载地址
*/ */
public void startSubTask(String url) { public void startSubTask(String url) {
if (mUtil != null) { if (getUtil() != null) {
((AbsGroupUtil) mUtil).startSubTask(url); ((AbsGroupUtil) getUtil()).startSubTask(url);
} }
} }
@ -45,8 +45,8 @@ public abstract class AbsGroupTask<ENTITY extends AbsEntity, TASK_ENTITY extends
* @param url 子任务下载地址 * @param url 子任务下载地址
*/ */
public void stopSubTask(String url) { public void stopSubTask(String url) {
if (mUtil != null) { if (getUtil() != null) {
((AbsGroupUtil) mUtil).stopSubTask(url); ((AbsGroupUtil) getUtil()).stopSubTask(url);
} }
} }
} }

@ -23,6 +23,7 @@ import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.normal.CancelCmd; import com.arialyy.aria.core.command.normal.CancelCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.ReStartCmd;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
@ -79,7 +80,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
if (mEntity instanceof AbsNormalEntity) { if (mEntity instanceof AbsNormalEntity) {
CommonUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile()); CommonUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile());
} else if (mEntity instanceof DownloadGroupEntity) { } else if (mEntity instanceof DownloadGroupEntity) {
CommonUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile()); CommonUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(), true);
} }
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey()); TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
} }
@ -370,8 +371,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void reStart() { @Override public void reStart() {
if (checkConfig()) { if (checkConfig()) {
cancel(); ReStartCmd cmd =
start(); (ReStartCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_RESTART,
checkTaskType());
AriaManager.getInstance(AriaManager.APP).setCmd(cmd).exe();
} }
} }
@ -409,6 +412,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
} }
@Override public void start(int type) {
}
@Override public void stop() { @Override public void stop() {
} }
@ -421,6 +428,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
} }
@Override public void cancel(int type) {
}
@Override public Object getExpand(String key) { @Override public Object getExpand(String key) {
return null; return null;
} }

@ -18,6 +18,8 @@ package com.arialyy.aria.core.inf;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -40,7 +42,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
protected Context mContext; protected Context mContext;
boolean isHeighestTask = false; boolean isHeighestTask = false;
private boolean isCancel = false, isStop = false; private boolean isCancel = false, isStop = false;
protected IUtil mUtil; private IUtil mUtil;
/** /**
* 扩展信息 * 扩展信息
*/ */
@ -62,6 +64,15 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
return mOutHandler; return mOutHandler;
} }
protected abstract IUtil createUtil();
protected synchronized IUtil getUtil() {
if (mUtil == null) {
mUtil = createUtil();
}
return mUtil;
}
/** /**
* 添加扩展数据 读取扩展数据{@link #getExpand(String)} * 添加扩展数据 读取扩展数据{@link #getExpand(String)}
*/ */
@ -98,8 +109,8 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* @param speed 单位为kb * @param speed 单位为kb
*/ */
public void setMaxSpeed(int speed) { public void setMaxSpeed(int speed) {
if (mUtil != null) { if (getUtil() != null) {
mUtil.setMaxSpeed(speed); getUtil().setMaxSpeed(speed);
} }
} }
@ -183,10 +194,25 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
} }
@Override public void start() { @Override public void start() {
if (mUtil.isRunning()) { start(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void start(@TaskSchedulerType int type) {
mSchedulerType = type;
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getUtil().isRunning()) {
ALog.e(TAG, String.format("任务【%s】重启失败", getTaskName()));
return;
}
mUtil = createUtil();
mUtil.start();
ALog.d(TAG, String.format("任务【%s】重启成功", getTaskName()));
return;
}
if (getUtil().isRunning()) {
ALog.d(TAG, "任务正在下载"); ALog.d(TAG, "任务正在下载");
} else { } else {
mUtil.start(); getUtil().start();
} }
} }
@ -197,8 +223,8 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
@Override public void stop(@TaskSchedulerType int type) { @Override public void stop(@TaskSchedulerType int type) {
isStop = true; isStop = true;
mSchedulerType = type; mSchedulerType = type;
if (mUtil.isRunning()) { if (getUtil().isRunning()) {
mUtil.stop(); getUtil().stop();
} else { } else {
ALog.d(TAG, "下载任务未执行"); ALog.d(TAG, "下载任务未执行");
mListener.onStop(mEntity.getCurrentProgress()); mListener.onStop(mEntity.getCurrentProgress());
@ -206,11 +232,16 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
} }
@Override public void cancel() { @Override public void cancel() {
cancel(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void cancel(@TaskSchedulerType int type) {
isCancel = true; isCancel = true;
if (!mUtil.isRunning()) { mSchedulerType = type;
if (!getUtil().isRunning()) {
mListener.onCancel(); mListener.onCancel();
} else { } else {
mUtil.cancel(); getUtil().cancel();
} }
} }
@ -220,7 +251,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* @return {@code true} 正在下载 * @return {@code true} 正在下载
*/ */
@Override public boolean isRunning() { @Override public boolean isRunning() {
return mUtil.isRunning(); return getUtil().isRunning();
} }
/** /**

@ -79,8 +79,18 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/ */
TASK_WRAPPER getTaskWrapper(); TASK_WRAPPER getTaskWrapper();
/**
* 启动任务
*/
void start(); void start();
/**
* 启动任务
*
* @param type {@link TaskSchedulerType}
*/
void start(@TaskSchedulerType int type);
/** /**
* 停止任务 * 停止任务
*/ */
@ -89,15 +99,22 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
/** /**
* 停止任务 * 停止任务
* *
* @param type {@code 0}默认操作{@code 1}停止任务不自动执行下一任务 * @param type {@link TaskSchedulerType}
*/ */
void stop(int type); void stop(@TaskSchedulerType int type);
/** /**
* 删除任务 * 删除任务
*/ */
void cancel(); void cancel();
/**
* 停止任务
*
* @param type {@link TaskSchedulerType}
*/
void cancel(@TaskSchedulerType int type);
/** /**
* 读取扩展数据 * 读取扩展数据
*/ */
@ -134,6 +151,4 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
* {@link TaskSchedulerType} * {@link TaskSchedulerType}
*/ */
int getSchedulerType(); int getSchedulerType();
} }

@ -7,7 +7,9 @@ import java.lang.annotation.RetentionPolicy;
@IntDef({ @IntDef({
TaskSchedulerType.TYPE_DEFAULT, TaskSchedulerType.TYPE_DEFAULT,
TaskSchedulerType.TYPE_STOP_NOT_NEXT, TaskSchedulerType.TYPE_STOP_NOT_NEXT,
TaskSchedulerType.TYPE_STOP_AND_WAIT TaskSchedulerType.TYPE_STOP_AND_WAIT,
TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY,
TaskSchedulerType.TYPE_START_AND_RESET_STATE
}) })
@Retention(RetentionPolicy.SOURCE) public @interface TaskSchedulerType { @Retention(RetentionPolicy.SOURCE) public @interface TaskSchedulerType {
int TYPE_DEFAULT = 1; int TYPE_DEFAULT = 1;
@ -19,4 +21,14 @@ import java.lang.annotation.RetentionPolicy;
* 停止任务并让当前任务处于等待状态 * 停止任务并让当前任务处于等待状态
*/ */
int TYPE_STOP_AND_WAIT = 3; int TYPE_STOP_AND_WAIT = 3;
/**
* 删除任务并且不通知回调
*/
int TYPE_CANCEL_AND_NOT_NOTIFY = 4;
/**
* 重置状态并启动任务
*/
int TYPE_START_AND_RESET_STATE = 5;
} }

@ -17,6 +17,7 @@
package com.arialyy.aria.core.manager; package com.arialyy.aria.core.manager;
import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.AbsThreadTask;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -24,25 +25,26 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* 线程任务管理器 * 线程任务管理器
*/ */
public class ThreadTaskManager { public class ThreadTaskManager {
private static volatile ThreadTaskManager INSTANCE = null; private static volatile ThreadTaskManager INSTANCE = null;
private static final Object LOCK = new Object();
private final String TAG = "ThreadTaskManager"; private final String TAG = "ThreadTaskManager";
private ExecutorService mExePool; private ExecutorService mExePool;
private Map<String, Set<Future>> mThreadTasks = new HashMap<>(); private Map<String, Set<FutureContainer>> mThreadTasks = new ConcurrentHashMap<>();
private static final ReentrantLock LOCK = new ReentrantLock();
public static ThreadTaskManager getInstance() { public static synchronized ThreadTaskManager getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { INSTANCE = new ThreadTaskManager();
INSTANCE = new ThreadTaskManager();
}
} }
return INSTANCE; return INSTANCE;
} }
@ -57,21 +59,37 @@ public class ThreadTaskManager {
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()} * @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
* @param threadTask 线程任务{@link AbsThreadTask} * @param threadTask 线程任务{@link AbsThreadTask}
*/ */
public synchronized void startThread(String key, AbsThreadTask threadTask) { public void startThread(String key, AbsThreadTask threadTask) {
if (mExePool.isShutdown()) { try {
ALog.e(TAG, "线程池已经关闭"); LOCK.tryLock(2, TimeUnit.SECONDS);
return; if (mExePool.isShutdown()) {
} ALog.e(TAG, "线程池已经关闭");
key = getKey(key); return;
Set<Future> temp = mThreadTasks.get(key); }
if (temp == null) { key = getKey(key);
temp = new HashSet<>(); Set<FutureContainer> temp = mThreadTasks.get(key);
mThreadTasks.put(key, temp); if (temp == null) {
temp = new HashSet<>();
mThreadTasks.put(key, temp);
}
FutureContainer container = new FutureContainer();
container.threadTask = threadTask;
container.future = mExePool.submit(threadTask);
temp.add(container);
} catch (Exception e) {
e.printStackTrace();
} finally {
LOCK.unlock();
} }
temp.add(mExePool.submit(threadTask));
} }
public synchronized boolean taskIsRunning(String key){ /**
* 任务是否在执行
*
* @param key 任务的key{@link AbsTask#getKey()}
* @return {@code true} 任务正在运行
*/
public boolean taskIsRunning(String key) {
return mThreadTasks.get(getKey(key)) != null; return mThreadTasks.get(getKey(key)) != null;
} }
@ -80,29 +98,31 @@ public class ThreadTaskManager {
* *
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()} * @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
*/ */
public synchronized void removeTaskThread(String key) { public void removeTaskThread(String key) {
if (mExePool.isShutdown()) { try {
ALog.e(TAG, "线程池已经关闭");
return; LOCK.tryLock(2, TimeUnit.SECONDS);
} if (mExePool.isShutdown()) {
key = getKey(key); ALog.e(TAG, "线程池已经关闭");
Set<Future> temp = mThreadTasks.get(key); return;
if (temp != null && temp.size() > 0) { }
try { key = getKey(key);
for (Future future : temp) { Set<FutureContainer> temp = mThreadTasks.get(key);
if (future.isDone() || future.isCancelled()) { if (temp != null && temp.size() > 0) {
for (FutureContainer container : temp) {
if (container.future.isDone() || container.future.isCancelled()) {
continue; continue;
} }
AbsThreadTask task = (AbsThreadTask) future.get(); container.threadTask.setInterrupted(true);
task.setInterrupted(true);
future.cancel(true);
} }
} catch (Exception e) { temp.clear();
ALog.e(TAG, e);
} }
temp.clear(); mThreadTasks.remove(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
LOCK.unlock();
} }
mThreadTasks.remove(key);
} }
/** /**
@ -110,21 +130,28 @@ public class ThreadTaskManager {
* *
* @param task 线程任务 * @param task 线程任务
*/ */
public synchronized void retryThread(AbsThreadTask task) { public void retryThread(AbsThreadTask task) {
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
try { try {
if (task == null || task.isInterrupted()) { LOCK.tryLock(2, TimeUnit.SECONDS);
ALog.e(TAG, "线程为空或线程已经中断"); if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
try {
if (task == null || task.isInterrupted()) {
ALog.e(TAG, "线程为空或线程已经中断");
return;
}
} catch (Exception e) {
ALog.e(TAG, e);
return; return;
} }
mExePool.submit(task);
} catch (Exception e) { } catch (Exception e) {
ALog.e(TAG, e); e.printStackTrace();
return; } finally {
LOCK.unlock();
} }
mExePool.submit(task);
} }
/** /**
@ -136,4 +163,9 @@ public class ThreadTaskManager {
private String getKey(String key) { private String getKey(String key) {
return CommonUtil.getStrMd5(key); return CommonUtil.getStrMd5(key);
} }
private class FutureContainer {
Future future;
AbsThreadTask threadTask;
}
} }

@ -194,16 +194,26 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
if (task.getState() == IEntity.STATE_WAIT) { if (task.getState() == IEntity.STATE_WAIT) {
break; break;
} }
mQueue.removeTaskFormQueue(task.getKey());
if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) {
ALog.d(TAG, String.format("停止任务【%s】成功,尝试开始下一任务", task.getTaskName()));
startNextTask(task);
} else {
ALog.d(TAG, String.format("停止任务【%s】成功", task.getTaskName()));
}
break;
case CANCEL: case CANCEL:
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) { if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) {
ALog.d(TAG, "stop_next"); ALog.d(TAG, String.format("删除任务【%s】成功,尝试开始下一任务", task.getTaskName()));
startNextTask(task); startNextTask(task);
} else {
ALog.d(TAG, String.format("删除任务【%s】成功", task.getTaskName()));
} }
break; break;
case COMPLETE: case COMPLETE:
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
ALog.d(TAG, "complete_next"); ALog.d(TAG, String.format("任务【%s】处理完成", task.getTaskName()));
startNextTask(task); startNextTask(task);
break; break;
case FAIL: case FAIL:

@ -19,6 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.common.BaseListener; import com.arialyy.aria.core.common.BaseListener;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IUploadListener; import com.arialyy.aria.core.inf.IUploadListener;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
/** /**
@ -36,7 +37,8 @@ class BaseUListener extends BaseListener<UploadEntity, UTaskWrapper, UploadTask>
mTaskWrapper.setState(state); mTaskWrapper.setState(state);
mEntity.setState(state); mEntity.setState(state);
if (state == IEntity.STATE_CANCEL) { if (state == IEntity.STATE_CANCEL) {
CommonUtil.delTaskRecord(mEntity.getFilePath(), 2, mTaskWrapper.isRemoveFile(), true); CommonUtil.delTaskRecord(mEntity.getFilePath(), 2, mTaskWrapper.isRemoveFile(),
getTask().getSchedulerType() != TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
} else if (state == IEntity.STATE_STOP) { } else if (state == IEntity.STATE_STOP) {
mEntity.setStopTime(System.currentTimeMillis()); mEntity.setStopTime(System.currentTimeMillis());
} else if (state == IEntity.STATE_COMPLETE) { } else if (state == IEntity.STATE_COMPLETE) {

@ -16,11 +16,13 @@
package com.arialyy.aria.core.upload; package com.arialyy.aria.core.upload;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.ftp.FTPSDelegate; import com.arialyy.aria.core.common.ftp.FTPSDelegate;
import com.arialyy.aria.core.common.ftp.FtpDelegate; import com.arialyy.aria.core.common.ftp.FtpDelegate;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IFtpTarget; import com.arialyy.aria.core.inf.IFtpTarget;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CheckUtil;
import java.net.Proxy; import java.net.Proxy;
@ -53,6 +55,14 @@ public class FtpUploadTarget extends AbsUploadTarget<FtpUploadTarget>
return this; return this;
} }
/**
* FTP文件上传拦截器如果远端已有同名文件可使用该拦截器控制覆盖文件或修改该文件上传到服务器端端的文件名
*/
@CheckResult
public FtpUploadTarget setUploadInterceptor(@NonNull IFtpUploadInterceptor uploadInterceptor) {
return mNormalDelegate.setUploadInterceptor(uploadInterceptor);
}
/** /**
* 是否是FTPS协议 * 是否是FTPS协议
* 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)} * 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)}

@ -17,6 +17,7 @@ package com.arialyy.aria.core.upload;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.core.inf.INormalTarget; import com.arialyy.aria.core.inf.INormalTarget;
import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue;
@ -61,6 +62,14 @@ class UNormalDelegate<TARGET extends AbsUploadTarget> implements INormalTarget {
return mTarget; return mTarget;
} }
TARGET setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) {
if (uploadInterceptor == null) {
throw new NullPointerException("ftp拦截器为空");
}
mTarget.getTaskWrapper().asFtp().setUploadInterceptor(uploadInterceptor);
return mTarget;
}
@Override public AbsEntity getEntity() { @Override public AbsEntity getEntity() {
return mEntity; return mEntity;
} }
@ -82,10 +91,10 @@ class UNormalDelegate<TARGET extends AbsUploadTarget> implements INormalTarget {
if (mTarget.getTaskWrapper().asFtp().getUrlEntity() != null && mTarget.getTaskWrapper() if (mTarget.getTaskWrapper().asFtp().getUrlEntity() != null && mTarget.getTaskWrapper()
.asFtp() .asFtp()
.getUrlEntity().isFtps) { .getUrlEntity().isFtps) {
//if (TextUtils.isEmpty(mTaskWrapper.getUrlEntity().storePath)) { if (TextUtils.isEmpty(mTarget.getTaskWrapper().asFtp().getUrlEntity().storePath)) {
// ALog.e(TAG, "证书路径为空"); ALog.e(TAG, "证书路径为空");
// return false; return false;
//} }
if (TextUtils.isEmpty(mTarget.getTaskWrapper().asFtp().getUrlEntity().keyAlias)) { if (TextUtils.isEmpty(mTarget.getTaskWrapper().asFtp().getUrlEntity().keyAlias)) {
ALog.e(TAG, "证书别名为空"); ALog.e(TAG, "证书别名为空");
return false; return false;

@ -15,17 +15,25 @@
*/ */
package com.arialyy.aria.core.upload.uploader; package com.arialyy.aria.core.upload.uploader;
import android.text.TextUtils;
import aria.apache.commons.net.ftp.FTPClient;
import aria.apache.commons.net.ftp.FTPFile; import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.common.ftp.AbsFtpInfoThread; import com.arialyy.aria.core.common.ftp.AbsFtpInfoThread;
import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.OnFileInfoCallback; import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.common.TaskRecord;
import com.arialyy.aria.core.common.ThreadRecord; import com.arialyy.aria.core.common.ThreadRecord;
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
import com.arialyy.aria.core.common.ftp.FtpInterceptHandler;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.DbDataHelper; import com.arialyy.aria.util.DbDataHelper;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* Created by Aria.Lao on 2017/9/26. * Created by Aria.Lao on 2017/9/26.
@ -35,13 +43,71 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
private static final String TAG = "FtpUploadFileInfoThread"; private static final String TAG = "FtpUploadFileInfoThread";
static final int CODE_COMPLETE = 0xab1; static final int CODE_COMPLETE = 0xab1;
private boolean isComplete = false; private boolean isComplete = false;
private String remotePath;
/**
* true 使用拦截器false 不使用拦截器
*/
private boolean useInterceptor = false;
FtpFileInfoThread(UTaskWrapper taskEntity, OnFileInfoCallback callback) { FtpFileInfoThread(UTaskWrapper taskEntity, OnFileInfoCallback callback) {
super(taskEntity, callback); super(taskEntity, callback);
} }
@Override protected String setRemotePath() { @Override protected String getRemotePath() {
return mTaskWrapper.asFtp().getUrlEntity().remotePath + "/" + mEntity.getFileName(); return remotePath == null ?
mTaskWrapper.asFtp().getUrlEntity().remotePath + "/" + mEntity.getFileName() : remotePath;
}
@Override protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
try {
IFtpUploadInterceptor interceptor = mTaskWrapper.asFtp().getUploadInterceptor();
if (interceptor != null) {
useInterceptor = true;
List<String> files = new ArrayList<>();
for (FTPFile ftpFile : ftpFiles) {
if (ftpFile.isDirectory()) {
continue;
}
files.add(ftpFile.getName());
}
FtpInterceptHandler interceptHandler = interceptor.onIntercept(mEntity, files);
if (interceptHandler.isStopUpload()) {
// TODO: 2019-05-22 操作任务停止
return true;
}
/*
处理远端有同名文件的情况
*/
if (files.contains(mEntity.getFileName())) {
if (interceptHandler.isCoverServerFile()) {
ALog.i(TAG, String.format("远端已拥有同名文件,将覆盖该文件,文件名:%s", mEntity.getFileName()));
boolean b = client.deleteFile(
new String(getRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET));
ALog.d(TAG,
String.format("删除文件%s,code: %s, msg: %s", b ? "成功" : "失败", client.getReplyCode(),
client.getReplyString()));
} else if (!TextUtils.isEmpty(interceptHandler.getNewFileName())) {
ALog.i(TAG, String.format("远端已拥有同名文件,将修改remotePath,文件名:%s,remotePath:%s",
mEntity.getFileName(), interceptHandler.getNewFileName()));
remotePath = mTaskWrapper.asFtp().getUrlEntity().remotePath
+ "/"
+ interceptHandler.getNewFileName();
client.disconnect();
run();
}
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
mTaskWrapper.asFtp().setUploadInterceptor(null);
}
return true;
} }
/** /**
@ -54,7 +120,7 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
*/ */
@Override protected void handleFile(String remotePath, FTPFile ftpFile) { @Override protected void handleFile(String remotePath, FTPFile ftpFile) {
super.handleFile(remotePath, ftpFile); super.handleFile(remotePath, ftpFile);
if (ftpFile != null) { if (ftpFile != null && !useInterceptor) {
//远程文件已完成 //远程文件已完成
if (ftpFile.getSize() == mEntity.getFileSize()) { if (ftpFile.getSize() == mEntity.getFileSize()) {
isComplete = true; isComplete = true;

@ -37,6 +37,7 @@ public class SimpleUploadUtil implements IUtil, Runnable {
private UTaskWrapper mTaskWrapper; private UTaskWrapper mTaskWrapper;
private IUploadListener mListener; private IUploadListener mListener;
private Uploader mUploader; private Uploader mUploader;
private boolean isStop = false, isCancel = false;
public SimpleUploadUtil(UTaskWrapper taskWrapper, IUploadListener listener) { public SimpleUploadUtil(UTaskWrapper taskWrapper, IUploadListener listener) {
mTaskWrapper = taskWrapper; mTaskWrapper = taskWrapper;
@ -90,14 +91,19 @@ public class SimpleUploadUtil implements IUtil, Runnable {
} }
@Override public void cancel() { @Override public void cancel() {
isCancel = true;
mUploader.cancel(); mUploader.cancel();
} }
@Override public void stop() { @Override public void stop() {
isStop = true;
mUploader.stop(); mUploader.stop();
} }
@Override public void start() { @Override public void start() {
if (isStop || isCancel) {
return;
}
new Thread(this).start(); new Thread(this).start();
} }

@ -0,0 +1,32 @@
/*
* 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.exception;
/**
* Created by lyy on 2017/1/18.
* Aria 文件异常
*/
public class FileNotFoundException extends BaseException {
private static final String ARIA_FILE_EXCEPTION = "Aria File not found Exception:";
public FileNotFoundException(String tag, String detailMessage) {
super(tag, String.format("%s%s", ARIA_FILE_EXCEPTION, detailMessage));
}
public FileNotFoundException(String tag, String message, Exception e){
super(tag, message, e);
}
}

@ -600,7 +600,7 @@ public class CommonUtil {
} }
DownloadGroupEntity groupEntity = DbDataHelper.getDGEntity(groupHash); DownloadGroupEntity groupEntity = DbDataHelper.getDGEntity(groupHash);
delGroupTaskRecord(groupEntity, removeFile); delGroupTaskRecord(groupEntity, removeFile, true);
} }
/** /**
@ -608,7 +608,8 @@ public class CommonUtil {
* *
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件 {@code false}如果任务已经完成只删除任务数据库记录 * @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件 {@code false}如果任务已经完成只删除任务数据库记录
*/ */
public static void delGroupTaskRecord(DownloadGroupEntity groupEntity, boolean removeFile) { public static void delGroupTaskRecord(DownloadGroupEntity groupEntity, boolean removeFile,
boolean removeEntity) {
if (groupEntity == null) { if (groupEntity == null) {
ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null"); ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null");
return; return;
@ -654,8 +655,10 @@ public class CommonUtil {
dir.delete(); dir.delete();
} }
} }
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash()); if (removeEntity) {
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash()); DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash());
}
} }
/** /**

@ -1,4 +1,6 @@
## 开发日志 ## 开发日志
+ v_3.6.5
- fix bug https://github.com/AriaLyy/Aria/issues/403
+ v_3.6.4 (2019/5/16) + v_3.6.4 (2019/5/16)
- 优化任务接收器的代码结构 - 优化任务接收器的代码结构
- 修复`DbEntity.saveAll()`失败的问题 - 修复`DbEntity.saveAll()`失败的问题

@ -1,7 +1,7 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
//apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion rootProject.ext.compileSdkVersion compileSdkVersion rootProject.ext.compileSdkVersion
@ -46,8 +46,9 @@ dependencies {
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}" implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:design:${rootProject.ext.supportLibVersion}" implementation "com.android.support:design:${rootProject.ext.supportLibVersion}"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlin_version}"
api project(':Aria') api project(':Aria')
annotationProcessor project(':AriaCompiler') kapt project(':AriaCompiler')
// compile 'com.arialyy.aria:aria-core:3.4.0' // compile 'com.arialyy.aria:aria-core:3.4.0'
// annotationProcessor 'com.arialyy.aria:aria-compiler:3.4' // annotationProcessor 'com.arialyy.aria:aria-compiler:3.4'

@ -41,6 +41,7 @@
<activity android:name=".core.download.group.FTPDirDownloadActivity"/> <activity android:name=".core.download.group.FTPDirDownloadActivity"/>
<activity android:name=".core.upload.HttpUploadActivity"/> <activity android:name=".core.upload.HttpUploadActivity"/>
<activity android:name=".core.upload.FtpUploadActivity"/> <activity android:name=".core.upload.FtpUploadActivity"/>
<activity android:name=".core.download.KotlinDownloadActivity"/>
<service android:name=".core.download.service_download.DownloadService"/> <service android:name=".core.download.service_download.DownloadService"/>
</application> </application>

@ -72,6 +72,7 @@ public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding>
module.startNextActivity(data.get(position), HighestPriorityActivity.class); module.startNextActivity(data.get(position), HighestPriorityActivity.class);
break; break;
case 3: case 3:
module.startNextActivity(data.get(position), KotlinDownloadActivity.class);
break; break;
case 4: case 4:
break; break;

@ -1,75 +1,166 @@
//package com.arialyy.simple.core.download package com.arialyy.simple.core.download
//
//import android.os.Bundle import android.os.Bundle
//import android.os.Environment import android.os.Environment
//import android.support.v7.app.AppCompatActivity import android.util.Log
//import android.util.Log import android.view.View
//import android.view.View import android.widget.Button
//import com.arialyy.annotations.Download import android.widget.Toast
//import com.arialyy.aria.core.Aria import com.arialyy.annotations.Download
//import com.arialyy.aria.core.download.DownloadTask import com.arialyy.aria.core.Aria
//import com.arialyy.simple.R import com.arialyy.aria.core.download.DownloadTarget
//import com.arialyy.simple.base.BaseActivity import com.arialyy.aria.core.download.DownloadTask
// import com.arialyy.aria.core.inf.IEntity
///** import com.arialyy.frame.util.show.T
// * Created by lyy on 2017/10/23. import com.arialyy.simple.R
// */ import com.arialyy.simple.base.BaseActivity
//class KotlinDownloadActivity : AppCompatActivity() { import com.arialyy.simple.databinding.ActivitySingleBinding
//
// private val DOWNLOAD_URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk" /**
// * Created by lyy on 2017/10/23.
// private val TAG = "KotlinDownloadActivity"; */
// class KotlinDownloadActivity : BaseActivity<ActivitySingleBinding>() {
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState) private val DOWNLOAD_URL =
// setContentView(setLayoutId()) "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"
// }
// private lateinit var mStart: Button
// fun setLayoutId(): Int { private lateinit var mStop: Button
// return R.layout.activity_single private lateinit var mCancel: Button
// } private lateinit var target: DownloadTarget
//
// fun init(savedInstanceState: Bundle?) { override fun setLayoutId(): Int {
// title = "单任务下载" return R.layout.activity_single
//// val target = Aria.download(this).load(DOWNLOAD_URL) }
//// binding.progress = target.getPercent()
//// if (target.getTaskState() == IEntity.STATE_STOP) { override fun init(savedInstanceState: Bundle?) {
//// mStart.setText("恢复") title = "kotlin测试"
//// mStart.setTextColor(resources.getColor(android.R.color.holo_blue_light)) Aria.get(this)
//// setBtState(true) .downloadConfig.maxTaskNum = 2
//// } else if (target.isDownloading()) { Aria.download(this)
//// setBtState(false) .register()
//// } mStart = findViewById(R.id.start)
//// binding.fileSize = target.getConvertFileSize() mStop = findViewById(R.id.stop)
// Aria.get(this).downloadConfig.maxTaskNum = 2 mCancel = findViewById(R.id.cancel)
// Aria.download(this).register() mStop.visibility = View.GONE
// }
// target = Aria.download(this)
// @Download.onTaskRunning .load(DOWNLOAD_URL)
// protected fun running(task: DownloadTask) { binding.progress = target.percent
// Log.d(TAG, task.percent.toString() + "") if (target.taskState == IEntity.STATE_STOP) {
//// val len = task.fileSize mStart.text = "恢复"
//// if (len == 0L) { } else if (target.isRunning) {
//// binding.progress = 0 mStart.text = "停止"
//// } else { }
//// binding.progress = task.percent binding.fileSize = target.convertFileSize
//// } }
//// binding.speed = task.convertSpeed
// } /**
// * 注解方法不能添加internal修饰符否则会出现e: [kapt] An exception occurred: java.lang.IllegalArgumentException: index 1 for '$a' not in range (received 0 arguments)错误
// fun onClick(view: View) { */
// when (view.id) { @Download.onTaskRunning
// R.id.start -> startD() fun running(task: DownloadTask) {
// R.id.stop -> Aria.download(this).load(DOWNLOAD_URL).stop() Log.d(TAG, task.percent.toString())
// R.id.cancel -> Aria.download(this).load(DOWNLOAD_URL).cancel() val len = task.fileSize
// } if (len == 0L) {
// } binding.progress = 0
// } else {
// private fun startD() { binding.progress = task.percent
// Aria.download(this) }
// .load(DOWNLOAD_URL) binding.speed = task.convertSpeed
// .addHeader("groupHash", "value") }
// .setDownloadPath(Environment.getExternalStorageDirectory().path + "/hhhhhhhh.apk")
// .start() @Download.onWait
// } fun onWait(task: DownloadTask) {
//} if (task.key == DOWNLOAD_URL) {
Log.d(TAG, "wait ==> " + task.downloadEntity.fileName)
}
}
@Download.onPre
fun onPre(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "停止"
}
}
@Download.onTaskStart
fun taskStart(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
binding.fileSize = task.convertFileSize
}
}
@Download.onTaskComplete
fun complete(task: DownloadTask) {
Log.d(TAG, "完成")
}
@Download.onTaskResume
fun taskResume(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "停止"
}
}
@Download.onTaskStop
fun taskStop(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
mStart.text = "恢复"
binding.speed = ""
}
}
@Download.onTaskCancel
fun taskCancel(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
binding.progress = 0
Toast.makeText(this@KotlinDownloadActivity, "取消下载", Toast.LENGTH_SHORT)
.show()
mStart.text = "开始"
binding.speed = ""
Log.d(TAG, "cancel")
}
}
@Download.onTaskFail
fun taskFail(task: DownloadTask) {
if (task.key == DOWNLOAD_URL) {
Toast.makeText(this@KotlinDownloadActivity, "下载失败", Toast.LENGTH_SHORT)
.show()
mStart.text = "开始"
}
}
@Download.onNoSupportBreakPoint
fun onNoSupportBreakPoint(task: DownloadTask) {
Log.d(TAG, "该下载链接不支持断点")
if (task.key == DOWNLOAD_URL) {
T.showShort(this@KotlinDownloadActivity, "该下载链接不支持断点")
}
}
fun onClick(view: View) {
when (view.id) {
R.id.start -> {
if (target.isRunning) {
Aria.download(this)
.load(DOWNLOAD_URL)
.stop()
} else {
startD()
}
}
R.id.stop -> Aria.download(this).load(DOWNLOAD_URL).stop()
R.id.cancel -> Aria.download(this).load(DOWNLOAD_URL).cancel()
}
}
private fun startD() {
Aria.download(this)
.load(DOWNLOAD_URL)
.addHeader("groupHash", "value")
.setFilePath(Environment.getExternalStorageDirectory().path + "/kotlin.apk")
.start()
}
}

@ -64,9 +64,10 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"http://kotlinlang.org/docs/kotlin-docs.pdf";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
//"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apks"; //"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apks";
"http://hzdown.muzhiwan.com/2017/05/08/nl.noio.kingdom_59104935e56f0.apk";
//"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip"; //"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip";
//"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip"; //"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip";
"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk"; //"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
//"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked //"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked
//"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载 //"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
//"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1"; //"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1";
@ -299,7 +300,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
Aria.download(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).stop();
break; break;
case R.id.cancel: case R.id.cancel:
Aria.download(this).load(DOWNLOAD_URL).cancel(true); Aria.download(this).load(DOWNLOAD_URL).reStart();
//Aria.download(this).load(DOWNLOAD_URL).cancel(true);
//Aria.download(this).load(DOWNLOAD_URL).removeRecord(); //Aria.download(this).load(DOWNLOAD_URL).removeRecord();
break; break;
} }

@ -1,113 +1,126 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* 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.simple.core.upload; package com.arialyy.simple.core.upload;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import com.arialyy.annotations.Upload; import com.arialyy.annotations.Upload;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.common.ftp.FtpInterceptHandler;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.frame.util.FileUtil; import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.frame.util.show.T; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.simple.R; import com.arialyy.frame.util.FileUtil;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.frame.util.show.T;
import com.arialyy.simple.databinding.ActivityFtpUploadBinding; import com.arialyy.simple.R;
import java.io.File; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
/** import java.io.File;
* Created by lyy on 2017/7/28. Ftp 文件上传demo import java.util.List;
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> { /**
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar"; * Created by lyy on 2017/7/28. Ftp 文件上传demo
private final String URL = "ftp://9.9.9.205:2121/aa/你好"; */
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
@Override protected void init(Bundle savedInstanceState) { private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
setTile("D_FTP 文件上传"); private final String URL = "ftp://9.9.9.205:2121/aa/你好";
super.init(savedInstanceState);
Aria.upload(this).register(); @Override protected void init(Bundle savedInstanceState) {
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH); setTile("D_FTP 文件上传");
if (entity != null) { super.init(savedInstanceState);
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize())); Aria.upload(this).register();
getBinding().setProgress(entity.isComplete() ? 100 UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); if (entity != null) {
} getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
} getBinding().setProgress(entity.isComplete() ? 100
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
@Override protected int setLayoutId() { }
return R.layout.activity_ftp_upload; }
}
@Override protected int setLayoutId() {
public void onClick(View view) { return R.layout.activity_ftp_upload;
switch (view.getId()) { }
case R.id.start:
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start(); public void onClick(View view) {
break; switch (view.getId()) {
case R.id.stop: case R.id.start:
Aria.upload(this).loadFtp(FILE_PATH).stop(); Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).setUploadInterceptor(
break; new IFtpUploadInterceptor() {
case R.id.cancel:
Aria.upload(this).loadFtp(FILE_PATH).cancel(); @Override
break; public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
} FtpInterceptHandler.Builder builder = new FtpInterceptHandler.Builder();
} builder.coverServerFile();
//builder.resetFileName("test");
@Upload.onWait void onWait(UploadTask task) { return builder.build();
Log.d(TAG, task.getTaskName() + "_wait"); }
} }).login("lao", "123456").start();
break;
@Upload.onPre public void onPre(UploadTask task) { case R.id.stop:
getBinding().setFileSize(task.getConvertFileSize()); Aria.upload(this).loadFtp(FILE_PATH).stop();
} break;
case R.id.cancel:
@Upload.onTaskStart public void taskStart(UploadTask task) { Aria.upload(this).loadFtp(FILE_PATH).cancel();
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath()))); break;
} }
}
@Upload.onTaskResume public void taskResume(UploadTask task) {
Log.d(TAG, "恢复上传"); @Upload.onWait void onWait(UploadTask task) {
} Log.d(TAG, task.getTaskName() + "_wait");
}
@Upload.onTaskStop public void taskStop(UploadTask task) {
getBinding().setSpeed(""); @Upload.onPre public void onPre(UploadTask task) {
Log.d(TAG, "停止上传"); getBinding().setFileSize(task.getConvertFileSize());
} }
@Upload.onTaskCancel public void taskCancel(UploadTask task) { @Upload.onTaskStart public void taskStart(UploadTask task) {
getBinding().setSpeed(""); Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
getBinding().setFileSize(""); }
getBinding().setProgress(0);
Log.d(TAG, "删除任务"); @Upload.onTaskResume public void taskResume(UploadTask task) {
} Log.d(TAG, "恢复上传");
}
@Upload.onTaskFail public void taskFail(UploadTask task) {
Log.d(TAG, "上传失败"); @Upload.onTaskStop public void taskStop(UploadTask task) {
} getBinding().setSpeed("");
Log.d(TAG, "停止上传");
@Upload.onTaskRunning public void taskRunning(UploadTask task) { }
Log.d(TAG, "PP = " + task.getPercent());
getBinding().setProgress(task.getPercent()); @Upload.onTaskCancel public void taskCancel(UploadTask task) {
getBinding().setSpeed(task.getConvertSpeed()); getBinding().setSpeed("");
} getBinding().setFileSize("");
getBinding().setProgress(0);
@Upload.onTaskComplete public void taskComplete(UploadTask task) { Log.d(TAG, "删除任务");
getBinding().setProgress(100); }
getBinding().setSpeed("");
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成"); @Upload.onTaskFail public void taskFail(UploadTask task) {
} Log.d(TAG, "上传失败");
} }
@Upload.onTaskRunning public void taskRunning(UploadTask task) {
Log.d(TAG, "PP = " + task.getPercent());
getBinding().setProgress(task.getPercent());
getBinding().setSpeed(task.getConvertSpeed());
}
@Upload.onTaskComplete public void taskComplete(UploadTask task) {
getBinding().setProgress(100);
getBinding().setSpeed("");
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成");
}
}

@ -65,6 +65,7 @@ public class CommonModule extends AbsModule {
R.drawable.ic_http, R.drawable.ic_http,
R.drawable.ic_http_group, R.drawable.ic_http_group,
R.drawable.ic_top, R.drawable.ic_top,
R.drawable.ic_kotlin,
R.drawable.ic_server, R.drawable.ic_server,
R.drawable.ic_windows R.drawable.ic_windows
}; };

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="1024"
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/icon_color" android:pathData="M863.1,914.43a116.03,116.03 0,0 1,-166.4 8.32L419.9,665.6q-2.18,-1.79 -4.29,-3.9L633.6,537.98l221.31,205.63a123.01,123.01 0,0 1,8.19 170.82zM381.82,280.83v-23.49A128,128 0,0 0,255.62 128a128,128 0,0 0,-126.21 129.34L129.41,424.32zM128,822.02v7.23A129.22,129.22 0,0 0,255.62 960a129.22,129.22 0,0 0,127.62 -130.75L383.23,677.25zM881.22,196.35a116.54,116.54 0,0 0,-160.38 -47.17l-587.52,333.44v276.48l701.82,-398.34a122.5,122.5 0,0 0,46.08 -164.42z"/>
</vector>

@ -24,6 +24,7 @@
<item>单任务下载</item> <item>单任务下载</item>
<item>多任务下载</item> <item>多任务下载</item>
<item>高优先级任务</item> <item>高优先级任务</item>
<item>kotlin</item>
<item>Service中使用</item> <item>Service中使用</item>
<item>组件中使用</item> <item>组件中使用</item>
</string-array> </string-array>

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.11' ext.kotlin_version = '1.3.20'
repositories { repositories {
jcenter() jcenter()
mavenCentral() mavenCentral()

Loading…
Cancel
Save