From 8f8f8fa7d7fe89f9eeb5ab50402d303a331cd35f Mon Sep 17 00:00:00 2001 From: laoyuyu <511455842@qq.com> Date: Tue, 11 Jun 2019 19:17:28 +0800 Subject: [PATCH] =?UTF-8?q?fix=20bug=20https://github.com/AriaLyy/Aria/iss?= =?UTF-8?q?ues/407=20=E7=A7=BB=E9=99=A4`DownloadGroupEntity`=E5=AD=97?= =?UTF-8?q?=E6=AE=B5`groupHash`=E7=9A=84=E4=B8=BB=E9=94=AE=E7=BA=A6?= =?UTF-8?q?=E6=9D=9F=EF=BC=8C`DownloadEntity`=E5=AD=97=E6=AE=B5`groupHash`?= =?UTF-8?q?=E7=9A=84=E5=A4=96=E9=94=AE=E7=BA=A6=E6=9D=9F=EF=BC=8C`TaskReco?= =?UTF-8?q?rd`=E5=AD=97=E6=AE=B5`dGroupHash`=E7=9A=84=E5=A4=96=E9=94=AE?= =?UTF-8?q?=E7=BA=A6=E6=9D=9F=20=E4=BC=98=E5=8C=96=E5=85=B3=E8=81=94?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E7=9A=84=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../arialyy/aria/core/common/AbsFileer.java | 32 +-- .../aria/core/common/AbsThreadTask.java | 44 +++- .../aria/core/common/BaseListener.java | 2 +- .../aria/core/common/NormalFileer.java | 8 +- .../arialyy/aria/core/common/TaskRecord.java | 8 +- .../aria/core/common/http/HttpDelegate.java | 1 - .../core/download/AbsGroupConfigHandler.java | 16 +- .../aria/core/download/DownloadEntity.java | 8 +- .../aria/core/download/DownloadGroupTask.java | 2 +- .../aria/core/download/DownloadTask.java | 13 +- .../core/download/m3u8/M3U8LiveDelegate.java | 15 ++ .../download/m3u8/M3U8LiveDownloadUtil.java | 13 +- .../core/download/m3u8/M3U8LiveLoader.java | 13 +- .../core/download/m3u8/M3U8TaskConfig.java | 13 + .../core/download/m3u8/M3U8VodLoader.java | 7 + .../arialyy/aria/core/inf/AbsGroupEntity.java | 6 +- .../arialyy/aria/core/inf/AbsGroupTask.java | 4 +- .../arialyy/aria/core/inf/AbsNormalTask.java | 4 +- .../com/arialyy/aria/core/inf/AbsTask.java | 7 +- .../aria/core/manager/ThreadTaskManager.java | 40 +++- .../java/com/arialyy/aria/orm/DBConfig.java | 3 +- .../com/arialyy/aria/orm/DelegateFind.java | 222 +++++++----------- .../java/com/arialyy/aria/orm/SqlHelper.java | 21 +- DEV_LOG.md | 5 + .../core/download/m3u8/M3U8VodModule.java | 2 +- .../multi_download/FileListAdapter.java | 1 + .../multi_download/MultiTaskActivity.java | 3 + 27 files changed, 277 insertions(+), 236 deletions(-) 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 b98b8786..5fc8eaf8 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 @@ -15,9 +15,8 @@ */ package com.arialyy.aria.core.common; -import android.content.Context; import android.os.Looper; -import com.arialyy.aria.core.AriaManager; +import android.util.SparseArray; import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.IEventListener; @@ -25,8 +24,6 @@ import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; import java.io.File; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -40,10 +37,9 @@ public abstract class AbsFileer mTask = new HashMap<>(); + private SparseArray mTask = new SparseArray<>(); private ScheduledThreadPoolExecutor mTimer; /** @@ -58,7 +54,6 @@ public abstract class AbsFileer getTaskList() { + public SparseArray getTaskList() { return mTask; } @@ -92,10 +87,8 @@ public abstract class AbsFileer= 0) { mListener.onProgress(mStateManager.getCurrentProgress()); @@ -209,7 +201,8 @@ public abstract class AbsFileer, - TASK extends AbsTask> + TASK extends AbsTask> implements IEventListener { protected static String TAG; private static final int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度 diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/NormalFileer.java b/Aria/src/main/java/com/arialyy/aria/core/common/NormalFileer.java index 936c1e7f..eca68d68 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/NormalFileer.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/NormalFileer.java @@ -55,7 +55,8 @@ public abstract class NormalFileer 0) { task.setMaxSpeed(maxSpeed / mStartThreadNum); } @@ -168,8 +169,9 @@ public abstract class NormalFileer implements IGro ALog.d(TAG, String.format("修改新路径为:%s", newDirPath)); List subTasks = mWrapper.getSubTaskWrapper(); if (subTasks != null && !subTasks.isEmpty()) { - List des = new ArrayList<>(); for (DTaskWrapper dte : subTasks) { DownloadEntity de = dte.getEntity(); - String oldPath = de.getDownloadPath(); + String oldPath = de.getFilePath(); String newPath = newDirPath + "/" + de.getFileName(); File file = new File(oldPath); if (file.exists()) { file.renameTo(new File(newPath)); } - de.setDownloadPath(newPath); - des.add(de); + de.setFilePath(newPath); } } } @@ -103,12 +101,18 @@ abstract class AbsGroupConfigHandler implements IGro ALog.e(TAG, "文件夹路径不能为null"); return false; } else if (!mDirPathTemp.startsWith("/")) { - ALog.e(TAG, "文件夹路径【" + mDirPathTemp + "】错误"); + ALog.e(TAG, String.format("文件夹路径【%s】错误", mDirPathTemp)); return false; } File file = new File(mDirPathTemp); if (file.isFile()) { - ALog.e(TAG, "路径【" + mDirPathTemp + "】是文件,请设置文件夹路径"); + ALog.e(TAG, String.format("路径【%s】是文件,请设置文件夹路径", mDirPathTemp)); + return false; + } + + if ((getEntity().getDirPath() == null || !getEntity().getDirPath().equals(mDirPathTemp)) + && DbEntity.checkDataExist(DownloadGroupEntity.class, "dirPath=?", mDirPathTemp)) { + ALog.e(TAG, String.format("文件夹路径【%s】已被其它任务占用,请重新设置文件夹路径", mDirPathTemp)); return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java index 495df2a5..81445007 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java @@ -21,9 +21,7 @@ import android.os.Parcelable; import android.text.TextUtils; import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTaskWrapper; -import com.arialyy.aria.orm.ActionPolicy; -import com.arialyy.aria.orm.annotation.Foreign; -import com.arialyy.aria.orm.annotation.Primary; +import com.arialyy.aria.orm.annotation.Unique; import com.arialyy.aria.util.CommonUtil; /** @@ -31,13 +29,11 @@ import com.arialyy.aria.util.CommonUtil; * 下载实体 */ public class DownloadEntity extends AbsNormalEntity implements Parcelable { - @Primary private String downloadPath; //保存路径 + @Unique private String downloadPath; //保存路径 /** * 所属任务组 */ - @Foreign(parent = DownloadGroupEntity.class, column = "groupHash", - onUpdate = ActionPolicy.CASCADE, onDelete = ActionPolicy.CASCADE) private String groupHash; /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java index 9117ab82..927eaabc 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java @@ -32,7 +32,7 @@ import com.arialyy.aria.util.CheckUtil; * Created by AriaL on 2017/6/27. * 任务组任务 */ -public class DownloadGroupTask extends AbsGroupTask { +public class DownloadGroupTask extends AbsGroupTask { private DownloadGroupTask(DGTaskWrapper taskWrapper, Handler outHandler) { mTaskWrapper = taskWrapper; 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 a213dd15..0dbb7924 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 @@ -32,7 +32,7 @@ import com.arialyy.aria.core.scheduler.ISchedulers; * Created by lyy on 2016/8/11. * 下载任务类 */ -public class DownloadTask extends AbsNormalTask { +public class DownloadTask extends AbsNormalTask { public static final String TAG = "DownloadTask"; private DownloadTask(DTaskWrapper taskWrapper, Handler outHandler) { @@ -40,7 +40,6 @@ public class DownloadTask extends AbsNormalTask { mOutHandler = outHandler; mContext = AriaManager.APP; mListener = new BaseDListener(this, mOutHandler); - mEntity = taskWrapper.getEntity(); } /** @@ -57,7 +56,7 @@ public class DownloadTask extends AbsNormalTask { * 获取文件保存路径 */ public String getFilePath() { - return mEntity.getFilePath(); + return mTaskWrapper.getEntity().getFilePath(); } public DownloadEntity getEntity() { @@ -70,7 +69,7 @@ public class DownloadTask extends AbsNormalTask { * @see DownloadTask#getKey() */ @Deprecated public String getDownloadUrl() { - return mEntity.getUrl(); + return mTaskWrapper.getEntity().getUrl(); } @Override public int getTaskType() { @@ -78,15 +77,15 @@ public class DownloadTask extends AbsNormalTask { } @Override public String getKey() { - return mEntity.getUrl(); + return mTaskWrapper.getEntity().getUrl(); } public DownloadEntity getDownloadEntity() { - return mEntity; + return mTaskWrapper.getEntity(); } @Override public String getTaskName() { - return mEntity.getFileName(); + return mTaskWrapper.getEntity().getFileName(); } @Override protected synchronized IUtil createUtil() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java index 699b6329..24581fcc 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveDelegate.java @@ -19,6 +19,7 @@ import com.arialyy.aria.core.common.BaseDelegate; import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.inf.AbsTarget; import com.arialyy.aria.core.inf.AbsTaskWrapper; +import com.arialyy.aria.util.ALog; /** * m3u8直播参数设置 @@ -40,4 +41,18 @@ public class M3U8LiveDelegate extends BaseDelegate mPeerUrls = new ArrayList<>(); public M3U8LiveDownloadUtil(DTaskWrapper wrapper, IDownloadListener listener) { mWrapper = wrapper; @@ -86,6 +87,7 @@ public class M3U8LiveDownloadUtil implements IUtil { */ @Override public void stop() { isStop = true; + mLoader.stop(); handleComplete(); } @@ -122,7 +124,7 @@ public class M3U8LiveDownloadUtil implements IUtil { mInfoThread = (M3U8InfoThread) getLiveInfo(); mInfoPool.execute(mInfoThread); } - }, 0, 1000, TimeUnit.MILLISECONDS); + }, 0, mWrapper.asM3U8().getLiveUpdateInterval(), TimeUnit.MILLISECONDS); } private void closeTimer() { @@ -150,6 +152,10 @@ public class M3U8LiveDownloadUtil implements IUtil { }); infoThread.setOnGetPeerCallback(new M3U8InfoThread.OnGetLivePeerCallback() { @Override public void onGetPeer(String url) { + if (mPeerUrls.contains(url)) { + return; + } + mPeerUrls.add(url); ILiveTsUrlConverter converter = mWrapper.asM3U8().getLiveTsUrlConverter(); if (converter != null) { if (TextUtils.isEmpty(mWrapper.asM3U8().getBandWidthUrl())) { @@ -162,7 +168,6 @@ public class M3U8LiveDownloadUtil implements IUtil { failDownload(new M3U8Exception(TAG, String.format("ts地址错误,url:%s", url)), false); return; } - //todo url 需要去重 mLoader.offerPeer(url); } }); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java index 2f502983..f265e660 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java @@ -100,7 +100,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader { } @Override protected void setMaxSpeed(int maxSpeed) { - // TODO: 2019-06-06 展不支持 + // TODO: 2019-06-06 暂不支持 } private void notifyLock() { @@ -199,7 +199,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader { } /** - * M3U8线程状态管理 + * M3U8线程状态管理,直播不处理停止状态、删除、失败的状态 */ private class LiveStateManager implements IThreadState { private final String TAG = "M3U8ThreadStateManager"; @@ -208,8 +208,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader { * 任务状态回调 */ private IEventListener mListener; - private int mCancelNum = 0; // 已经取消的线程的数 - private int mStopNum = 0; // 已经停止的线程数 private long mProgress; //当前总进度 private Looper mLooper; @@ -232,7 +230,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case STATE_STOP: - mStopNum++; if (isStop()) { ALog.d(TAG, "任务停止"); mListener.onStop(mProgress); @@ -240,7 +237,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader { } break; case STATE_CANCEL: - mCancelNum++; if (isCancel()) { ALog.d(TAG, "任务取消"); mListener.onCancel(); @@ -258,23 +254,18 @@ public class M3U8LiveLoader extends BaseM3U8Loader { } @Override public boolean isStop() { - // 某些服务器后一次性发送多个ts地址,所以不能简单使用mStopNum == mFlagQueue.size();判断状态 - //return mStopNum == mFlagQueue.size(); return false; } @Override public boolean isFail() { - // 直播下载不处理失败的切片 return false; } @Override public boolean isComplete() { - // 直播不处理完成 return false; } @Override public boolean isCancel() { - //return mCancelNum == mFlagQueue.size(); return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java index 9f4e2703..b2f79b9e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java @@ -82,6 +82,19 @@ public class M3U8TaskConfig { */ private ILiveTsUrlConverter liveTsUrlConverter; + /** + * 直播的m3u8文件更新间隔 + */ + private long liveUpdateInterval = 10 * 1000; + + public long getLiveUpdateInterval() { + return liveUpdateInterval; + } + + public void setLiveUpdateInterval(long liveUpdateInterval) { + this.liveUpdateInterval = liveUpdateInterval; + } + public ILiveTsUrlConverter getLiveTsUrlConverter() { return liveTsUrlConverter; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java index 65ee3551..bd79bb8a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java @@ -19,6 +19,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; +import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.IThreadState; import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.common.TaskRecord; @@ -200,6 +201,8 @@ public class M3U8VodLoader extends BaseM3U8Loader { switch (msg.what) { case STATE_STOP: mStopNum++; + ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), + (AbsThreadTask) msg.obj); if (isStop()) { ALog.d(TAG, "任务停止"); mListener.onStop(mProgress); @@ -208,6 +211,8 @@ public class M3U8VodLoader extends BaseM3U8Loader { break; case STATE_CANCEL: mCancelNum++; + ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), + (AbsThreadTask) msg.obj); if (isCancel()) { ALog.d(TAG, "任务取消"); mListener.onCancel(); @@ -225,6 +230,8 @@ public class M3U8VodLoader extends BaseM3U8Loader { break; case STATE_COMPLETE: mCompleteNum++; + ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), + (AbsThreadTask) msg.obj); handlerPercent(); notifyLock(); if (isComplete()) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupEntity.java index 93be21f3..31cb6d3a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupEntity.java @@ -17,7 +17,7 @@ package com.arialyy.aria.core.inf; import android.os.Parcel; import android.os.Parcelable; -import com.arialyy.aria.orm.annotation.Primary; +import com.arialyy.aria.orm.annotation.Unique; import java.util.ArrayList; import java.util.List; @@ -28,7 +28,7 @@ public abstract class AbsGroupEntity extends AbsEntity implements Parcelable { /** * 组名,组名为任务地址相加的url的Md5 */ - @Primary protected String groupHash; + @Unique protected String groupHash; /** * 任务组别名 @@ -38,7 +38,7 @@ public abstract class AbsGroupEntity extends AbsEntity implements Parcelable { /** * 任务组下载文件的文件夹地址 */ - private String dirPath; + @Unique private String dirPath; /** * 子任务url地址 diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java index b474fe70..421fe86d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java @@ -21,8 +21,8 @@ import com.arialyy.aria.core.download.group.AbsGroupUtil; * Created by AriaL on 2017/6/29. * 任务组任务抽象类 */ -public abstract class AbsGroupTask - extends AbsTask { +public abstract class AbsGroupTask + extends AbsTask { @Override public String getKey() { return mTaskWrapper.getEntity().getKey(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTask.java index 71db595d..d3fcb898 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTask.java @@ -18,8 +18,8 @@ package com.arialyy.aria.core.inf; /** * Created by lyy on 2017/6/3. */ -public abstract class AbsNormalTask - extends AbsTask { +public abstract class AbsNormalTask + extends AbsTask { /** * 最高优先级命令,最高优先级命令有以下属性 diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java index 72e0a651..f8d7370a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java @@ -27,7 +27,7 @@ import java.util.Map; /** * Created by AriaL on 2017/6/29. */ -public abstract class AbsTask +public abstract class AbsTask implements ITask { public static final String ERROR_INFO_KEY = "ERROR_INFO_KEY"; @@ -51,7 +51,6 @@ public abstract class AbsTask temp = mThreadTasks.get(key); + if (temp != null && temp.size() > 0) { + FutureContainer tempC = null; + for (FutureContainer container : temp) { + if (container.threadTask == task) { + tempC = container; + break; + } + } + if (tempC != null) { + task.setInterrupted(true); + temp.remove(tempC); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + LOCK.unlock(); + } + } + /** * 重试线程任务 * 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 aee68a8c..09385de4 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java @@ -25,6 +25,7 @@ import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UTaskWrapper; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -34,7 +35,7 @@ import java.util.Map; class DBConfig { /*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/ static boolean DEBUG = false; - static Map mapping = new HashMap<>(); + static Map mapping = new LinkedHashMap<>(); static String DB_NAME; static int VERSION = 48; 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 f977bd74..ae8e01ad 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java @@ -15,11 +15,11 @@ */ package com.arialyy.aria.orm; -import android.annotation.TargetApi; +import android.annotation.SuppressLint; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.os.Build; import android.text.TextUtils; +import android.util.SparseArray; import com.arialyy.aria.orm.annotation.Many; import com.arialyy.aria.orm.annotation.One; import com.arialyy.aria.orm.annotation.Wrapper; @@ -29,9 +29,8 @@ import com.arialyy.aria.util.CommonUtil; import java.lang.reflect.Field; import java.net.URLDecoder; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -127,11 +126,11 @@ class DelegateFind extends AbsDelegate { * @param page 当前页 * @param num 一页的数量 */ - private List exeRelationSql(SQLiteDatabase db, Class clazz, + private List exeRelationSql(SQLiteDatabase db, Class wrapperClazz, int page, int num, String... expression) { db = checkDb(db); - if (SqlUtil.isWrapper(clazz)) { - Field[] om = getOneAndManyField(clazz); + if (SqlUtil.isWrapper(wrapperClazz)) { + Field[] om = getOneAndManyField(wrapperClazz); if (om == null) { return null; } @@ -145,8 +144,6 @@ class DelegateFind extends AbsDelegate { final String cTableName = childClazz.getSimpleName(); List pColumn = SqlUtil.getAllNotIgnoreField(parentClazz); List cColumn = SqlUtil.getAllNotIgnoreField(childClazz); - List pColumnAlias = new ArrayList<>(); - List cColumnAlias = new ArrayList<>(); StringBuilder pSb = new StringBuilder(); StringBuilder cSb = new StringBuilder(); @@ -154,7 +151,6 @@ class DelegateFind extends AbsDelegate { pSb.append(pTableName.concat(".rowid AS ").concat(PARENT_COLUMN_ALIAS).concat("rowid,")); for (Field f : pColumn) { String temp = PARENT_COLUMN_ALIAS.concat(f.getName()); - pColumnAlias.add(temp); pSb.append(pTableName.concat(".").concat(f.getName())) .append(" AS ") .append(temp) @@ -166,7 +162,6 @@ class DelegateFind extends AbsDelegate { pSb.append(cTableName.concat(".rowid AS ").concat(CHILD_COLUMN_ALIAS).concat("rowid,")); for (Field f : cColumn) { String temp = CHILD_COLUMN_ALIAS.concat(f.getName()); - cColumnAlias.add(temp); cSb.append(cTableName.concat(".").concat(f.getName())) .append(" AS ") .append(temp) @@ -223,8 +218,7 @@ class DelegateFind extends AbsDelegate { } Cursor cursor = db.rawQuery(sql, null); List data = - (List) newInstanceEntity(clazz, parentClazz, childClazz, cursor, pColumn, cColumn, - pColumnAlias, cColumnAlias); + newInstanceEntity(wrapperClazz, parentClazz, childClazz, cursor, pColumn, cColumn); closeCursor(cursor); return data; } catch (ClassNotFoundException e) { @@ -242,139 +236,84 @@ class DelegateFind extends AbsDelegate { * * @param pColumn 父表的所有字段 * @param cColumn 字表的所有字段 - * @param pColumnAlias 关联查询父表别名 - * @param cColumnAlias 关联查询子表别名 */ private synchronized List newInstanceEntity( - Class clazz, Class

