diff --git a/Aria/src/main/java/com/arialyy/aria/core/UrlMapping.java b/Aria/src/main/java/com/arialyy/aria/core/UrlMapping.java new file mode 100644 index 00000000..41098241 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/UrlMapping.java @@ -0,0 +1,34 @@ +/* + * 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; + +import com.arialyy.aria.orm.DbEntity; + +/** + * Created by lyy on 2017/10/17. + * Url 映射表 + */ +public class UrlMapping extends DbEntity { + /** + * 各实体对应的key + */ + public String key; + + /** + * 链接 + */ + public String url; +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFtpInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFtpInfoThread.java index adabb171..98aaee5f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFtpInfoThread.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFtpInfoThread.java @@ -88,7 +88,6 @@ public abstract class AbsFtpInfoThread 0) { + mEntity.setCurrentProgress(location); } mTaskEntity.update(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java index 9d52c280..9d651fdc 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java @@ -55,7 +55,6 @@ abstract class BaseGroupTarget { public DownloadTask build() { DownloadTask task = new DownloadTask(taskEntity, outHandler); task.setTargetName(targetName); - taskEntity.getEntity().save(); taskEntity.save(); return task; } 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 5cbd1bf5..5af62a2c 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 @@ -18,6 +18,7 @@ package com.arialyy.aria.core.download; import com.arialyy.aria.core.inf.AbsNormalTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.orm.Ignore; +import com.arialyy.aria.orm.NoNull; import com.arialyy.aria.orm.OneToOne; /** @@ -31,7 +32,7 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity { /** * 任务的url */ - public String url = ""; + @NoNull public String url = ""; /** * 所属的任务组组名,如果不属于任务组,则为null @@ -49,4 +50,12 @@ public class DownloadTaskEntity extends AbsNormalTaskEntity { @Override public DownloadEntity getEntity() { return entity; } + + public void save(DownloadEntity entity) { + url = entity.getUrl(); + key = entity.getDownloadPath(); + this.entity = entity; + entity.save(); + save(); + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java index 2fcca589..37ff76b6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java @@ -50,12 +50,10 @@ public class FtpDirDownloadTarget mTaskEntity = DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", key); if (mTaskEntity == null) { mTaskEntity = new DownloadGroupTaskEntity(); - mTaskEntity.key = key; - mTaskEntity.entity = getDownloadGroupEntity(); - mTaskEntity.insert(); + mTaskEntity.save(getDownloadGroupEntity()); } if (mTaskEntity.entity == null) { - mTaskEntity.entity = getDownloadGroupEntity(); + mTaskEntity.save(getDownloadGroupEntity()); } mEntity = mTaskEntity.entity; } 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 210528d5..95bd3b88 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 @@ -75,7 +75,6 @@ public class FtpDownloadTarget extends DownloadTarget { mEntity.setDownloadPath(downloadPath); mEntity.setFileName(newFile.getName()); mTaskEntity.key = downloadPath; - mEntity.update(); mTaskEntity.update(); CommonUtil.renameDownloadConfig(oldFile.getName(), newFile.getName()); } 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 729dea68..011afd04 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 @@ -169,25 +169,25 @@ public abstract class AbsGroupUtil implements IUtil { * @param url 子任务下载地址 */ public void cancelSubTask(String url) { - //List urls = mTaskEntity.entity.getUrls(); - //if (urls != null && !urls.isEmpty() && urls.contains(url)) { - // urls.remove(url); - // DownloadTaskEntity det = - // DbEntity.findFirst(DownloadTaskEntity.class, "url=? and isGroupTask='true'", url); - // if (det != null) { - // mTotalLen -= det.getEntity().getFileSize(); - // mGroupSize--; - // if (mGroupSize == 0) { - // closeTimer(false); - // mListener.onCancel(); - // } - // } - // mTaskEntity.getEntity().update(); - //} - //Downloader d = getDownloader(url, false); - //if (d != null) { - // d.cancel(); - //} + List urls = mTaskEntity.entity.getUrls(); + if (urls != null && !urls.isEmpty() && urls.contains(url)) { + urls.remove(url); + DownloadTaskEntity det = + DbEntity.findFirst(DownloadTaskEntity.class, "url=? and isGroupTask='true'", url); + if (det != null) { + mTotalLen -= det.getEntity().getFileSize(); + mGroupSize--; + if (mGroupSize == 0) { + closeTimer(false); + mListener.onCancel(); + } + } + mTaskEntity.update(); + } + Downloader d = getDownloader(url, false); + if (d != null) { + d.cancel(); + } } /** @@ -416,19 +416,18 @@ public abstract class AbsGroupUtil implements IUtil { * 子任务事件监听 */ private class ChildDownloadListener implements IDownloadListener { - - DownloadTaskEntity taskEntity; - DownloadEntity entity; + private DownloadTaskEntity subTaskEntity; + private DownloadEntity subEntity; private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度 - private long mLastSaveTime; - long lastLen = 0; + private long lastSaveTime; + private long lastLen = 0; ChildDownloadListener(DownloadTaskEntity entity) { - this.taskEntity = entity; - this.entity = taskEntity.getEntity(); - this.entity.setFailNum(0); - lastLen = this.entity.getCurrentProgress(); - mLastSaveTime = System.currentTimeMillis(); + subTaskEntity = entity; + subEntity = subTaskEntity.getEntity(); + subEntity.setFailNum(0); + lastLen = subEntity.getCurrentProgress(); + lastSaveTime = System.currentTimeMillis(); } @Override public void onPre() { @@ -436,33 +435,33 @@ public abstract class AbsGroupUtil implements IUtil { } @Override public void onPostPre(long fileSize) { - entity.setFileSize(fileSize); - entity.setConvertFileSize(CommonUtil.formatFileSize(fileSize)); + subEntity.setFileSize(fileSize); + subEntity.setConvertFileSize(CommonUtil.formatFileSize(fileSize)); saveData(IEntity.STATE_POST_PRE, -1); - mListener.onSubPre(entity); + mListener.onSubPre(subEntity); } @Override public void onResume(long resumeLocation) { saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); lastLen = resumeLocation; - mListener.onSubStart(entity); + mListener.onSubStart(subEntity); } @Override public void onStart(long startLocation) { saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); lastLen = startLocation; - mListener.onSubStart(entity); + mListener.onSubStart(subEntity); } @Override public void onProgress(long currentLocation) { long speed = currentLocation - lastLen; mCurrentLocation += speed; - entity.setCurrentProgress(currentLocation); + subEntity.setCurrentProgress(currentLocation); handleSpeed(speed); - mListener.onSubRunning(entity); - if (System.currentTimeMillis() - mLastSaveTime >= RUN_SAVE_INTERVAL) { + mListener.onSubRunning(subEntity); + if (System.currentTimeMillis() - lastSaveTime >= RUN_SAVE_INTERVAL) { saveData(IEntity.STATE_RUNNING, currentLocation); - mLastSaveTime = System.currentTimeMillis(); + lastSaveTime = System.currentTimeMillis(); } lastLen = currentLocation; } @@ -470,7 +469,7 @@ public abstract class AbsGroupUtil implements IUtil { @Override public void onStop(long stopLocation) { saveData(IEntity.STATE_STOP, stopLocation); handleSpeed(0); - mListener.onSubStop(entity); + mListener.onSubStop(subEntity); synchronized (AbsGroupUtil.class) { mStopNum++; if (mStopNum + mCompleteNum + mInitFailNum + mFailNum >= mGroupSize) { @@ -483,13 +482,13 @@ public abstract class AbsGroupUtil implements IUtil { @Override public void onCancel() { saveData(IEntity.STATE_CANCEL, -1); handleSpeed(0); - mListener.onSubCancel(entity); + mListener.onSubCancel(subEntity); } @Override public void onComplete() { - saveData(IEntity.STATE_COMPLETE, entity.getFileSize()); + saveData(IEntity.STATE_COMPLETE, subEntity.getFileSize()); handleSpeed(0); - mListener.onSubComplete(entity); + mListener.onSubComplete(subEntity); synchronized (AbsGroupUtil.class) { mCompleteNum++; //如果子任务完成的数量和总任务数一致,表示任务组任务已经完成 @@ -505,7 +504,7 @@ public abstract class AbsGroupUtil implements IUtil { } @Override public void onFail(boolean needRetry) { - entity.setFailNum(entity.getFailNum() + 1); + subEntity.setFailNum(subEntity.getFailNum() + 1); saveData(IEntity.STATE_FAIL, lastLen); handleSpeed(0); reTry(needRetry); @@ -516,12 +515,12 @@ public abstract class AbsGroupUtil implements IUtil { */ private void reTry(boolean needRetry) { synchronized (AriaManager.LOCK) { - if (entity.getFailNum() < 5 && isRunning && needRetry && NetUtils.isConnected( + if (subEntity.getFailNum() < 5 && isRunning && needRetry && NetUtils.isConnected( AriaManager.APP)) { reStartTask(); } else { mFailNum++; - mListener.onSubFail(entity); + mListener.onSubFail(subEntity); //如果失败的任务数大于实际的下载任务数,任务组停止下载 if (mFailNum >= mActualTaskNum) { closeTimer(false); @@ -535,28 +534,32 @@ public abstract class AbsGroupUtil implements IUtil { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { - Downloader dt = mDownloaderMap.get(entity.getUrl()); + Downloader dt = mDownloaderMap.get(subEntity.getUrl()); dt.start(); } }, 3000); } private void handleSpeed(long speed) { - entity.setSpeed(speed); - entity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s"); - entity.setPercent((int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); + subEntity.setSpeed(speed); + subEntity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s"); + subEntity.setPercent((int) (subEntity.getCurrentProgress() * 100 / subEntity.getFileSize())); } private void saveData(int state, long location) { - entity.setState(state); - entity.setComplete(state == IEntity.STATE_COMPLETE); - if (entity.isComplete()) { - entity.setCompleteTime(System.currentTimeMillis()); - entity.setCurrentProgress(entity.getFileSize()); + subTaskEntity.state = state; + subEntity.setState(state); + subEntity.setComplete(state == IEntity.STATE_COMPLETE); + if (state == IEntity.STATE_CANCEL) { + subTaskEntity.deleteData(); + return; + } else if (subEntity.isComplete()) { + subEntity.setCompleteTime(System.currentTimeMillis()); + subEntity.setCurrentProgress(subEntity.getFileSize()); } else if (location > 0) { - entity.setCurrentProgress(location); + subEntity.setCurrentProgress(location); } - entity.update(); + subTaskEntity.update(); } @Override public void supportBreakpoint(boolean support) { 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 86f1c180..4063c773 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 @@ -118,7 +118,6 @@ class HttpFileInfoThread implements Runnable { if (onFileInfoListener != null) { onFileInfoListener.onComplete(mEntity.getUrl(), code); } - mEntity.update(); mTaskEntity.update(); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java index 8b7f80de..317bb95f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java @@ -45,7 +45,7 @@ public abstract class AbsTarget extends DbEntity { public int getState() { return getEntity().getState(); } + + @Override public void deleteData() { + if (getEntity() != null) { + getEntity().deleteData(); + } + super.deleteData(); + } + + @Override public void update() { + if (getEntity() != null) { + getEntity().update(); + } + super.update(); + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsUploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsUploadTarget.java index 552a8068..a45ccf4c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsUploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsUploadTarget.java @@ -40,7 +40,6 @@ public abstract class AbsUploadTarget 0) { + mEntity.setCurrentProgress(location); } mTaskEntity.update(); } 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 3d4d7410..c5f44524 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java @@ -17,6 +17,7 @@ package com.arialyy.aria.orm; import android.text.TextUtils; import com.arialyy.aria.core.ErrorEntity; +import com.arialyy.aria.core.UrlMapping; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; @@ -33,7 +34,8 @@ import java.util.Map; class DBConfig { static Map mapping = new HashMap<>(); static String DB_NAME; - static int VERSION = 16; + //static int VERSION = 16; + static int VERSION = 17; static { if (TextUtils.isEmpty(DB_NAME)) { @@ -52,5 +54,6 @@ class DBConfig { mapping.put("UploadEntity", UploadEntity.class); mapping.put("UploadTaskEntity", UploadTaskEntity.class); mapping.put("ErrorEntity", ErrorEntity.class); + //mapping.put("UrlMapping", UrlMapping.class); } } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/NoNull.java b/Aria/src/main/java/com/arialyy/aria/orm/NoNull.java new file mode 100644 index 00000000..212efc4b --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/orm/NoNull.java @@ -0,0 +1,30 @@ +/* + * 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; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Created by lyy on 2015/11/2. + * 非空字段 + */ +@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface NoNull { + boolean value() default true; +} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java index 29e78688..0abbafad 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java @@ -26,7 +26,6 @@ import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; -import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.ArrayList; @@ -423,6 +422,8 @@ final class SqlHelper extends SQLiteOpenHelper { db = checkDb(db); List fields = CommonUtil.getAllFields(clazz); if (fields != null && fields.size() > 0) { + //外键Map,在Sqlite3中foreign修饰的字段必须放在最后 + final List foreignArray = new ArrayList<>(); StringBuilder sb = new StringBuilder(); sb.append("create table ") .append(TextUtils.isEmpty(tableName) ? CommonUtil.getClassName(clazz) : tableName) @@ -458,17 +459,26 @@ final class SqlHelper extends SQLiteOpenHelper { sb.append(" PRIMARY KEY"); } if (SqlUtil.isForeign(field)) { - Foreign foreign = field.getAnnotation(Foreign.class); - sb.append(",FOREIGN KEY (") - .append(field.getName()) - .append(") REFERENCES ") - .append(foreign.table()) - .append("(") - .append(foreign.column()) - .append(")"); + foreignArray.add(field); + } + + if (SqlUtil.isNoNull(field)) { + sb.append(" NOT NULL"); } sb.append(","); } + + for (Field field : foreignArray) { + Foreign foreign = field.getAnnotation(Foreign.class); + sb.append("FOREIGN KEY (") + .append(field.getName()) + .append(") REFERENCES ") + .append(CommonUtil.getClassName(foreign.table())) + .append("(") + .append(foreign.column()) + .append("),"); + } + String str = sb.toString(); str = str.substring(0, str.length() - 1) + ");"; print(CREATE_TABLE, str); 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 bbb37627..dd736b81 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java @@ -184,13 +184,13 @@ final class SqlUtil { } /** - * 判断是否是主外键约束 + * 判断是否是非空约束 * - * @return {@code true}主外键约束 + * @return {@code true}为非空约束 */ - static boolean isPrimaryAndForeign(Field field) { - PrimaryAndForeign fk = field.getAnnotation(PrimaryAndForeign.class); - return fk != null; + static boolean isNoNull(Field field) { + NoNull nn = field.getAnnotation(NoNull.class); + return nn != null; } private static Object checkData(String type, String data) { 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 99f19bcb..ffc1bc1c 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -247,9 +247,6 @@ public class CommonUtil { dir.delete(); } } - if (entity != null) { - entity.deleteData(); - } tEntity.deleteData(); } @@ -271,7 +268,7 @@ public class CommonUtil { if (config.exists()) { config.delete(); } - uEntity.deleteData(); + //uEntity.deleteData(); tEntity.deleteData(); } diff --git a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java index 137848ef..11410be7 100644 --- a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java +++ b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java @@ -29,6 +29,7 @@ public class UploadTaskEntity extends AbsNormalTaskEntity { public String contentType = "multipart/form-data"; //上传的文件类型 public String userAgent = "User-Agent"; @OneToOne(table = UploadEntity.class, key = "filePath") public UploadEntity entity; + public String filePath = ""; /** * 文件上传表单 @@ -41,4 +42,12 @@ public class UploadTaskEntity extends AbsNormalTaskEntity { @Override public UploadEntity getEntity() { return entity; } + + public void save(UploadEntity entity) { + filePath = entity.getFilePath(); + key = entity.getKey(); + this.entity = entity; + entity.save(); + save(); + } }