diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index 2fe50163..1a0eb578 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -77,8 +77,8 @@ import org.xml.sax.SAXException; private Configuration.AppConfig mAConfig; private AriaManager(Context context) { - DelegateWrapper.init(context.getApplicationContext()); APP = context.getApplicationContext(); + initDb(APP); regAppLifeCallback(context); initConfig(); initAria(); @@ -100,6 +100,20 @@ import org.xml.sax.SAXException; return INSTANCE; } + private void initDb(Context context) { + String dbBase = context.getFilesDir().getPath() + context.getPackageName() + "/databases/"; + File db = new File(dbBase + "AriaLyyDb"); + File dbConfig = new File(dbBase + "AriaLyyDb-journal"); + if (db.exists()) { + db.renameTo(new File(dbBase + "AndroidAria.db")); + // 如果数据库是在/data/data/{packagename}/databases/下面,journal文件因权限问题将无法删除和重命名 + if (dbConfig.exists()) { + dbConfig.delete(); + } + } + DelegateWrapper.init(context.getApplicationContext()); + } + private void initAria() { if (mAConfig.getUseAriaCrashHandler()) { Thread.setDefaultUncaughtExceptionHandler(new AriaCrashHandler()); @@ -363,7 +377,7 @@ import org.xml.sax.SAXException; } else { try { String md5Code = CommonUtil.getFileMD5(xmlFile); - File file = new File(APP.getFilesDir().getPath() + "temp.xml"); + File file = new File(APP.getFilesDir().getPath() + "/temp.xml"); if (file.exists()) { file.delete(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java index 71211cd2..d6cb98ec 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java @@ -59,6 +59,9 @@ class ConfigHelper extends DefaultHandler { String value = attributes.getValue("value"); switch (qName) { + case "openDynamicFile": + loadOpenDynamicFile(value); + break; case "threadNum": loadThreadNum(value); break; @@ -97,6 +100,9 @@ class ConfigHelper extends DefaultHandler { case "updateInterval": loadUpdateInterval(value); break; + case "notNetRetry": + loadNotNetRetry(value); + break; } } else if (isAppConfig) { String value = attributes.getValue("value"); @@ -111,6 +117,21 @@ class ConfigHelper extends DefaultHandler { } } + private void loadOpenDynamicFile(String value) { + if (isDownloadConfig) { + mDownloadConfig.openDynamicFile = checkBoolean(value) ? Boolean.valueOf(value) : false; + } + } + + private void loadNotNetRetry(String value) { + if (isDownloadConfig) { + mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false; + } + if (isUploadConfig) { + mUploadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false; + } + } + private void loadLogLevel(String value) { int level; try { @@ -210,6 +231,10 @@ class ConfigHelper extends DefaultHandler { if (isDownloadConfig) { mDownloadConfig.buffSize = buffSize; } + + if (isUploadConfig) { + mUploadConfig.buffSize = buffSize; + } } private void loadIOTimeout(String value) { @@ -222,6 +247,10 @@ class ConfigHelper extends DefaultHandler { if (isDownloadConfig) { mDownloadConfig.iOTimeOut = time; } + + if (isUploadConfig) { + mUploadConfig.iOTimeOut = time; + } } private void loadConnectTime(String value) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java index 680245a0..b3da691f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java @@ -56,7 +56,6 @@ class StartCmd extends AbsNormalCmd { return; } String mod; - // TODO: 2018/4/12 配置文件不存在,是否会出现wait获取不到 ? int maxTaskNum = mQueue.getMaxTaskNum(); AriaManager manager = AriaManager.getInstance(AriaManager.APP); if (isDownloadCmd) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java index 521284f5..bef04a0c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java @@ -19,16 +19,18 @@ import android.content.Context; import android.util.SparseArray; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.core.inf.IEventListener; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.core.upload.UploadTaskEntity; +import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; +import com.arialyy.aria.util.DbHelper; import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.Timer; @@ -50,10 +52,8 @@ public abstract class AbsFileer keys = pro.keySet(); - int num = 0; - for (Object key : keys) { - String str = String.valueOf(key); - Object state = pro.getProperty(str); - if (str.contains(RECORD)) { - num++; - } else if (state != null && str.contains(STATE) && Integer.parseInt(state + "") == 1) { + private void convertDb() { + List records = + DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", + mTaskEntity.getKey()); + if (records == null || records.size() == 0) { + Properties pro = CommonUtil.loadConfig(mConfigFile); + if (pro.isEmpty()) { + mTaskEntity.setNewTask(true); + return; + } + initRecord(); + Set keys = pro.keySet(); + // 老版本记录是5s存一次,但是5s中内,如果线程执行完成,record记录是没有的,只有state记录... + // 第一步应该是record 和 state去重取正确的线程数 + Set set = new HashSet<>(); + for (Object key : keys) { + String str = String.valueOf(key); int i = Integer.parseInt(str.substring(str.length() - 1, str.length())); - if (pro.getProperty(mTempFile.getName() + RECORD + i) != null) { - mCompleteThreadNum++; - } + set.add(i); } - } - if (num == 0) { - return true; - } - mStartThreadNum = num; - for (int i = 0; i < mStartThreadNum; i++) { - if (pro.getProperty(mTempFile.getName() + RECORD + i) == null) { + int threadNum = set.size(); + if (threadNum == 0) { + mTaskEntity.setNewTask(true); + return; + } + mRecord.threadNum = threadNum; + mTotalThreadNum = threadNum; + + for (int i = 0; i < threadNum; i++) { + ThreadRecord tRecord = new ThreadRecord(); + tRecord.key = mRecord.filePath; Object state = pro.getProperty(mTempFile.getName() + STATE + i); + Object record = pro.getProperty(mTempFile.getName() + RECORD + i); if (state != null && Integer.parseInt(state + "") == 1) { + mCompleteThreadNum++; + tRecord.isComplete = true; continue; } - return true; + mStartThreadNum++; + if (record != null) { + Long temp = Long.parseLong(record + ""); + tRecord.startLocation = temp > 0 ? temp : 0; + } else { + tRecord.startLocation = 0; + } + mRecord.threadRecords.add(tRecord); } + mConfigFile.delete(); } - return false; + } + + /** + * 初始化记录 + */ + private void initRecord() { + mRecord = new TaskRecord(); + mRecord.fileName = mEntity.getFileName(); + mRecord.filePath = mTaskEntity.getKey(); + mRecord.threadRecords = new ArrayList<>(); + mRecord.isGroupRecord = mTaskEntity.getEntity().isGroupChild(); + mRecord.isOpenDynamicFile = + AriaManager.getInstance(AriaManager.APP).getDownloadConfig().isOpenDynamicFile(); + if (mRecord.isGroupRecord) { + if (mTaskEntity.getEntity() instanceof DownloadEntity) { + mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName(); + } + } + } + + /** + * 保存任务记录 + */ + private void saveRecord() { + mRecord.save(); + for (ThreadRecord tr : mRecord.threadRecords) { + tr.save(); + } + } + + public TaskRecord getRecord() { + return mRecord; } /** @@ -291,9 +369,7 @@ public abstract class AbsFileer config = new SubThreadConfig<>(); config.FILE_SIZE = fileLength; config.URL = mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getUrl(); @@ -317,66 +394,76 @@ public abstract class AbsFileer= 0) { - Long r = Long.parseLong(record + ""); + if (tr.startLocation >= 0) { + Long r = tr.startLocation; //记录的位置需要在线程区间中 if (startL < r && r < (i == (mTotalThreadNum - 1) ? fileLength : endL)) { mConstance.CURRENT_LOCATION += r - startL; startL = r; } ALog.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载"); - recordL[rl] = i; - rl++; - } else { - recordL[rl] = i; - rl++; } + //最后一个线程的结束位置即为文件的总长度 if (i == (mTotalThreadNum - 1)) { - //最后一个线程的结束位置即为文件的总长度 endL = fileLength; } - AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength); + // 更新记录 + tr.startLocation = startL; + tr.endLocation = endL; + if (isNewTr) { + mRecord.threadRecords.add(tr); + } + AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength, tr); if (task == null) return; mTask.put(i, task); + threadId[rl] = i; + rl++; } - startSingleTask(recordL); + saveRecord(); + startThreadTask(threadId); } /** * 启动单线程下载任务 */ - private void startSingleTask(int[] recordL) { + private void startThreadTask(int[] recordL) { if (mConstance.CURRENT_LOCATION > 0) { mListener.onResume(mConstance.CURRENT_LOCATION); } else { @@ -390,7 +477,6 @@ public abstract class AbsFileer mConfig; @@ -63,6 +58,10 @@ public abstract class AbsThreadTask info) { - AriaManager manager = AriaManager.getInstance(AriaManager.APP); STATE = constance; - STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut(); - STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut(); mListener = listener; mConfig = info; mTaskEntity = mConfig.TASK_ENTITY; mEntity = mTaskEntity.getEntity(); - mConfigFPath = info.CONFIG_FILE_PATH; - mBufSize = manager.getDownloadConfig().getBuffSize(); - setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMaxSpeed()); mTaskType = getTaskType(); mLastSaveTime = System.currentTimeMillis(); mConfigThreadPool = Executors.newCachedThreadPool(); @@ -99,7 +92,7 @@ public abstract class AbsThreadTask= mConfig.END_LOCATION || isComplete) { - key = mConfig.TEMP_FILE.getName() + AbsFileer.STATE + mConfig.THREAD_ID; - value = "1"; - } else if (0 < record && record < mConfig.END_LOCATION) { - key = mConfig.TEMP_FILE.getName() + AbsFileer.RECORD + mConfig.THREAD_ID; - value = String.valueOf(record); - } - if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) { - File configFile = new File(mConfigFPath); - Properties pro = CommonUtil.loadConfig(configFile); - pro.setProperty(key, value); - CommonUtil.saveConfig(configFile, pro); + if (mConfig.THREAD_RECORD != null) { + mConfig.THREAD_RECORD.isComplete = isComplete; + if (0 < record && record < mConfig.END_LOCATION) { + mConfig.THREAD_RECORD.startLocation = record; } + mConfig.THREAD_RECORD.update(); } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java b/Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java index d8da2277..c959b6f0 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java @@ -16,12 +16,14 @@ package com.arialyy.aria.core.common; import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CommonUtil; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.List; import java.util.Set; -import static java.util.Collections.unmodifiableSet; - /** * Created by Aria.Lao on 2017/7/10. * 代理参数获取 @@ -45,8 +47,18 @@ public class ProxyHelper { } private void init() { + List classes = CommonUtil.getClassName(AriaManager.APP, "com.arialyy.aria"); + for (String className : classes) { + if (!className.startsWith("com.arialyy.aria.ProxyClassCounter")){ + continue; + } + count(className); + } + } + + private void count(String className) { try { - Class clazz = Class.forName("com.arialyy.aria.ProxyClassCounter"); + Class clazz = Class.forName(className); Method download = clazz.getMethod("getDownloadCounter"); Method downloadGroup = clazz.getMethod("getDownloadGroupCounter"); Method downloadGroupSub = clazz.getMethod("getDownloadGroupSubCounter"); @@ -54,19 +66,31 @@ public class ProxyHelper { Object object = clazz.newInstance(); Object dc = download.invoke(object); if (dc != null) { - downloadCounter = unmodifiableSet((Set) dc); + if (downloadCounter == null) { + downloadCounter = new HashSet<>(); + } + downloadCounter.addAll((Set) dc); } Object dgc = downloadGroup.invoke(object); if (dgc != null) { - downloadGroupCounter = unmodifiableSet((Set) dgc); + if (downloadGroupCounter == null) { + downloadGroupCounter = new HashSet<>(); + } + downloadGroupCounter.addAll((Set) dgc); } Object dgsc = downloadGroupSub.invoke(object); - if (dgsc != null){ - downloadGroupSubCounter = unmodifiableSet((Set) dgsc); + if (dgsc != null) { + if (downloadGroupSubCounter == null) { + downloadGroupSubCounter = new HashSet<>(); + } + downloadGroupSubCounter.addAll((Set) dgsc); } Object uc = upload.invoke(object); if (uc != null) { - uploadCounter = unmodifiableSet((Set) uc); + if (uploadCounter == null) { + uploadCounter = new HashSet<>(); + } + uploadCounter.addAll((Set) uc); } } catch (ClassNotFoundException e) { e.printStackTrace(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/RecordWrapper.java b/Aria/src/main/java/com/arialyy/aria/core/common/RecordWrapper.java new file mode 100644 index 00000000..3d61c124 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/common/RecordWrapper.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.common; + +import com.arialyy.aria.orm.AbsWrapper; +import com.arialyy.aria.orm.annotation.Many; +import com.arialyy.aria.orm.annotation.One; +import com.arialyy.aria.orm.annotation.Wrapper; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by laoyuyu on 2018/3/30. + * 任务记录和线程记录的关系 + */ +@Wrapper +public class RecordWrapper extends AbsWrapper { + + @One + public TaskRecord taskRecord; + + @Many(parentColumn = "filePath", entityColumn = "key") + public List threadRecords; + + @Override protected void handleConvert() { + if (threadRecords != null && !threadRecords.isEmpty()) { + taskRecord.threadRecords = threadRecords; + } else { + taskRecord.threadRecords = new ArrayList<>(); + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java index e42e3f86..25db8ea6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java @@ -23,14 +23,13 @@ public class StateConstance { public int CANCEL_NUM = 0; public int STOP_NUM = 0; public int FAIL_NUM = 0; - public int CONNECT_TIME_OUT; //连接超时时间 - public int READ_TIME_OUT; //流读取的超时时间 public int COMPLETE_THREAD_NUM = 0; - public int THREAD_NUM; + public int START_THREAD_NUM; //启动的线程数 public long CURRENT_LOCATION = 0; public boolean isRunning = false; public boolean isCancel = false; public boolean isStop = false; + public TaskRecord TASK_RECORD; public StateConstance() { } @@ -49,27 +48,28 @@ public class StateConstance { * 所有子线程是否都已经停止下载 */ public boolean isStop() { - return STOP_NUM == THREAD_NUM; + return STOP_NUM == START_THREAD_NUM; } /** * 所有子线程是否都已经下载失败 */ public boolean isFail() { - return COMPLETE_THREAD_NUM != THREAD_NUM && FAIL_NUM + COMPLETE_THREAD_NUM >= THREAD_NUM; + return COMPLETE_THREAD_NUM != START_THREAD_NUM + && FAIL_NUM + COMPLETE_THREAD_NUM >= START_THREAD_NUM; } /** * 所有子线程是否都已经完成下载 */ public boolean isComplete() { - return COMPLETE_THREAD_NUM >= THREAD_NUM; + return COMPLETE_THREAD_NUM >= START_THREAD_NUM; } /** * 所有子线程是否都已经取消下载 */ public boolean isCancel() { - return CANCEL_NUM == THREAD_NUM; + return CANCEL_NUM == START_THREAD_NUM; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java b/Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java index d2992980..2dc5b647 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java @@ -19,7 +19,7 @@ public class SubThreadConfig { public File TEMP_FILE; //服务器地址 public String URL; - public String CONFIG_FILE_PATH; public TASK_ENTITY TASK_ENTITY; public boolean SUPPORT_BP = true; + public ThreadRecord THREAD_RECORD; } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java b/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java index 51d63ec0..cc0cc3fd 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java @@ -15,18 +15,68 @@ */ package com.arialyy.aria.core.common; +import com.arialyy.aria.core.download.DownloadGroupEntity; +import com.arialyy.aria.orm.ActionPolicy; import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.orm.annotation.Foreign; +import com.arialyy.aria.orm.annotation.Ignore; +import com.arialyy.aria.orm.annotation.NoNull; +import com.arialyy.aria.orm.annotation.Primary; +import java.util.List; /** * Created by laoyuyu on 2018/3/21. - * 任务上传或下载的记录 + * 任务上传或下载的任务记录 */ -class TaskRecord extends DbEntity { +public class TaskRecord extends DbEntity { + + @Ignore + public List threadRecords; + /** * 任务线程数 */ public int threadNum; - //public int re + /** + * 任务文件路径 + */ + @Primary + public String filePath; + /** + * 文件长度 + */ + public long fileLength; + + /** + * 任务文件名 + */ + @NoNull + public String fileName; + + /** + * 是否是任务组的子任务记录 + * {@code true}是 + */ + public boolean isGroupRecord = false; + + /** + * 下载任务组名 + */ + @Foreign(parent = DownloadGroupEntity.class, column = "groupName", onUpdate = ActionPolicy.CASCADE, onDelete = ActionPolicy.CASCADE) + public String dGroupName; + + /** + * 上传组任务名,暂时没有用 + */ + @Ignore + @Deprecated + public String uGroupName; + + /** + * 是否是使用虚拟文件下载的 + * {@code true}是,{@code false}不是 + */ + public boolean isOpenDynamicFile = false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/ThreadRecord.java b/Aria/src/main/java/com/arialyy/aria/core/common/ThreadRecord.java new file mode 100644 index 00000000..29632e51 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/common/ThreadRecord.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.common; + +import com.arialyy.aria.orm.ActionPolicy; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.orm.annotation.Foreign; + +/** + * Created by laoyuyu on 2018/5/8. + * 任务的线程记录 + */ +public class ThreadRecord extends DbEntity { + @Foreign(parent = TaskRecord.class, column = "filePath", onUpdate = ActionPolicy.CASCADE, onDelete = ActionPolicy.CASCADE) + public String key; + + /** + * 开始位置 + */ + public long startLocation; + + /** + * 结束位置 + */ + public long endLocation; + + /** + * 线程是否完成 + * {@code true}完成,{@code false}未完成 + */ + public boolean isComplete = false; + + /** + * 线程id + */ + public int threadId = -1; +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java index 30d6388f..3e1be934 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java @@ -17,12 +17,16 @@ package com.arialyy.aria.core.download; import android.os.Handler; import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsGroupEntity; +import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.CommonUtil; import java.lang.ref.WeakReference; @@ -154,7 +158,16 @@ class BaseDListener mEntity.setDownloadPath(filePath); mEntity.setFileName(newFile.getName()); mTaskEntity.setKey(filePath); - //mTaskEntity.update(); if (oldFile.exists()) { oldFile.renameTo(newFile); - CommonUtil.renameDownloadConfig(oldFile.getName(), newFile.getName()); + CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); } } return true; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java index 800a5974..96f52012 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java @@ -29,12 +29,7 @@ public class DownloadGroupEntity extends AbsGroupEntity { @Ignore private List subEntities; - /** - * 任务组下载文件的文件夹地址 - * - * @see DownloadGroupTarget#setDirPath(String) - */ - private String dirPath; + /** * 子任务实体列表 @@ -47,14 +42,6 @@ public class DownloadGroupEntity extends AbsGroupEntity { this.subEntities = subTasks; } - public String getDirPath() { - return dirPath; - } - - public void setDirPath(String dirPath) { - this.dirPath = dirPath; - } - public void setGroupName(String key) { this.groupName = key; } @@ -73,13 +60,11 @@ public class DownloadGroupEntity extends AbsGroupEntity { @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeTypedList(this.subEntities); - dest.writeString(this.dirPath); } protected DownloadGroupEntity(Parcel in) { super(in); this.subEntities = in.createTypedArrayList(DownloadEntity.CREATOR); - this.dirPath = in.readString(); } public static final Creator CREATOR = new Creator() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java index 7de286cb..bb872563 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java @@ -224,7 +224,7 @@ public class DownloadGroupTarget extends BaseGroupTarget { if (oldFile.exists()) { oldFile.renameTo(new File(newPath)); } - CommonUtil.renameDownloadConfig(oldFile.getName(), newName); + CommonUtil.modifyTaskRecord(oldFile.getPath(), newPath); entity.setDownloadPath(newPath); taskEntity.setKey(newPath); entity.setFileName(newName); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java index cba839aa..7d06a4df 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -49,7 +49,6 @@ public class DownloadTarget extends BaseNormalTarget /** * 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment;filename=***} * 如果获取不到服务器文件名,则使用用户设置的文件名 - * 只适用于HTTP请求 * * @param use {@code true} 使用 */ diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java index ea770433..2fb5394b 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java @@ -137,10 +137,11 @@ public class DownloadTask extends AbsNormalTask { * 取消下载 */ @Override public void cancel() { - if (!mUtil.isRunning()) { + if (mUtil.isRunning()) { + mUtil.cancel(); + } else { mListener.onCancel(); } - mUtil.cancel(); } @Override public String getTaskName() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java index 9803d604..0d046d50 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java @@ -73,6 +73,10 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity { return key; } + @Override public void setKey(String key) { + this.key = key; + } + public String getUrl() { return url; } @@ -109,7 +113,5 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity { isGroupTask = groupTask; } - public void setKey(String key) { - this.key = key; - } + } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java index 81ae6413..1a60635c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java @@ -68,8 +68,6 @@ public class FtpDownloadTarget extends BaseNormalTarget * 关于文件名: * 1、如果保存路径是该文件的保存路径,如:/mnt/sdcard/file.zip,则使用路径中的文件名file.zip * 2、如果保存路径是文件夹路径,如:/mnt/sdcard/,则使用FTP服务器该文件的文件名 - * - * @param filePath 路径必须为文件路径,不能为文件夹路径 */ public FtpDownloadTarget setFilePath(@NonNull String filePath) { mTempFilePath = filePath; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java index 8880a09d..991d50bd 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java @@ -234,7 +234,6 @@ public abstract class AbsGroupUtil implements IUtil { } } clearState(); - CommonUtil.delDownloadGroupTaskConfig(mGTEntity.isRemoveFile(), mGTEntity.getEntity()); mListener.onCancel(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java index de1780e1..972f939f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java @@ -23,7 +23,6 @@ import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; -import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; @@ -40,37 +39,20 @@ class Downloader extends AbsFileer { Downloader(IDownloadListener listener, DownloadTaskEntity taskEntity) { super(listener, taskEntity); - setUpdateInterval( - AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getUpdateInterval()); + mTempFile = new File(mEntity.getDownloadPath()); + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + setUpdateInterval(manager.getDownloadConfig().getUpdateInterval()); } @Override protected int setNewTaskThreadNum() { - return mEntity.getFileSize() <= SUB_LEN || mTaskEntity.getRequestType() == AbsTaskEntity.D_FTP_DIR - ? 1 - : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum(); - } - - @Override protected void checkTask() { - mConfigFile = new File(CommonUtil.getFileConfigPath(true, mEntity.getFileName())); - mTempFile = new File(mEntity.getDownloadPath()); - if (!mTaskEntity.isSupportBP()) { - isNewTask = true; - return; - } - if (mTaskEntity.isNewTask()) { - isNewTask = true; - return; - } - if (!mConfigFile.exists()) { //记录文件被删除,则重新下载 - isNewTask = true; - CommonUtil.createFile(mConfigFile.getPath()); - } else if (!mTempFile.exists()) { - isNewTask = true; - } else if (DbEntity.findFirst(DownloadEntity.class, "url=?", mEntity.getUrl()) == null) { - isNewTask = true; - } else { - isNewTask = checkConfigFile(); - } + return + // 小于1m的文件或是任务组的子任务、使用虚拟文件,线程数都是1 + mEntity.getFileSize() <= SUB_LEN + || mTaskEntity.getRequestType() == AbsTaskEntity.D_FTP_DIR + || mTaskEntity.getRequestType() == AbsTaskEntity.DG_HTTP + || mRecord.isOpenDynamicFile + ? 1 + : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum(); } @Override protected boolean handleNewTask() { @@ -79,7 +61,7 @@ class Downloader extends AbsFileer { try { file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192); //设置文件长度 - file.setLength(mEntity.getFileSize()); + file.setLength(mRecord.isOpenDynamicFile ? 1 : mEntity.getFileSize()); return true; } catch (IOException e) { failDownload("下载失败【downloadUrl:" diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java index 4f0e8973..125c4422 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java @@ -15,6 +15,7 @@ */ package com.arialyy.aria.core.download.downloader; +import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.AbsFtpThreadTask; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; @@ -23,7 +24,6 @@ import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; -import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.commons.net.ftp.FTPClient; @@ -35,10 +35,22 @@ import org.apache.commons.net.ftp.FTPReply; */ class FtpThreadTask extends AbsFtpThreadTask { private final String TAG = "FtpThreadTask"; + private boolean isOpenDynamicFile; + /** + * 2M的动态长度 + */ + private final int LEN_INTERVAL = 1024 * 1024 * 2; FtpThreadTask(StateConstance constance, IDownloadListener listener, SubThreadConfig downloadInfo) { super(constance, listener, downloadInfo); + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + mConnectTimeOut = manager.getDownloadConfig().getConnectTimeOut(); + mReadTimeOut = manager.getDownloadConfig().getIOTimeOut(); + mBufSize = manager.getDownloadConfig().getBuffSize(); + isNotNetRetry = manager.getDownloadConfig().isNotNetRetry(); + isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile; + setMaxSpeed(manager.getDownloadConfig().getMaxSpeed()); } @Override public void run() { @@ -92,6 +104,11 @@ class FtpThreadTask extends AbsFtpThreadTask break; } if (mSleepTime > 0) Thread.sleep(mSleepTime); + if (isOpenDynamicFile) { + file.setLength( + STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION + + LEN_INTERVAL : mEntity.getFileSize()); + } if (mChildCurrentLocation + len >= mConfig.END_LOCATION) { len = (int) (mConfig.END_LOCATION - mChildCurrentLocation); file.write(buffer, 0, len); @@ -107,10 +124,7 @@ class FtpThreadTask extends AbsFtpThreadTask writeConfig(true, 1); STATE.COMPLETE_THREAD_NUM++; if (STATE.isComplete()) { - File configFile = new File(mConfigFPath); - if (configFile.exists()) { - configFile.delete(); - } + STATE.TASK_RECORD.deleteData(); STATE.isRunning = false; mListener.onComplete(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java index 63634d0f..10183650 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java @@ -148,6 +148,7 @@ class HttpFileInfoThread implements Runnable { return; } mEntity.setFileSize(len); + mTaskEntity.setNewTask(true); mTaskEntity.setSupportBP(false); end = true; } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { @@ -178,15 +179,13 @@ class HttpFileInfoThread implements Runnable { return; } File oldFile = new File(mEntity.getDownloadPath()); - String oldName = oldFile.getName(); String newPath = oldFile.getParent() + "/" + newName; - if (oldFile.exists()){ + if (oldFile.exists()) { oldFile.renameTo(new File(newPath)); } mEntity.setFileName(newName); mEntity.setDownloadPath(newPath); mTaskEntity.setKey(newPath); - CommonUtil.renameDownloadConfig(oldName, newName); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java index 333dfff7..b3a99db6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java @@ -15,6 +15,7 @@ */ package com.arialyy.aria.core.download.downloader; +import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; @@ -25,10 +26,8 @@ import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; import java.io.BufferedInputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -39,10 +38,22 @@ import java.net.URL; */ final class HttpThreadTask extends AbsThreadTask { private final String TAG = "HttpThreadTask"; + /** + * 2M的动态长度 + */ + private final int LEN_INTERVAL = 1024 * 1024 * 2; + private boolean isOpenDynamicFile; HttpThreadTask(StateConstance constance, IDownloadListener listener, SubThreadConfig downloadInfo) { super(constance, listener, downloadInfo); + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + mConnectTimeOut = manager.getDownloadConfig().getConnectTimeOut(); + mReadTimeOut = manager.getDownloadConfig().getIOTimeOut(); + mBufSize = manager.getDownloadConfig().getBuffSize(); + isNotNetRetry = manager.getDownloadConfig().isNotNetRetry(); + isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile; + setMaxSpeed(manager.getDownloadConfig().getMaxSpeed()); } @Override public void run() { @@ -71,8 +82,8 @@ final class HttpThreadTask extends AbsThreadTask 0) { Thread.sleep(mSleepTime); } + if (isOpenDynamicFile) { + file.setLength( + STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION + + LEN_INTERVAL : mEntity.getFileSize()); + } file.write(buffer, 0, len); progress(len); } @@ -155,10 +171,7 @@ final class HttpThreadTask extends AbsThreadTask urls = new ArrayList<>(); + public String getDirPath() { + return dirPath; + } + + public void setDirPath(String dirPath) { + this.dirPath = dirPath; + } + public List getUrls() { return urls; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java index 9407a302..22d9891c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java @@ -137,6 +137,8 @@ public abstract class AbsTaskEntity extends DbEntity { public abstract String getKey(); + public abstract void setKey(String key); + @Override public void update() { if (getEntity() != null) { getEntity().update(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/manager/UTEFactory.java b/Aria/src/main/java/com/arialyy/aria/core/manager/UTEFactory.java index 759b2dbd..207425c8 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/manager/UTEFactory.java +++ b/Aria/src/main/java/com/arialyy/aria/core/manager/UTEFactory.java @@ -48,9 +48,9 @@ class UTEFactory implements INormalTEFactory { List wrapper = DbEntity.findRelationData(UTEWrapper.class, "UploadTaskEntity.key=?", entity.getFilePath()); - + UploadTaskEntity uTaskEntity = null; if (wrapper != null && !wrapper.isEmpty()) { - UploadTaskEntity uTaskEntity = wrapper.get(0).taskEntity; + uTaskEntity = wrapper.get(0).taskEntity; if (uTaskEntity == null) { uTaskEntity = new UploadTaskEntity(); uTaskEntity.setEntity(entity); @@ -58,12 +58,12 @@ class UTEFactory implements INormalTEFactory { uTaskEntity.getEntity().getFilePath())) { uTaskEntity.setEntity(entity); } - return uTaskEntity; } else { - UploadTaskEntity uTaskEntity = new UploadTaskEntity(); + uTaskEntity = new UploadTaskEntity(); uTaskEntity.setEntity(entity); - return uTaskEntity; } + uTaskEntity.setKey(entity.getFilePath()); + return uTaskEntity; } @Override public UploadTaskEntity create(String key) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java index 7e96d1d0..67e74206 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java @@ -16,14 +16,12 @@ package com.arialyy.aria.core.queue; -import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.queue.pool.BaseCachePool; import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.NetUtils; /** * Created by lyy on 2017/2/23. @@ -195,10 +193,10 @@ abstract class AbsTaskQueue && mExecutePool.getTask(entity.getEntity().getKey()) == null) { task = (UploadTask) TaskFactory.getInstance() .createTask(targetName, entity, UploadSchedulers.getInstance()); - entity.setKey(entity.getEntity().getFilePath()); mCachePool.putTask(task); } else { ALog.w(TAG, "任务已存在"); diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java index 5cfdfced..c4857df5 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -30,6 +30,7 @@ import com.arialyy.aria.core.manager.TEManager; import com.arialyy.aria.core.queue.ITaskQueue; import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.NetUtils; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -181,7 +182,9 @@ abstract class AbsSchedulers reTryNum) { + if ((!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) + || task.getTaskEntity().getEntity().getFailNum() > reTryNum) { callback(FAIL, task); mQueue.removeTaskFormQueue(task.getKey()); startNextTask(); @@ -284,6 +292,7 @@ abstract class AbsSchedulers ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹"); return false; } + mTaskEntity.setKey(mEntity.getFilePath()); return true; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java index fcb7ad05..b313d64a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java @@ -17,12 +17,16 @@ package com.arialyy.aria.core.upload; import android.os.Handler; import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsGroupEntity; +import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IUploadListener; import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.CommonUtil; import java.lang.ref.WeakReference; @@ -140,7 +144,15 @@ class BaseUListener { - private static final String TAG = "FtpUploadFtpFileInfoThread"; + private static final String TAG = "FtpUploadFileInfoThread"; static final int CODE_COMPLETE = 0xab1; private boolean isComplete = false; @@ -67,16 +68,27 @@ class FtpFileInfoThread extends AbsFtpInfoThread + "尝试从位置:" + (ftpFile.getSize() - 1) + "开始上传"); - File configFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName())); - Properties pro = CommonUtil.loadConfig(configFile); - String key = mEntity.getFileName() + "_record_" + 0; mTaskEntity.setNewTask(false); - long oldRecord = Long.parseLong(pro.getProperty(key, "0")); - if (oldRecord == 0 || oldRecord != ftpFile.getSize()) { - //修改本地保存的停止地址为服务器上对应文件的大小 - pro.setProperty(key, (ftpFile.getSize() - 1) + ""); - CommonUtil.saveConfig(configFile, pro); + + // 修改记录 + TaskRecord record = DbHelper.getTaskRecord(mTaskEntity.getKey()); + if (record == null) { + record = new TaskRecord(); + record.fileName = mEntity.getFileName(); + record.filePath = mTaskEntity.getKey(); + record.threadRecords = new ArrayList<>(); + } + ThreadRecord threadRecord; + if (record.threadRecords == null || record.threadRecords.isEmpty()) { + threadRecord = new ThreadRecord(); + threadRecord.key = record.filePath; + } else { + threadRecord = record.threadRecords.get(0); } + //修改本地保存的停止地址为服务器上对应文件的大小 + threadRecord.startLocation = ftpFile.getSize() - 1; + record.save(); + threadRecord.save(); } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java index c6d7c497..3a1db27f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java @@ -15,6 +15,7 @@ */ package com.arialyy.aria.core.upload.uploader; +import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.AbsFtpThreadTask; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; @@ -23,7 +24,6 @@ import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; -import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import org.apache.commons.net.ftp.FTPClient; @@ -41,6 +41,11 @@ class FtpThreadTask extends AbsFtpThreadTask { FtpThreadTask(StateConstance constance, IEventListener listener, SubThreadConfig info) { super(constance, listener, info); + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + mConnectTimeOut = manager.getUploadConfig().getConnectTimeOut(); + mReadTimeOut = manager.getUploadConfig().getIOTimeOut(); + mBufSize = manager.getUploadConfig().getBuffSize(); + isNotNetRetry = manager.getUploadConfig().isNotNetRetry(); } @Override public void run() { @@ -82,10 +87,7 @@ class FtpThreadTask extends AbsFtpThreadTask { writeConfig(true, 1); STATE.COMPLETE_THREAD_NUM++; if (STATE.isComplete()) { - File configFile = new File(mConfigFPath); - if (configFile.exists()) { - configFile.delete(); - } + STATE.TASK_RECORD.deleteData(); STATE.isRunning = false; mListener.onComplete(); } @@ -114,7 +116,8 @@ class FtpThreadTask extends AbsFtpThreadTask { private void initPath() throws UnsupportedEncodingException { dir = new String(mTaskEntity.getUrlEntity().remotePath.getBytes(charSet), SERVER_CHARSET); remotePath = new String( - ("/" + mTaskEntity.getUrlEntity().remotePath + "/" + mEntity.getFileName()).getBytes(charSet), + ("/" + mTaskEntity.getUrlEntity().remotePath + "/" + mEntity.getFileName()).getBytes( + charSet), SERVER_CHARSET); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java index 6457da57..e0c4c641 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java @@ -15,7 +15,7 @@ */ package com.arialyy.aria.core.upload.uploader; -import android.util.Log; +import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.StateConstance; import com.arialyy.aria.core.common.SubThreadConfig; @@ -52,6 +52,11 @@ class HttpThreadTask extends AbsThreadTask { HttpThreadTask(StateConstance constance, IUploadListener listener, SubThreadConfig uploadInfo) { super(constance, listener, uploadInfo); + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + mConnectTimeOut = manager.getUploadConfig().getConnectTimeOut(); + mReadTimeOut = manager.getUploadConfig().getIOTimeOut(); + mBufSize = manager.getUploadConfig().getBuffSize(); + isNotNetRetry = manager.getUploadConfig().isNotNetRetry(); } @Override public void run() { @@ -74,10 +79,11 @@ class HttpThreadTask extends AbsThreadTask { mHttpConn.setRequestProperty("Content-Type", mTaskEntity.getContentType() + "; boundary=" + BOUNDARY); mHttpConn.setRequestProperty("User-Agent", mTaskEntity.getUserAgent()); - mHttpConn.setConnectTimeout(5000); + mHttpConn.setConnectTimeout(mConnectTimeOut); + mHttpConn.setReadTimeout(mReadTimeOut); //mHttpConn.setRequestProperty("Range", "bytes=" + 0 + "-" + "100"); //内部缓冲区---分段上传防止oom - mHttpConn.setChunkedStreamingMode(1024); + mHttpConn.setChunkedStreamingMode(mBufSize); //添加Http请求头部 Set keys = mTaskEntity.getHeaders().keySet(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java index 48c7aa3b..64859186 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java @@ -24,7 +24,6 @@ import com.arialyy.aria.core.inf.IUploadListener; import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.orm.DbEntity; -import com.arialyy.aria.util.CommonUtil; import java.io.File; /** @@ -40,31 +39,6 @@ class Uploader extends AbsFileer { AriaManager.getInstance(AriaManager.APP).getUploadConfig().getUpdateInterval()); } - /** - * 检查任务是否是新任务,新任务条件: - * 1、文件不存在 - * 2、记录文件不存在 - * 3、记录文件缺失或不匹配 - * 4、数据库记录不存在 - * 5、不支持断点,则是新任务 - */ - protected void checkTask() { - mConfigFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName())); - if (!mTaskEntity.isSupportBP()) { - isNewTask = true; - return; - } - if (!mConfigFile.exists()) { //记录文件被删除,则重新下载 - isNewTask = true; - CommonUtil.createFile(mConfigFile.getPath()); - } else if (DbEntity.findFirst(UploadEntity.class, "filePath=?", mEntity.getFilePath()) - == null) { - isNewTask = true; - } else { - isNewTask = checkConfigFile(); - } - } - @Override protected boolean handleNewTask() { return true; } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java index 8d9fb2ac..17ab3f1d 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java @@ -16,6 +16,8 @@ package com.arialyy.aria.orm; import android.text.TextUtils; +import com.arialyy.aria.core.common.TaskRecord; +import com.arialyy.aria.core.common.ThreadRecord; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; @@ -33,7 +35,7 @@ class DBConfig { /*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/ static Map mapping = new HashMap<>(); static String DB_NAME; - static int VERSION = 31; + static int VERSION = 33; /** * 是否将数据库保存在Sd卡,{@code true} 是 @@ -42,7 +44,7 @@ class DBConfig { static { if (TextUtils.isEmpty(DB_NAME)) { - DB_NAME = "AriaLyyDb"; + DB_NAME = "AndroidAria.db"; } if (VERSION == -1) { VERSION = 1; @@ -56,5 +58,7 @@ class DBConfig { mapping.put("UploadTaskEntity", UploadTaskEntity.class); mapping.put("DownloadEntity", DownloadEntity.class); mapping.put("UploadEntity", UploadEntity.class); + mapping.put("TaskRecord", TaskRecord.class); + mapping.put("ThreadRecord", ThreadRecord.class); } } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java index 9466bef0..f6856acc 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java @@ -30,6 +30,13 @@ public abstract class DbEntity { } + ///** + // * 保存关联数据 + // */ + //public static void saveRelationData(AbsWrapper wrapper) { + // DelegateWrapper.getInstance().saveRelationData(wrapper); + //} + /** * 查询关联数据 * diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java b/Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java index c23fabf6..01e9360a 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java @@ -187,6 +187,10 @@ class DelegateCommon extends AbsDelegate { } } + if (SqlUtil.isUnique(field)){ + sb.append(" UNIQUE"); + } + sb.append(","); } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java b/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java index 2b76ec6b..c2946ce1 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java @@ -51,6 +51,7 @@ class DelegateFind extends AbsDelegate { * 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null * 如果实体中没有{@link One}或{@link Many}注解,将返回null * 如果实体中有多个{@link One}或{@link Many}注解,将返回nul + * {@link One} 的注解对象必须是{@link DbEntity},{@link Many}的注解对象必须是List,并且List中的类型必须是{@link DbEntity} */ List findRelationData(SQLiteDatabase db, Class clazz, String... expression) { @@ -75,6 +76,10 @@ class DelegateFind extends AbsDelegate { ALog.w(TAG, "查询数据失败,实体中有多个@Many 注解"); return null; } + if (!field.getType().isAssignableFrom(List.class)) { + ALog.w(TAG, "查询数据失败,@Many 注解的类型不是List"); + return null; + } hasMany = true; many = field; } @@ -499,10 +504,16 @@ class DelegateFind extends AbsDelegate { /** * 通过rowId判断数据是否存在 */ - boolean itemExist(SQLiteDatabase db, Class clazz, - long rowId) { + boolean itemExist(SQLiteDatabase db, Class clazz, long rowId) { + return itemExist(db, CommonUtil.getClassName(clazz), rowId); + } + + /** + * 通过rowId判断数据是否存在 + */ + boolean itemExist(SQLiteDatabase db, String tableName, long rowId) { db = checkDb(db); - String sql = "SELECT rowid FROM " + CommonUtil.getClassName(clazz) + " WHERE rowid=" + rowId; + String sql = "SELECT rowid FROM " + tableName + " WHERE rowid=" + rowId; print(ROW_ID, sql); Cursor cursor = db.rawQuery(sql, null); boolean isExist = cursor.getCount() > 0; diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java b/Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java index 4a9ca900..006598d2 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java @@ -18,7 +18,6 @@ package com.arialyy.aria.orm; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; -import android.util.Log; import com.arialyy.aria.orm.annotation.Primary; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CheckUtil; @@ -36,6 +35,50 @@ class DelegateUpdate extends AbsDelegate { private DelegateUpdate() { } + ///** + // * 添加或更新关联数据 + // */ + //void saveRelationData(SQLiteDatabase db, AbsWrapper wrapper) { + // Class clazz = wrapper.getClass(); + // List fields = CommonUtil.getAllFields(clazz); + // DbEntity one = null; + // Object many = null; + // try { + // for (Field field : fields) { + // if (SqlUtil.isOne(field)) { + // one = (DbEntity) field.get(wrapper); + // } else if (SqlUtil.isMany(field)) { + // many = field.get(wrapper); + // } + // } + // if (one == null) { + // ALog.w(TAG, "保存关联数据失败,@One注解的字段为null"); + // return; + // } + // if (many == null) { + // ALog.w(TAG, "保存关联数据失败,@Many注解的字段为null"); + // return; + // } + // List oneFields = CommonUtil.getAllFields(one.getClass()); + // one.save(); + // if (many.getClass() == List.class) { + // for (DbEntity sub : (List) many) { + // sub.getClass().getA + // sub.save(); + // } + // } else { + // if (DbEntity.class.isInstance(many)) { + // ((DbEntity) many).save(); + // } else { + // ALog.w(TAG, "保存关联数据失败,@Many注解的字段不是DbEntity子类"); + // return; + // } + // } + // } catch (IllegalAccessException e) { + // e.printStackTrace(); + // } + //} + /** * 删除某条数据 */ @@ -62,7 +105,6 @@ class DelegateUpdate extends AbsDelegate { db = checkDb(db); Class clazz = dbEntity.getClass(); List fields = CommonUtil.getAllFields(clazz); - //DbEntity cacheEntity = mDataCache.get(getCacheKey(dbEntity)); if (fields != null && fields.size() > 0) { ContentValues values = new ContentValues(); try { @@ -71,14 +113,6 @@ class DelegateUpdate extends AbsDelegate { if (isIgnore(dbEntity, field)) { continue; } - //if (cacheEntity != null - // && field.get(dbEntity).equals(field.get(cacheEntity)) - // && !field.getName().equals("state")) { //在LruCache中 state字段总是不能重新赋值... - // Log.d(TAG, field.get(dbEntity) + ""); - // Log.d(TAG, field.get(cacheEntity) + ""); - // - // continue; - //} String value; Type type = field.getType(); if (type == Map.class && checkMap(field)) { @@ -101,7 +135,6 @@ class DelegateUpdate extends AbsDelegate { ALog.d(TAG, "没有数据更新"); } } - //mDataCache.put(getCacheKey(dbEntity), dbEntity); close(db); } @@ -137,7 +170,6 @@ class DelegateUpdate extends AbsDelegate { } catch (IllegalAccessException e) { e.printStackTrace(); } - //print(INSERT_DATA, ); dbEntity.rowID = db.insert(CommonUtil.getClassName(dbEntity), null, values); } close(db); diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java b/Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java index 6a817885..1c909eeb 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java @@ -56,6 +56,13 @@ public class DelegateWrapper { return INSTANCE; } + ///** + // * 保存关联数据 + // */ + //void saveRelationData(AbsWrapper wrapper){ + // + //} + /** * 查询关联表数据 * @@ -125,6 +132,13 @@ public class DelegateWrapper { return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, clazz, rowId); } + /** + * 通过rowId判断数据是否存在 + */ + boolean isExist(String tableName, long rowId) { + return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, tableName, rowId); + } + /** * 插入数据 */ diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java index 525f90cd..857d470a 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java @@ -23,6 +23,7 @@ import com.arialyy.aria.orm.annotation.Many; import com.arialyy.aria.orm.annotation.NoNull; import com.arialyy.aria.orm.annotation.One; import com.arialyy.aria.orm.annotation.Primary; +import com.arialyy.aria.orm.annotation.Unique; import com.arialyy.aria.orm.annotation.Wrapper; import com.arialyy.aria.util.CommonUtil; import java.lang.reflect.Field; @@ -247,6 +248,16 @@ final class SqlUtil { return nn != null; } + /** + * 判断是否是Unique + * + * @return {@code true}为Unique + */ + static boolean isUnique(Field field) { + Unique nn = field.getAnnotation(Unique.class); + return nn != null; + } + private static Object checkData(String type, String data) { if (type.equalsIgnoreCase("java.lang.String")) { return data; diff --git a/Aria/src/main/java/com/arialyy/aria/orm/annotation/Unique.java b/Aria/src/main/java/com/arialyy/aria/orm/annotation/Unique.java new file mode 100644 index 00000000..a0316388 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/orm/annotation/Unique.java @@ -0,0 +1,29 @@ +/* + * 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.orm.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by laoyuyu on 2018/5/8. + * 数据库 UNIQUE 约束 + */ +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) +public @interface Unique { +} diff --git a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java index 96f06349..b252e7b7 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -30,11 +30,16 @@ import com.arialyy.aria.core.command.group.AbsGroupCmd; import com.arialyy.aria.core.command.group.GroupCmdFactory; import com.arialyy.aria.core.command.normal.AbsNormalCmd; import com.arialyy.aria.core.command.normal.NormalCmdFactory; +import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; +import com.arialyy.aria.core.inf.AbsGroupEntity; import com.arialyy.aria.core.inf.AbsGroupTaskEntity; +import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.orm.DbEntity; +import dalvik.system.DexFile; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -53,9 +58,8 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; @@ -65,10 +69,44 @@ import java.util.regex.Pattern; /** * Created by lyy on 2016/1/22. + * 通用工具 */ public class CommonUtil { private static final String TAG = "CommonUtil"; + /** + * 获取某包下所有类 + * + * @param packageName 包名 + * @return 类的完整名称 + */ + public static List getClassName(Context context, String packageName) { + List classNameList = new ArrayList<>(); + try { + String pPath = context.getPackageCodePath(); + File dir = new File(pPath).getParentFile(); + String dPath = dir.getPath(); + for (String path : dir.list()) { + String fPath = dPath + "/" + path; + if (!fPath.endsWith(".apk")) { + continue; + } + DexFile df = new DexFile(fPath);//通过DexFile查找当前的APK中可执行文件 + Enumeration enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式 + while (enumeration.hasMoreElements()) {//遍历 + String className = enumeration.nextElement(); + if (className.contains(packageName)) {//在当前所有可执行的类里面查找包含有该包名的所有类 + classNameList.add(className); + } + } + df.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return classNameList; + } + /** * 拦截window.location.replace数据 * @@ -82,7 +120,7 @@ public class CommonUtil { String reg = Regular.REG_WINLOD_REPLACE; Pattern p = Pattern.compile(reg); Matcher m = p.matcher(text); - if (m.find()){ + if (m.find()) { String s = m.group(); s = s.substring(9, s.length() - 2); return s; @@ -356,20 +394,27 @@ public class CommonUtil { } /** - * 删除下载任务组的配置 + * 删除任务组记录 * * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 * {@code false}如果任务已经完成,只删除任务数据库记录 */ - public static void delDownloadGroupTaskConfig(boolean removeFile, - DownloadGroupEntity groupEntity) { + public static void delGroupTaskRecord(boolean removeFile, AbsGroupEntity groupEntity) { if (groupEntity == null) { ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null"); return; } + List records = DbEntity.findDatas(TaskRecord.class, + groupEntity instanceof DownloadGroupEntity ? "dGroupName=?" : "uGroupName=?", + groupEntity.getGroupName()); - for (DownloadEntity taskEntity : groupEntity.getSubEntities()) { - delDownloadTaskConfig(removeFile, taskEntity); + if (records == null || records.isEmpty()) { + ALog.w(TAG, "组任务记录删除失败,记录为null"); + return; + } + + for (TaskRecord tr : records) { + tr.deleteData(); } File dir = new File(groupEntity.getDirPath()); @@ -386,38 +431,23 @@ public class CommonUtil { } /** - * 删除上传任务的配置 + * 删除任务记录 * - * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 + * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经完成的文件 * {@code false}如果任务已经完成,只删除任务数据库记录 */ - public static void delUploadTaskConfig(boolean removeFile, UploadEntity uEntity) { - if (uEntity == null) { + public static void delTaskRecord(TaskRecord record, boolean removeFile, + AbsNormalEntity dEntity) { + if (dEntity == null) return; + File file; + if (dEntity instanceof DownloadEntity) { + file = new File(((DownloadEntity) dEntity).getDownloadPath()); + } else if (dEntity instanceof UploadEntity) { + file = new File(((UploadEntity) dEntity).getFilePath()); + } else { + ALog.w(TAG, "删除记录失败,未知类型"); return; } - File file = new File(uEntity.getFilePath()); - if (removeFile) { - if (file.exists()) { - file.delete(); - } - } - File config = new File(getFileConfigPath(false, uEntity.getFileName())); - if (config.exists()) { - config.delete(); - } - //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 - uEntity.deleteData(); - } - - /** - * 删除下载任务的配置 - * - * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经下载完成的文件 - * {@code false}如果任务已经完成,只删除任务数据库记录 - */ - public static void delDownloadTaskConfig(boolean removeFile, DownloadEntity dEntity) { - if (dEntity == null) return; - File file = new File(dEntity.getDownloadPath()); if (removeFile) { if (file.exists()) { file.delete(); @@ -430,9 +460,8 @@ public class CommonUtil { } } - File config = new File(getFileConfigPath(true, dEntity.getFileName())); - if (config.exists()) { - config.delete(); + if (record != null) { + record.deleteData(); } //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 dEntity.deleteData(); @@ -473,9 +502,10 @@ public class CommonUtil { public static void createFileFormInputStream(InputStream is, String path) { try { FileOutputStream fos = new FileOutputStream(path); - byte[] buf = new byte[1376]; - while (is.read(buf) > 0) { - fos.write(buf, 0, buf.length); + byte[] buf = new byte[1024]; + int len; + while ((len = is.read(buf)) > 0) { + fos.write(buf, 0, len); } is.close(); fos.flush(); @@ -849,60 +879,28 @@ public class CommonUtil { } /** - * 重命名下载配置文件 - * 如果旧的配置文件名不存在,则使用新的配置文件名新创建一个文件,否则将旧的配置文件重命名为新的位置文件名。 - * 除了重命名配置文件名外,还会将文件中的记录重命名为新的记录,如果没有记录,则不做处理 + * 更新任务记录 * - * @param oldName 旧的下载文件名 - * @param newName 新的下载文件名 + * @param oldPath 旧的文件路径 + * @param newPath 新的文件路径 */ - public static void renameDownloadConfig(String oldName, String newName) { - renameConfig(true, oldName, newName); - } - - /** - * 重命名上传配置文件 - * 如果旧的配置文件名不存在,则使用新的配置文件名新创建一个文件,否则将旧的配置文件重命名为新的位置文件名。 - * 除了重命名配置文件名外,还会将文件中的记录重命名为新的记录,如果没有记录,则不做处理 - * - * @param oldName 旧的上传文件名 - * @param newName 新的上传文件名 - */ - public static void renameUploadConfig(String oldName, String newName) { - renameConfig(false, oldName, newName); - } - - private static void renameConfig(boolean isDownload, String oldName, String newName) { - if (oldName.equals(newName)) return; - File oldFile = new File(getFileConfigPath(isDownload, oldName)); - File newFile = new File(getFileConfigPath(isDownload, oldName)); + public static void modifyTaskRecord(String oldPath, String newPath) { + if (oldPath.equals(newPath)) { + ALog.w(TAG, "修改任务记录失败,新文件路径和旧文件路径一致"); + return; + } + File oldFile = new File(oldPath); if (!oldFile.exists()) { - createFile(newFile.getPath()); - } else { - Properties pro = CommonUtil.loadConfig(oldFile); - if (!pro.isEmpty()) { - Set keys = pro.keySet(); - Set newKeys = new LinkedHashSet<>(); - Set values = new LinkedHashSet<>(); - for (Object key : keys) { - String oldKey = String.valueOf(key); - if (oldKey.contains(oldName)) { - values.add(pro.getProperty(oldKey)); - newKeys.add(oldKey.replace(oldName, newName)); - } - } - - pro.clear(); - Iterator next = values.iterator(); - for (String key : newKeys) { - pro.setProperty(key, next.next()); - } - - CommonUtil.saveConfig(oldFile, pro); - } - - oldFile.renameTo(newFile); + ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】不存在"); + return; + } + TaskRecord record = DbHelper.getTaskRecord(oldPath); + if (record == null) { + ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】对应的任务记录不存在"); + return; } + record.filePath = newPath; + record.update(); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/util/DbHelper.java b/Aria/src/main/java/com/arialyy/aria/util/DbHelper.java new file mode 100644 index 00000000..5277c433 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/DbHelper.java @@ -0,0 +1,42 @@ +/* + * 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.util; + +import com.arialyy.aria.core.common.RecordWrapper; +import com.arialyy.aria.core.common.TaskRecord; +import com.arialyy.aria.orm.DbEntity; +import java.util.List; + +/** + * 数据库帮助类 + */ +public class DbHelper { + + /** + * 获取任务记录 + * + * @param filePath 文件地址 + * @return 没有记录返回null,有记录则返回任务记录 + */ + public static TaskRecord getTaskRecord(String filePath) { + List records = + DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", filePath); + if (records == null || records.size() == 0) { + return null; + } + return records.get(0).taskRecord; + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java index ec874cd6..7a6ed484 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.UUID; import javax.annotation.processing.Filer; import javax.lang.model.element.Modifier; @@ -49,7 +50,8 @@ final class CountFiler { void createCountFile() throws IOException { Set keys = mPbUtil.getListenerClass().keySet(); if (keys.size() == 0) return; - TypeSpec.Builder builder = TypeSpec.classBuilder(ProxyConstance.PROXY_COUNTER_NAME) + TypeSpec.Builder builder = TypeSpec.classBuilder( + ProxyConstance.PROXY_COUNTER_NAME + UUID.randomUUID().toString().replace("-", "")) .addModifiers(Modifier.PUBLIC, Modifier.FINAL); FieldSpec mappingField = FieldSpec.builder( diff --git a/DEV_LOG.md b/DEV_LOG.md index 961a3125..ece42758 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -1,4 +1,11 @@ ## 开发日志 + + v_3.4.1 + - 移除记录配置文件,改用数据库记录任务记录 + - 上传配置添加io超时时间、缓存大小配置 + - 添加没有网络也会重试的开关 + - 修复多次删除记录的bug + - 文件长度现在可动态增加,详情见 https://aria.laoyuyu.me/aria_doc/start/config.html + - 修复多module同时引用Aria导致打正式包出错的问题 https://github.com/AriaLyy/Aria/issues/240 + v_3.4 - 优化大量代码 - 重构Aria的ORM模型,提高了数据读取的可靠性和读写速度 diff --git a/README.md b/README.md index 1642b74e..e8bf6aa8 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Aria有以下特点: + 支持https地址下载 - 在配置文件中很容易就可以设置CA证书的信息 + 支持300、301、302重定向下载链接下载 + + 下载支持文件长度动态增加,文件下载初始化时将不再占用过多的内存空间,见[动态长度配置](https://aria.laoyuyu.me/aria_doc/start/config.html#%E4%B8%8B%E8%BD%BD%E5%8A%A8%E6%80%81%E6%96%87%E4%BB%B6%E8%AF%B4%E6%98%8E) [怎样使用Aria?](#使用) @@ -29,8 +30,8 @@ Aria有以下特点: [![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion) [![Download](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion) ```java -compile 'com.arialyy.aria:aria-core:3.4' -annotationProcessor 'com.arialyy.aria:aria-compiler:3.4' +compile 'com.arialyy.aria:aria-core:3.4.1' +annotationProcessor 'com.arialyy.aria:aria-compiler:3.4.1' ``` 如果出现android support,请将 `compile 'com.arialyy.aria:aria-core:'`替换为 ``` @@ -98,13 +99,13 @@ protected void onCreate(Bundle savedInstanceState) { ### 版本日志 - + v_3.4 - - 优化大量代码 - - 重构Aria的ORM模型,提高了数据读取的可靠性和读写速度 - - 现在可在任意类中使用Aria了,[使用方法](http://aria.laoyuyu.me/aria_doc/start/any_java.html) - - 添加`window.location.replace("http://xxxx")`类型的网页重定向支持 - - 支持gzip、deflate 压缩类型的输入流 - - 添加`useServerFileName`,可使用服务端响应header的`Content-Disposition`携带的文件名 + + v_3.4.1 + - 移除记录配置文件,改用数据库记录任务记录 + - 上传配置添加io超时时间、缓存大小配置 + - 添加没有网络也会重试的开关 + - 修复多次删除记录的bug + - 文件长度现在可动态增加,详情见 https://aria.laoyuyu.me/aria_doc/start/config.html + - 修复多module同时引用Aria导致打正式包出错的问题 https://github.com/AriaLyy/Aria/issues/240 [更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) diff --git a/app/build.gradle b/app/build.gradle index c966701e..3f35f8e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,11 +34,10 @@ android { abortOnError false } -// sourceSets { -// main.kotlin.srcDirs += 'src/main/kotlin' -// main.java.srcDirs += 'src/main/java' -// } - + // sourceSets { + // main.kotlin.srcDirs += 'src/main/kotlin' + // main.java.srcDirs += 'src/main/java' + // } } dependencies { @@ -52,9 +51,10 @@ dependencies { compile 'com.arialyy.frame:MVVM2:2.2.0' compile project(':Aria') compile project(':AriaCompiler') -// compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" -// compile 'com.arialyy.aria:aria-core:3.3.16' -// annotationProcessor 'com.arialyy.aria:aria-compiler:3.3.16' + // compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + // compile 'com.arialyy.aria:aria-core:3.3.16' + // annotationProcessor 'com.arialyy.aria:aria-compiler:3.3.16' + debugCompile 'com.amitshekhar.android:debug-db:1.0.0' } repositories { mavenCentral() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c11fae91..5b9696df 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,10 +15,10 @@ android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBar"> - - + + diff --git a/app/src/main/assets/aria_config.xml b/app/src/main/assets/aria_config.xml index 3c437798..186611b1 100644 --- a/app/src/main/assets/aria_config.xml +++ b/app/src/main/assets/aria_config.xml @@ -11,6 +11,15 @@ + + + + + + @@ -48,6 +57,16 @@ + + + + + + + + + + @@ -55,7 +74,7 @@ - + diff --git a/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java b/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java index f80bd566..4ef74def 100644 --- a/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java +++ b/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java @@ -3,12 +3,9 @@ package com.arialyy.simple.test; import android.os.Bundle; import android.view.View; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.inf.AbsEntity; -import com.arialyy.aria.util.ALog; import com.arialyy.simple.R; import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.databinding.ActivityTestBinding; -import java.util.List; /** * Created by laoyuyu on 2018/4/13. @@ -18,7 +15,10 @@ public class AnyRunActivity extends BaseActivity { AnyRunnModule module; String[] urls; int index = 0; - String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk"; + //String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk"; + //String URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; + private final String URL = "ftp://192.168.29.140:21/download/AriaPrj.rar"; + //String URL = "https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe"; @Override protected int setLayoutId() { return R.layout.activity_test; @@ -40,15 +40,17 @@ public class AnyRunActivity extends BaseActivity { // module.start(urls[index]); // index++; //} - module.start(URL); - List list = Aria.download(this).getTotalTaskList(); - ALog.d(TAG, "size ==> " + list.size()); + //for (int i = 0; i < 10; i++) { + + module.startFtp(URL); + //} + //List list = Aria.download(this).getTotalTaskList(); + //ALog.d(TAG, "size ==> " + list.size()); break; case R.id.stop: //List list = Aria.download(this).getTotalTaskList(); // - ////module.stop(); - //module.stop(URL); + module.stop(URL); break; case R.id.cancel: diff --git a/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java b/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java index 4b583b98..7d276022 100644 --- a/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java +++ b/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java @@ -62,16 +62,58 @@ public class AnyRunnModule { L.d(TAG, "md5Code ==> " + CommonUtil.getFileMD5(new File(task.getDownloadPath()))); } - void start(String url) { mUrl = url; Aria.download(this) .load(url) - .addHeader("Accept-Encoding", "gzip") + //.addHeader("Accept-Encoding", "gzip") .setRequestMode(RequestEnum.GET) - .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg1234.apk") - .resetState() + .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg123456.apk") + //.resetState() + .start(); + //String[] urls = new String[] { + // "http://cdn-s1.touchfound.net/1526449199142_3617.png", + // "http://cdn-s1.touchfound.net/mtVmResources/1526287158571.zip", + // "http://cdn-s1.touchfound.net/1526450206960_2186.png", + // "http://cdn-s1.touchfound.net/1526449199025_1476.png" + //}; + //for (int i = 0, len = urls.length; i < len; i++){ + // + // Aria.download(this) + // .load(urls[i]) + // //.addHeader("Accept-Encoding", "gzip") + // .setRequestMode(RequestEnum.GET) + // .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg123456.apk" + i) + // //.resetState() + // .start(); + //} + } + + void startFtp(String url) { + mUrl = url; + Aria.download(this) + .loadFtp(url) + .login("lao", "123456") + //.addHeader("Accept-Encoding", "gzip") + .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/") + //.resetState() .start(); + //String[] urls = new String[] { + // "http://cdn-s1.touchfound.net/1526449199142_3617.png", + // "http://cdn-s1.touchfound.net/mtVmResources/1526287158571.zip", + // "http://cdn-s1.touchfound.net/1526450206960_2186.png", + // "http://cdn-s1.touchfound.net/1526449199025_1476.png" + //}; + //for (int i = 0, len = urls.length; i < len; i++){ + // + // Aria.download(this) + // .load(urls[i]) + // //.addHeader("Accept-Encoding", "gzip") + // .setRequestMode(RequestEnum.GET) + // .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg123456.apk" + i) + // //.resetState() + // .start(); + //} } void stop(String url) { diff --git a/app/src/main/java/com/arialyy/simple/test/TestActivity.java b/app/src/main/java/com/arialyy/simple/test/TestActivity.java index 01db7974..760a1a9d 100644 --- a/app/src/main/java/com/arialyy/simple/test/TestActivity.java +++ b/app/src/main/java/com/arialyy/simple/test/TestActivity.java @@ -21,9 +21,9 @@ public class TestActivity extends BaseActivity { String TAG = "TestActivity"; //String URL = "http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载 //private final String URL = "ftp://192.168.1.3:21/download//AriaPrj.rar"; - private final String FILE_PATH = "/mnt/sdcard/SDK_Demo-release.apk"; + private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar"; //private final String URL = "ftp://192.168.29.140:21/aa//你好"; - private final String URL = "http://192.168.29.140:5000/upload/"; + private final String URL = "ftp://192.168.29.140:21/upload/"; @Override protected int setLayoutId() { return R.layout.activity_test; @@ -76,18 +76,17 @@ public class TestActivity extends BaseActivity { switch (view.getId()) { case R.id.start: Aria.upload(this) - .load(FILE_PATH) + .loadFtp(FILE_PATH) + .login("lao", "123456") .setUploadUrl(URL) - .setRequestMode(RequestEnum.POST) .setExtendField("韩寒哈大双") - .setAttachment("file") .start(); break; case R.id.stop: - Aria.upload(this).load(FILE_PATH).stop(); + Aria.upload(this).loadFtp(FILE_PATH).stop(); break; case R.id.cancel: - Aria.upload(this).load(FILE_PATH).cancel(); + Aria.upload(this).loadFtp(FILE_PATH).cancel(); break; } } diff --git a/aria/src/main/java/com/arialyy/aria/core/Configuration.java b/aria/src/main/java/com/arialyy/aria/core/Configuration.java index d6382c66..85b71691 100644 --- a/aria/src/main/java/com/arialyy/aria/core/Configuration.java +++ b/aria/src/main/java/com/arialyy/aria/core/Configuration.java @@ -192,6 +192,12 @@ class Configuration { * 通用任务配置 */ abstract static class BaseTaskConfig extends BaseConfig { + + /** + * 设置写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢 + */ + int buffSize = 8192; + /** * 进度刷新间隔,默认1秒 */ @@ -231,6 +237,16 @@ class Configuration { */ String queueMod = "wait"; + /** + * 断网的时候是否重试,{@code true}断网也重试;{@code false}断网不重试,直接走失败的回调 + */ + boolean notNetRetry = false; + + /** + * 设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒 + */ + int iOTimeOut = 20 * 1000; + public long getUpdateInterval() { return updateInterval; } @@ -303,20 +319,43 @@ class Configuration { saveKey("connectTimeOut", String.valueOf(connectTimeOut)); return this; } + + public boolean isNotNetRetry() { + return notNetRetry; + } + + public BaseTaskConfig setNotNetRetry(boolean notNetRetry) { + this.notNetRetry = notNetRetry; + saveKey("notNetRetry", String.valueOf(notNetRetry)); + return this; + } + + public int getIOTimeOut() { + return iOTimeOut; + } + + public BaseTaskConfig setIOTimeOut(int iOTimeOut) { + this.iOTimeOut = iOTimeOut; + saveKey("iOTimeOut", String.valueOf(iOTimeOut)); + return this; + } + + public int getBuffSize() { + return buffSize; + } + + public BaseTaskConfig setBuffSize(int buffSize) { + this.buffSize = buffSize; + saveKey("buffSize", String.valueOf(buffSize)); + return this; + } } /** * 下载配置 */ public static class DownloadConfig extends BaseTaskConfig { - /** - * 设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒 - */ - int iOTimeOut = 20 * 1000; - /** - * 设置写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢 - */ - int buffSize = 8192; + /** * 设置https ca 证书信息;path 为assets目录下的CA证书完整路径 */ @@ -335,6 +374,26 @@ class Configuration { */ int maxSpeed = 0; + /** + * 是否开启动态文件,开启动态文件后初始化时将不占用磁盘空间,下载多少byte,占多少空间,效果见chrome的下载 + * 注意: + * 1、使用该功能,将自动关闭多线程下载; + * 2、对于已经采用了多线程的任务,依然采用原来的下载方式; + * 3、原本参数是true,任务没下载完成,就参数改为false,那么没下载完成的任务还是会按照参数修改前的方式下载,只有新任务才会根据参数调用不同的下载方式 + * {@code true}使用 + */ + boolean openDynamicFile = true; + + public DownloadConfig setOpenDynamicFile(boolean openDynamicFile) { + this.openDynamicFile = openDynamicFile; + saveKey("openDynamicFile", String.valueOf(openDynamicFile)); + return this; + } + + public boolean isOpenDynamicFile() { + return openDynamicFile; + } + public DownloadConfig setMaxTaskNum(int maxTaskNum) { oldMaxTaskNum = this.maxTaskNum; this.maxTaskNum = maxTaskNum; @@ -343,10 +402,6 @@ class Configuration { return this; } - public int getIOTimeOut() { - return iOTimeOut; - } - public int getMaxSpeed() { return maxSpeed; } @@ -363,22 +418,6 @@ class Configuration { saveKey("threadNum", String.valueOf(threadNum)); } - public DownloadConfig setIOTimeOut(int iOTimeOut) { - this.iOTimeOut = iOTimeOut; - saveKey("iOTimeOut", String.valueOf(iOTimeOut)); - return this; - } - - public int getBuffSize() { - return buffSize; - } - - public DownloadConfig setBuffSize(int buffSize) { - this.buffSize = buffSize; - saveKey("buffSize", String.valueOf(buffSize)); - return this; - } - public String getCaPath() { return caPath; } diff --git a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java index 8e0e4e87..1cadfa4a 100644 --- a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java +++ b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java @@ -68,10 +68,11 @@ public class UploadTask extends AbsNormalTask { } @Override public void cancel() { - if (!mUtil.isRunning()) { + if (mUtil.isRunning()) { + mUtil.cancel(); + } else { mListener.onCancel(); } - mUtil.cancel(); } @Override public String getTaskName() { diff --git a/build.gradle b/build.gradle index 7d7d9d9c..7e6411b6 100644 --- a/build.gradle +++ b/build.gradle @@ -39,7 +39,7 @@ task clean(type: Delete) { ext { userOrg = 'arialyy' groupId = 'com.arialyy.aria' - publishVersion = '3.4' + publishVersion = '3.4.1' // publishVersion = '1.0.3' //FTP插件 repoName='maven' desc = 'android 下载框架'