parent, - Class child, + Class wrapperClazz, Class

parentClazz, + Class childClazz, Cursor cursor, - List pColumn, List cColumn, - List pColumnAlias, List cColumnAlias) { - try { - String parentPrimary = ""; //父表主键别名 - for (Field f : pColumn) { - if (SqlUtil.isPrimary(f)) { - parentPrimary = PARENT_COLUMN_ALIAS.concat(f.getName()); - break; - } - } - - List wrappers = new ArrayList<>(); - Map tempParent = new LinkedHashMap<>(); // 所有父表元素,key为父表主键的值 - Map> tempChild = new LinkedHashMap<>(); // 所有的字表元素,key为父表主键的值 + List pColumn, List cColumn) { + List wrappers = new ArrayList<>(); + SparseArray> childs = new SparseArray<>(); // 所有子表数据 + SparseArray parents = new SparseArray<>(); // 所有父表数据 - Object old = null; + try { while (cursor.moveToNext()) { - //创建父实体 - Object ppValue = setPPValue(parentPrimary, cursor); - if (old == null || ppValue != old) { //当主键不同时,表示是不同的父表数据 - old = ppValue; - if (tempParent.get(old) == null) { - P pEntity = parent.newInstance(); - String pPrimaryName = ""; - for (int i = 0, len = pColumnAlias.size(); i < len; i++) { - Field pField = pColumn.get(i); - pField.setAccessible(true); - Class type = pField.getType(); - int column = cursor.getColumnIndex(pColumnAlias.get(i)); - if (column == -1) continue; - setFieldValue(type, pField, column, cursor, pEntity); - - if (SqlUtil.isPrimary(pField) && (type == int.class || type == Integer.class)) { - pPrimaryName = pField.getName(); - } - } - - //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 - pEntity.rowID = cursor.getInt( - cursor.getColumnIndex( - TextUtils.isEmpty(pPrimaryName) ? PARENT_COLUMN_ALIAS.concat("rowid") - : pPrimaryName)); - - tempParent.put(ppValue, pEntity); - } - } - - // 创建子实体 - C cEntity = child.newInstance(); - String cPrimaryName = ""; - for (int i = 0, len = cColumnAlias.size(); i < len; i++) { - Field cField = cColumn.get(i); - cField.setAccessible(true); - Class type = cField.getType(); - - int column = cursor.getColumnIndex(cColumnAlias.get(i)); - if (column == -1) continue; - setFieldValue(type, cField, column, cursor, cEntity); - - if (SqlUtil.isPrimary(cField) && (type == int.class || type == Integer.class)) { - cPrimaryName = cField.getName(); - } + int pRowId = cursor.getInt(cursor.getColumnIndex(PARENT_COLUMN_ALIAS.concat("rowid"))); + if (childs.get(pRowId) == null) { + childs.put(pRowId, new ArrayList()); + parents.put(pRowId, createParent(pRowId, parentClazz, pColumn, cursor)); } - //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 - cEntity.rowID = cursor.getInt( - cursor.getColumnIndex( - TextUtils.isEmpty(cPrimaryName) ? CHILD_COLUMN_ALIAS.concat("rowid") - : cPrimaryName)); - if (tempChild.get(old) == null) { - tempChild.put(old, new ArrayList()); - } - tempChild.get(old).add(cEntity); + childs.get(pRowId).add(createChild(childClazz, cColumn, cursor)); } - List wFields = SqlUtil.getAllNotIgnoreField(clazz); - if (wFields != null && !wFields.isEmpty()) { - Set pKeys = tempParent.keySet(); - for (Object pk : pKeys) { - T wrapper = clazz.newInstance(); - P p = tempParent.get(pk); - boolean isPSet = false, isCSet = false; - for (Field f : wFields) { - if (!isPSet && f.getAnnotation(One.class) != null) { - f.set(wrapper, p); - isPSet = true; - } - if (!isCSet && f.getAnnotation(Many.class) != null) { - f.set(wrapper, tempChild.get(pk)); - isCSet = true; - } + List wFields = SqlUtil.getAllNotIgnoreField(wrapperClazz); + if (wFields == null || wFields.isEmpty()) { + return null; + } + for (int i = 0; i < parents.size(); i++) { + int pRowId = parents.keyAt(i); + T wrapper = wrapperClazz.newInstance(); + boolean isPSet = false, isCSet = false; // 保证One 或 Many 只设置一次 + for (Field f : wFields) { + if (!isPSet && f.getAnnotation(One.class) != null) { + f.set(wrapper, parents.get(pRowId)); + isPSet = true; + } + if (!isCSet && f.getAnnotation(Many.class) != null) { + f.set(wrapper, childs.get(pRowId)); + isCSet = true; } - wrapper.handleConvert(); //处理下转换 - wrappers.add(wrapper); } + wrapper.handleConvert(); //处理下转换 + wrappers.add(wrapper); } - return wrappers; - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { + } catch (Exception e) { e.printStackTrace(); } - return null; + + return wrappers; } /** - * 获取父表主键数据 - * - * @param parentPrimary 父表主键别名 + * 创建子对象 */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) private Object setPPValue(String parentPrimary, - Cursor cursor) { - Object ppValue = null; - int ppColumn = cursor.getColumnIndex(parentPrimary); //父表主键所在的列 - int type = cursor.getType(ppColumn); - switch (type) { - case Cursor.FIELD_TYPE_INTEGER: - ppValue = cursor.getLong(ppColumn); - break; - case Cursor.FIELD_TYPE_FLOAT: - ppValue = cursor.getFloat(ppColumn); - break; - case Cursor.FIELD_TYPE_STRING: - ppValue = cursor.getString(ppColumn); - break; + private T createChild(Class childClazz, List cColumn, + Cursor cursor) + throws InstantiationException, IllegalAccessException { + T child = childClazz.newInstance(); + child.rowID = cursor.getInt(cursor.getColumnIndex(CHILD_COLUMN_ALIAS.concat("rowid"))); + for (Field field : cColumn) { + field.setAccessible(true); + int columnIndex = cursor.getColumnIndex(CHILD_COLUMN_ALIAS.concat(field.getName())); + setFieldValue(field.getType(), field, columnIndex, cursor, child); } - return ppValue; + return child; + } + + /** + * 创建父对象 + */ + private T createParent(int rowId, Class parentClazz, List pColumn, + Cursor cursor) + throws InstantiationException, IllegalAccessException { + T parent = parentClazz.newInstance(); + parent.rowID = rowId; + for (Field field : pColumn) { + field.setAccessible(true); + int columnIndex = cursor.getColumnIndex(PARENT_COLUMN_ALIAS.concat(field.getName())); + setFieldValue(field.getType(), field, columnIndex, cursor, parent); + } + return parent; } /** @@ -467,9 +406,9 @@ class DelegateFind extends AbsDelegate { String sql, String[] selectionArgs) { String[] temp = new String[selectionArgs.length]; int i = 0; - for (String arg : selectionArgs){ + for (String arg : selectionArgs) { temp[i] = encodeStr(arg); - i ++; + i++; } Cursor cursor = db.rawQuery(sql, temp); List data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; @@ -525,43 +464,44 @@ class DelegateFind extends AbsDelegate { * * @throws IllegalAccessException */ - private void setFieldValue(Class type, Field field, int column, Cursor cursor, Object entity) + private void setFieldValue(Class type, Field field, int columnIndex, Cursor cursor, + DbEntity entity) throws IllegalAccessException { if (cursor == null || cursor.isClosed()) { ALog.e(TAG, "cursor没有初始化"); return; } if (type == String.class) { - String temp = cursor.getString(column); + String temp = cursor.getString(columnIndex); if (!TextUtils.isEmpty(temp)) { field.set(entity, URLDecoder.decode(temp)); } } else if (type == int.class || type == Integer.class) { - field.setInt(entity, cursor.getInt(column)); + field.setInt(entity, cursor.getInt(columnIndex)); } else if (type == float.class || type == Float.class) { - field.setFloat(entity, cursor.getFloat(column)); + field.setFloat(entity, cursor.getFloat(columnIndex)); } else if (type == double.class || type == Double.class) { - field.setDouble(entity, cursor.getDouble(column)); + field.setDouble(entity, cursor.getDouble(columnIndex)); } else if (type == long.class || type == Long.class) { - field.setLong(entity, cursor.getLong(column)); + field.setLong(entity, cursor.getLong(columnIndex)); } else if (type == boolean.class || type == Boolean.class) { - String temp = cursor.getString(column); + String temp = cursor.getString(columnIndex); if (TextUtils.isEmpty(temp)) { field.setBoolean(entity, false); } else { field.setBoolean(entity, !temp.equalsIgnoreCase("false")); } } else if (type == java.util.Date.class || type == java.sql.Date.class) { - field.set(entity, new Date(URLDecoder.decode(cursor.getString(column)))); + field.set(entity, new Date(URLDecoder.decode(cursor.getString(columnIndex)))); } else if (type == byte[].class) { - field.set(entity, cursor.getBlob(column)); + field.set(entity, cursor.getBlob(columnIndex)); } else if (type == Map.class) { - String temp = cursor.getString(column); + String temp = cursor.getString(columnIndex); if (!TextUtils.isEmpty(temp)) { field.set(entity, SqlUtil.str2Map(URLDecoder.decode(temp))); } } else if (type == List.class) { - String value = cursor.getString(column); + String value = cursor.getString(columnIndex); if (!TextUtils.isEmpty(value)) { field.set(entity, SqlUtil.str2List(URLDecoder.decode(value), field)); } 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 897cb3a3..dc67dd72 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java @@ -141,7 +141,7 @@ final class SqlHelper extends SQLiteOpenHelper { } /** - * 处理数据库升级,该段代码无法修改表字段 + * 处理数据库升级 * * @param modifyColumns 需要修改的表字段的映射,key为表名, * value{@code Map}中的Map的key为老字段名称,value为该老字段对应的新字段名称 @@ -176,8 +176,9 @@ final class SqlHelper extends SQLiteOpenHelper { long count = cursor.getLong(0); cursor.close(); + // 复制数据 if (count > 0) { - // 获取所有表字段名称 + // 获取旧表的所有字段名称 Cursor columnC = db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null); StringBuilder params = new StringBuilder(); @@ -243,11 +244,17 @@ final class SqlHelper extends SQLiteOpenHelper { mDelegate.dropTable(db, taskTable); } } + Map> columnMap = new HashMap<>(); - Map map = new HashMap<>(); - map.put("groupName", "groupHash"); - columnMap.put("DownloadEntity", map); - columnMap.put("DownloadGroupEntity", map); + // 处理DownloadEntity、DownloadGroupEntity的 groupName字段名的修改 + Map groupNameModify = new HashMap<>(); + groupNameModify.put("groupName", "groupHash"); + columnMap.put("DownloadEntity", groupNameModify); + columnMap.put("DownloadGroupEntity", groupNameModify); + // 处理TaskRecord的dGroupName字段名的修改 + Map dGroupNameModify = new HashMap<>(); + dGroupNameModify.put("dGroupName", "dGroupHash"); + columnMap.put("TaskRecord", dGroupNameModify); handleDbUpdate(db, columnMap, null); } @@ -263,7 +270,7 @@ final class SqlHelper extends SQLiteOpenHelper { } } - //删除所有主键为null和逐渐重复的数据 + //删除所有主键为null和主键重复的数据 String[] tables = new String[] { "DownloadEntity", "DownloadGroupEntity" }; String[] keys = new String[] { "downloadPath", "groupName" }; int i = 0; diff --git a/DEV_LOG.md b/DEV_LOG.md index 01263b66..a9cbc75b 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -3,6 +3,11 @@ - fix bug https://github.com/AriaLyy/Aria/issues/403 - 新增ftp上传拦截器 https://github.com/AriaLyy/Aria/issues/402 - 重构线程任务模块 + - 修复一个低版本数据库升级的问题 https://github.com/AriaLyy/Aria/issues/407 + - 新增遵循m3u8协议的文件下载 + - 修复拦截器可能出现的空指针问题 + - 移除`DownloadGroupEntity`字段`groupHash`的主键约束,`DownloadEntity`字段`groupHash`的外键约束,`TaskRecord`字段`dGroupHash`的外键约束 + - 优化关联查询的性能 + v_3.6.4 (2019/5/16) - 优化任务接收器的代码结构 - 修复`DbEntity.saveAll()`失败的问题 diff --git a/app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodModule.java b/app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodModule.java index 73162a9a..b91ab345 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodModule.java +++ b/app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodModule.java @@ -34,7 +34,7 @@ public class M3U8VodModule extends BaseViewModule { // m3u8测试集合:http://www.voidcn.com/article/p-snaliarm-ct.html //private final String defUrl = "https://www.gaoya123.cn/2019/1557993797897.m3u8"; // 多码率地址: - private final String defUrl = "http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8"; + private final String defUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"; private final String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/1557993797897.ts"; diff --git a/app/src/main/java/com/arialyy/simple/core/download/multi_download/FileListAdapter.java b/app/src/main/java/com/arialyy/simple/core/download/multi_download/FileListAdapter.java index 43783372..9e349631 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/multi_download/FileListAdapter.java +++ b/app/src/main/java/com/arialyy/simple/core/download/multi_download/FileListAdapter.java @@ -73,6 +73,7 @@ final class FileListAdapter extends AbsRVAdapter { } @DownloadGroup.onTaskFail void groupTaskFail(DownloadGroupTask task) { + if (task == null){ + return; + } mAdapter.updateBtState(task.getKey(), true); Log.d(TAG, String.format("group【%s】fail", task.getTaskName())); }