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.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.widget.PopupWindow;
@ -80,6 +82,7 @@ import org.xml.sax.SAXException;
private UploadConfig mUConfig;
private AppConfig mAConfig;
private DGroupConfig mDGConfig;
private Handler mAriaHandler;
private File[] files;
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() {
return mReceivers;
}

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

@ -62,6 +62,11 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
* 删除所有任务
*/
public static final int TASK_CANCEL_ALL = 0xb9;
/**
* 重启任务
*/
public static final int TASK_RESTART = 0xba;
private static volatile NormalCmdFactory INSTANCE = null;
private NormalCmdFactory() {
@ -103,6 +108,8 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
return new ResumeAllCmd<>(entity, taskType);
case TASK_CANCEL_ALL:
return new CancelAllCmd<>(entity, taskType);
case TASK_RESTART:
return new ReStartCmd<>(entity, taskType);
default:
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() {
ALog.d(TAG, "constance hash: " + mConstance.hashCode());
if (mConstance.isCancel) {
ALog.d(TAG, String.format("任务【%s】正在删除,删除任务失败", mTaskWrapper.getKey()));
return;
}
closeTimer();
mConstance.isCancel = true;
new Thread(new Runnable() {
@Override public void run() {
for (int i = 0; i < mTask.size(); i++) {
AbsThreadTask task = mTask.get(i);
if (task != null) {
task.cancel();
}
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
for (int i = 0; i < mTask.size(); i++) {
AbsThreadTask task = mTask.get(i);
if (task != null) {
task.cancel();
}
}).start();
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
}
public synchronized void stop() {
@ -284,18 +281,13 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
closeTimer();
mConstance.isStop = true;
if (mConstance.isComplete()) return;
new Thread(new Runnable() {
@Override public void run() {
for (int i = 0; i < mTask.size(); i++) {
AbsThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
task.stop();
}
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
for (int i = 0; i < mTask.size(); i++) {
AbsThreadTask task = mTask.get(i);
if (task != null && !task.isThreadComplete()) {
task.stop();
}
}).start();
}
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
}
/**
@ -303,6 +295,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
*/
public synchronized void start() {
if (isRunning()) {
ALog.d(TAG, String.format("任务【%s】正在执行,启动任务失败", mTaskWrapper.getKey()));
return;
}
new Thread(this).start();

@ -359,6 +359,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
ALog.d(TAG,
String.format("任务【%s】thread__%s__取消", getConfig().TEMP_FILE.getName(),
getConfig().THREAD_ID));
//ALog.d(TAG, "cancel_num = "
// + getState().CANCEL_NUM
// + ", start_thread_num = "
// + getState().START_THREAD_NUM);
if (getState().isCancel()) {
if (getConfig().TEMP_FILE.exists() && !(getEntity() instanceof UploadEntity)) {
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)
|| 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()));
mFailTimes++;
handleRetryRecord();

@ -55,6 +55,10 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
mLastSaveTime = System.currentTimeMillis();
}
protected TASK getTask() {
return mTask;
}
@Override public void onPre() {
saveData(IEntity.STATE_PRE, -1);
sendInState2Target(ISchedulers.PRE);
@ -103,7 +107,10 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
@Override public void onCancel() {
saveData(IEntity.STATE_CANCEL, -1);
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) {

@ -34,7 +34,7 @@ import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.AriaIOException;
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.util.ALog;
import com.arialyy.aria.util.Regular;
@ -79,11 +79,11 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
/**
* 设置请求的远程文件路径
* 获取请求的远程文件路径
*
* @return 远程文件路径
*/
protected abstract String setRemotePath();
protected abstract String getRemotePath();
@Override
public void run() {
@ -97,7 +97,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
return;
}
String remotePath =
new String(setRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
new String(getRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
if (mTaskDelegate.getUrlEntity().isFtps) {
((FTPSClient) client).execPROT("P");
//((FTPSClient) client).enterLocalActiveMode();
@ -105,9 +105,6 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
FTPFile[] files = client.listFiles(remotePath);
boolean isExist = files.length != 0;
if (!isExist && !isUpload) {
failDownload(new FileException(TAG,
String.format("文件不存在,url: %s, remotePath:%s", mTaskDelegate.getUrlEntity().url,
remotePath)), false);
int i = remotePath.lastIndexOf(File.separator);
FTPFile[] files1;
if (i == -1) {
@ -117,7 +114,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
if (files1.length > 0) {
ALog.i(TAG,
String.format("路径【%s】下的文件列表 ===================================", setRemotePath()));
String.format("路径【%s】下的文件列表 ===================================", getRemotePath()));
for (FTPFile file : files1) {
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()));
}
client.disconnect();
failDownload(new FileNotFoundException(TAG,
String.format("文件不存在,url: %s, remotePath:%s", mTaskDelegate.getUrlEntity().url,
remotePath)), false);
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();
if (!FTPReply.isPositiveCompletion(reply)) {
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();
failDownload(new AriaIOException(TAG,
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);
return null;
}
@ -367,7 +384,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
* 处理FTP文件信息
*
* @param remotePath ftp服务器文件夹路径
* @param ftpFile ftp服务器上对应的文件
* @param ftpFile ftp服务器上对应的文件
*/
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)
*
* 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.FtpUrlEntity;
import com.arialyy.aria.core.inf.ITargetHeadDelegate;
import java.net.Proxy;
/**
* fTP任务设置的信息用户名密码端口等信息
*/
public class FtpTaskDelegate implements ITargetHeadDelegate {
/**
* 账号和密码
*/
private FtpUrlEntity urlEntity;
private Proxy proxy;
/**
* 字符编码默认为"utf-8"
*/
private String charSet = "utf-8";
public FtpUrlEntity getUrlEntity() {
return urlEntity;
}
public void setUrlEntity(FtpUrlEntity urlEntity) {
this.urlEntity = urlEntity;
}
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;
}
}
/*
* 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.FtpUrlEntity;
import com.arialyy.aria.core.inf.ITargetHeadDelegate;
import java.net.Proxy;
/**
* fTP任务设置的信息用户名密码端口等信息
*/
public class FtpTaskDelegate implements ITargetHeadDelegate {
/**
* 账号和密码
*/
private FtpUrlEntity urlEntity;
private Proxy proxy;
/**
* 字符编码默认为"utf-8"
*/
private String charSet = "utf-8";
/**
* 上传拦截器
*/
private IFtpUploadInterceptor uploadInterceptor;
public IFtpUploadInterceptor getUploadInterceptor() {
return uploadInterceptor;
}
public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) {
this.uploadInterceptor = uploadInterceptor;
}
public FtpUrlEntity getUrlEntity() {
return urlEntity;
}
public void setUrlEntity(FtpUrlEntity urlEntity) {
this.urlEntity = urlEntity;
}
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.inf.IDownloadListener;
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.util.CommonUtil;
@ -55,7 +56,8 @@ public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, Do
mEntity.setState(state);
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;
} else if (state == IEntity.STATE_STOP) {
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.inf.GroupSendParams;
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.exception.BaseException;
import com.arialyy.aria.util.ALog;
@ -134,7 +135,8 @@ class DownloadGroupListener
mTaskWrapper.setState(state);
mEntity.setState(state);
if (state == IEntity.STATE_CANCEL) {
CommonUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile());
CommonUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile(),
getTask().getSchedulerType() != TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
return;
} else if (state == IEntity.STATE_STOP) {
mEntity.setStopTime(System.currentTimeMillis());

@ -19,6 +19,7 @@ import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
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.FtpDirDownloadUtil;
import com.arialyy.aria.core.download.group.IDownloadGroupListener;
@ -38,14 +39,6 @@ public class DownloadGroupTask extends AbsGroupTask<DownloadGroupEntity, DGTaskW
mOutHandler = outHandler;
mContext = AriaManager.APP;
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() {
@ -61,6 +54,16 @@ public class DownloadGroupTask extends AbsGroupTask<DownloadGroupEntity, DGTaskW
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 {
DGTaskWrapper taskEntity;
Handler outHandler;

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

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

@ -34,8 +34,8 @@ public abstract class AbsGroupTask<ENTITY extends AbsEntity, TASK_ENTITY extends
* @param url 子任务下载地址
*/
public void startSubTask(String url) {
if (mUtil != null) {
((AbsGroupUtil) mUtil).startSubTask(url);
if (getUtil() != null) {
((AbsGroupUtil) getUtil()).startSubTask(url);
}
}
@ -45,8 +45,8 @@ public abstract class AbsGroupTask<ENTITY extends AbsEntity, TASK_ENTITY extends
* @param url 子任务下载地址
*/
public void stopSubTask(String url) {
if (mUtil != null) {
((AbsGroupUtil) mUtil).stopSubTask(url);
if (getUtil() != null) {
((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.normal.CancelCmd;
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.DownloadGroupEntity;
import com.arialyy.aria.core.download.DTaskWrapper;
@ -79,7 +80,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
if (mEntity instanceof AbsNormalEntity) {
CommonUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile());
} else if (mEntity instanceof DownloadGroupEntity) {
CommonUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile());
CommonUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(), true);
}
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
}
@ -370,8 +371,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/
@Override public void reStart() {
if (checkConfig()) {
cancel();
start();
ReStartCmd cmd =
(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() {
}
@ -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) {
return null;
}

@ -18,6 +18,8 @@ package com.arialyy.aria.core.inf;
import android.content.Context;
import android.os.Handler;
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.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@ -40,7 +42,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
protected Context mContext;
boolean isHeighestTask = 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;
}
protected abstract IUtil createUtil();
protected synchronized IUtil getUtil() {
if (mUtil == null) {
mUtil = createUtil();
}
return mUtil;
}
/**
* 添加扩展数据 读取扩展数据{@link #getExpand(String)}
*/
@ -98,8 +109,8 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* @param speed 单位为kb
*/
public void setMaxSpeed(int speed) {
if (mUtil != null) {
mUtil.setMaxSpeed(speed);
if (getUtil() != null) {
getUtil().setMaxSpeed(speed);
}
}
@ -183,10 +194,25 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
}
@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, "任务正在下载");
} 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) {
isStop = true;
mSchedulerType = type;
if (mUtil.isRunning()) {
mUtil.stop();
if (getUtil().isRunning()) {
getUtil().stop();
} else {
ALog.d(TAG, "下载任务未执行");
mListener.onStop(mEntity.getCurrentProgress());
@ -206,11 +232,16 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
}
@Override public void cancel() {
cancel(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void cancel(@TaskSchedulerType int type) {
isCancel = true;
if (!mUtil.isRunning()) {
mSchedulerType = type;
if (!getUtil().isRunning()) {
mListener.onCancel();
} else {
mUtil.cancel();
getUtil().cancel();
}
}
@ -220,7 +251,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* @return {@code true} 正在下载
*/
@Override public boolean isRunning() {
return mUtil.isRunning();
return getUtil().isRunning();
}
/**

@ -79,8 +79,18 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
TASK_WRAPPER getTaskWrapper();
/**
* 启动任务
*/
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();
/**
* 停止任务
*
* @param type {@link TaskSchedulerType}
*/
void cancel(@TaskSchedulerType int type);
/**
* 读取扩展数据
*/
@ -134,6 +151,4 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
* {@link TaskSchedulerType}
*/
int getSchedulerType();
}

@ -7,7 +7,9 @@ import java.lang.annotation.RetentionPolicy;
@IntDef({
TaskSchedulerType.TYPE_DEFAULT,
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 {
int TYPE_DEFAULT = 1;
@ -19,4 +21,14 @@ import java.lang.annotation.RetentionPolicy;
* 停止任务并让当前任务处于等待状态
*/
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;
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.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@ -24,25 +25,26 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* 线程任务管理器
*/
public class ThreadTaskManager {
private static volatile ThreadTaskManager INSTANCE = null;
private static final Object LOCK = new Object();
private final String TAG = "ThreadTaskManager";
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) {
synchronized (LOCK) {
INSTANCE = new ThreadTaskManager();
}
INSTANCE = new ThreadTaskManager();
}
return INSTANCE;
}
@ -57,21 +59,37 @@ public class ThreadTaskManager {
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
* @param threadTask 线程任务{@link AbsThreadTask}
*/
public synchronized void startThread(String key, AbsThreadTask threadTask) {
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<Future> temp = mThreadTasks.get(key);
if (temp == null) {
temp = new HashSet<>();
mThreadTasks.put(key, temp);
public void startThread(String key, AbsThreadTask threadTask) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
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;
}
@ -80,29 +98,31 @@ public class ThreadTaskManager {
*
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
*/
public synchronized void removeTaskThread(String key) {
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<Future> temp = mThreadTasks.get(key);
if (temp != null && temp.size() > 0) {
try {
for (Future future : temp) {
if (future.isDone() || future.isCancelled()) {
public void removeTaskThread(String key) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
if (temp != null && temp.size() > 0) {
for (FutureContainer container : temp) {
if (container.future.isDone() || container.future.isCancelled()) {
continue;
}
AbsThreadTask task = (AbsThreadTask) future.get();
task.setInterrupted(true);
future.cancel(true);
container.threadTask.setInterrupted(true);
}
} catch (Exception e) {
ALog.e(TAG, e);
temp.clear();
}
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 线程任务
*/
public synchronized void retryThread(AbsThreadTask task) {
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
public void retryThread(AbsThreadTask task) {
try {
if (task == null || task.isInterrupted()) {
ALog.e(TAG, "线程为空或线程已经中断");
LOCK.tryLock(2, TimeUnit.SECONDS);
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;
}
mExePool.submit(task);
} catch (Exception e) {
ALog.e(TAG, e);
return;
e.printStackTrace();
} finally {
LOCK.unlock();
}
mExePool.submit(task);
}
/**
@ -136,4 +163,9 @@ public class ThreadTaskManager {
private String getKey(String 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) {
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:
mQueue.removeTaskFormQueue(task.getKey());
if (mQueue.getCurrentExePoolNum() < mQueue.getMaxTaskNum()) {
ALog.d(TAG, "stop_next");
ALog.d(TAG, String.format("删除任务【%s】成功,尝试开始下一任务", task.getTaskName()));
startNextTask(task);
} else {
ALog.d(TAG, String.format("删除任务【%s】成功", task.getTaskName()));
}
break;
case COMPLETE:
mQueue.removeTaskFormQueue(task.getKey());
ALog.d(TAG, "complete_next");
ALog.d(TAG, String.format("任务【%s】处理完成", task.getTaskName()));
startNextTask(task);
break;
case FAIL:

@ -19,6 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.common.BaseListener;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IUploadListener;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.util.CommonUtil;
/**
@ -36,7 +37,8 @@ class BaseUListener extends BaseListener<UploadEntity, UTaskWrapper, UploadTask>
mTaskWrapper.setState(state);
mEntity.setState(state);
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) {
mEntity.setStopTime(System.currentTimeMillis());
} else if (state == IEntity.STATE_COMPLETE) {

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

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

@ -15,17 +15,25 @@
*/
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 com.arialyy.aria.core.common.ftp.AbsFtpInfoThread;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.common.TaskRecord;
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.UploadEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.DbDataHelper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Aria.Lao on 2017/9/26.
@ -35,13 +43,71 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
private static final String TAG = "FtpUploadFileInfoThread";
static final int CODE_COMPLETE = 0xab1;
private boolean isComplete = false;
private String remotePath;
/**
* true 使用拦截器false 不使用拦截器
*/
private boolean useInterceptor = false;
FtpFileInfoThread(UTaskWrapper taskEntity, OnFileInfoCallback callback) {
super(taskEntity, callback);
}
@Override protected String setRemotePath() {
return mTaskWrapper.asFtp().getUrlEntity().remotePath + "/" + mEntity.getFileName();
@Override protected String getRemotePath() {
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) {
super.handleFile(remotePath, ftpFile);
if (ftpFile != null) {
if (ftpFile != null && !useInterceptor) {
//远程文件已完成
if (ftpFile.getSize() == mEntity.getFileSize()) {
isComplete = true;

@ -37,6 +37,7 @@ public class SimpleUploadUtil implements IUtil, Runnable {
private UTaskWrapper mTaskWrapper;
private IUploadListener mListener;
private Uploader mUploader;
private boolean isStop = false, isCancel = false;
public SimpleUploadUtil(UTaskWrapper taskWrapper, IUploadListener listener) {
mTaskWrapper = taskWrapper;
@ -90,14 +91,19 @@ public class SimpleUploadUtil implements IUtil, Runnable {
}
@Override public void cancel() {
isCancel = true;
mUploader.cancel();
}
@Override public void stop() {
isStop = true;
mUploader.stop();
}
@Override public void start() {
if (isStop || isCancel) {
return;
}
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);
delGroupTaskRecord(groupEntity, removeFile);
delGroupTaskRecord(groupEntity, removeFile, true);
}
/**
@ -608,7 +608,8 @@ public class CommonUtil {
*
* @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) {
ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null");
return;
@ -654,8 +655,10 @@ public class CommonUtil {
dir.delete();
}
}
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash());
if (removeEntity) {
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)
- 优化任务接收器的代码结构
- 修复`DbEntity.saveAll()`失败的问题

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

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

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

@ -1,75 +1,166 @@
//package com.arialyy.simple.core.download
//
//import android.os.Bundle
//import android.os.Environment
//import android.support.v7.app.AppCompatActivity
//import android.util.Log
//import android.view.View
//import com.arialyy.annotations.Download
//import com.arialyy.aria.core.Aria
//import com.arialyy.aria.core.download.DownloadTask
//import com.arialyy.simple.R
//import com.arialyy.simple.base.BaseActivity
//
///**
// * Created by lyy on 2017/10/23.
// */
//class KotlinDownloadActivity : AppCompatActivity() {
//
// private val DOWNLOAD_URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"
//
// private val TAG = "KotlinDownloadActivity";
//
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
// setContentView(setLayoutId())
// }
//
// fun setLayoutId(): Int {
// return R.layout.activity_single
// }
//
// fun init(savedInstanceState: Bundle?) {
// title = "单任务下载"
//// val target = Aria.download(this).load(DOWNLOAD_URL)
//// binding.progress = target.getPercent()
//// if (target.getTaskState() == IEntity.STATE_STOP) {
//// mStart.setText("恢复")
//// mStart.setTextColor(resources.getColor(android.R.color.holo_blue_light))
//// setBtState(true)
//// } else if (target.isDownloading()) {
//// setBtState(false)
//// }
//// binding.fileSize = target.getConvertFileSize()
// Aria.get(this).downloadConfig.maxTaskNum = 2
// Aria.download(this).register()
// }
//
// @Download.onTaskRunning
// protected fun running(task: DownloadTask) {
// Log.d(TAG, task.percent.toString() + "")
//// val len = task.fileSize
//// if (len == 0L) {
//// binding.progress = 0
//// } else {
//// binding.progress = task.percent
//// }
//// binding.speed = task.convertSpeed
// }
//
// fun onClick(view: View) {
// when (view.id) {
// R.id.start -> 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")
// .setDownloadPath(Environment.getExternalStorageDirectory().path + "/hhhhhhhh.apk")
// .start()
// }
//}
package com.arialyy.simple.core.download
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import com.arialyy.annotations.Download
import com.arialyy.aria.core.Aria
import com.arialyy.aria.core.download.DownloadTarget
import com.arialyy.aria.core.download.DownloadTask
import com.arialyy.aria.core.inf.IEntity
import com.arialyy.frame.util.show.T
import com.arialyy.simple.R
import com.arialyy.simple.base.BaseActivity
import com.arialyy.simple.databinding.ActivitySingleBinding
/**
* Created by lyy on 2017/10/23.
*/
class KotlinDownloadActivity : BaseActivity<ActivitySingleBinding>() {
private val DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"
private lateinit var mStart: Button
private lateinit var mStop: Button
private lateinit var mCancel: Button
private lateinit var target: DownloadTarget
override fun setLayoutId(): Int {
return R.layout.activity_single
}
override fun init(savedInstanceState: Bundle?) {
title = "kotlin测试"
Aria.get(this)
.downloadConfig.maxTaskNum = 2
Aria.download(this)
.register()
mStart = findViewById(R.id.start)
mStop = findViewById(R.id.stop)
mCancel = findViewById(R.id.cancel)
mStop.visibility = View.GONE
target = Aria.download(this)
.load(DOWNLOAD_URL)
binding.progress = target.percent
if (target.taskState == IEntity.STATE_STOP) {
mStart.text = "恢复"
} else if (target.isRunning) {
mStart.text = "停止"
}
binding.fileSize = target.convertFileSize
}
/**
* 注解方法不能添加internal修饰符否则会出现e: [kapt] An exception occurred: java.lang.IllegalArgumentException: index 1 for '$a' not in range (received 0 arguments)错误
*/
@Download.onTaskRunning
fun running(task: DownloadTask) {
Log.d(TAG, task.percent.toString())
val len = task.fileSize
if (len == 0L) {
binding.progress = 0
} else {
binding.progress = task.percent
}
binding.speed = task.convertSpeed
}
@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";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
//"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";
//"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://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
//"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();
break;
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();
break;
}

@ -1,113 +1,126 @@
/*
* 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.core.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.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
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
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
private final String URL = "ftp://9.9.9.205:2121/aa/你好";
@Override protected void init(Bundle savedInstanceState) {
setTile("D_FTP 文件上传");
super.init(savedInstanceState);
Aria.upload(this).register();
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
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;
}
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).loadFtp(FILE_PATH).cancel();
break;
}
}
@Upload.onWait void onWait(UploadTask task) {
Log.d(TAG, task.getTaskName() + "_wait");
}
@Upload.onPre public void onPre(UploadTask task) {
getBinding().setFileSize(task.getConvertFileSize());
}
@Upload.onTaskStart public void taskStart(UploadTask task) {
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
}
@Upload.onTaskResume public void taskResume(UploadTask task) {
Log.d(TAG, "恢复上传");
}
@Upload.onTaskStop public void taskStop(UploadTask task) {
getBinding().setSpeed("");
Log.d(TAG, "停止上传");
}
@Upload.onTaskCancel public void taskCancel(UploadTask task) {
getBinding().setSpeed("");
getBinding().setFileSize("");
getBinding().setProgress(0);
Log.d(TAG, "删除任务");
}
@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() + ",上传完成");
}
}
/*
* 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.core.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.common.ftp.FtpInterceptHandler;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
import java.io.File;
import java.util.List;
/**
* Created by lyy on 2017/7/28. Ftp 文件上传demo
*/
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
private final String URL = "ftp://9.9.9.205:2121/aa/你好";
@Override protected void init(Bundle savedInstanceState) {
setTile("D_FTP 文件上传");
super.init(savedInstanceState);
Aria.upload(this).register();
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
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;
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
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();
}
}).login("lao", "123456").start();
break;
case R.id.stop:
Aria.upload(this).loadFtp(FILE_PATH).stop();
break;
case R.id.cancel:
Aria.upload(this).loadFtp(FILE_PATH).cancel();
break;
}
}
@Upload.onWait void onWait(UploadTask task) {
Log.d(TAG, task.getTaskName() + "_wait");
}
@Upload.onPre public void onPre(UploadTask task) {
getBinding().setFileSize(task.getConvertFileSize());
}
@Upload.onTaskStart public void taskStart(UploadTask task) {
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
}
@Upload.onTaskResume public void taskResume(UploadTask task) {
Log.d(TAG, "恢复上传");
}
@Upload.onTaskStop public void taskStop(UploadTask task) {
getBinding().setSpeed("");
Log.d(TAG, "停止上传");
}
@Upload.onTaskCancel public void taskCancel(UploadTask task) {
getBinding().setSpeed("");
getBinding().setFileSize("");
getBinding().setProgress(0);
Log.d(TAG, "删除任务");
}
@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_group,
R.drawable.ic_top,
R.drawable.ic_kotlin,
R.drawable.ic_server,
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>kotlin</item>
<item>Service中使用</item>
<item>组件中使用</item>
</string-array>

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

Loading…
Cancel
Save