From 3f53971e6d7937a41ac2e8bb129696610aae9158 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Fri, 4 Sep 2026 17:19:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(core):=20=E4=BF=AE=E5=A4=8D=E6=81=A2?= =?UTF-8?q?=E5=A4=8DUri=E6=A8=A1=E5=BC=8F=E4=BB=BB=E5=8A=A1=E6=97=B6?= =?UTF-8?q?=E7=9B=AE=E6=A0=87=E4=B8=A2=E5=A4=B1=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?NPE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从持久化实体恢复DTaskWrapper的fileUri - 启动任务前校验下载目标有效性 - 在适配器中兜底恢复Uri并校验文件路径 - 版本号更新为3.8.17-beta-1 --- .../aria/core/download/DTaskWrapper.java | 6 +++++ .../aria/core/loader/AbsNormalLoaderUtil.java | 27 +++++++++++++++++++ .../loader/AbsNormalTTBuilderAdapter.java | 17 ++++++++++-- build.gradle | 6 ++--- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskWrapper.java b/PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskWrapper.java index 8932de87..69565140 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskWrapper.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskWrapper.java @@ -64,6 +64,12 @@ public class DTaskWrapper extends AbsTaskWrapper { public DTaskWrapper(DownloadEntity entity) { super(entity); + // 从持久化的实体恢复分区存储(Uri)模式:任务恢复/重建时,实体的 fileUri 字段已落库, + // 但 mTempFileUri 是瞬时变量,需要在此同步,否则 isUriMode()/getFileUri() 会误判为普通文件路径模式 + if (entity != null && !TextUtils.isEmpty(entity.getFileUri())) { + this.mTempFileUri = entity.getFileUri(); + this.mTempFilePath = null; + } } public ITaskOption getM3u8Option() { diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderUtil.java index 04002742..9faa6fcd 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderUtil.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderUtil.java @@ -16,6 +16,10 @@ package com.arialyy.aria.core.loader; +import android.text.TextUtils; + +import com.arialyy.aria.core.download.DTaskWrapper; +import com.arialyy.aria.core.common.AbsNormalEntity; import com.arialyy.aria.core.inf.IUtil; import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; @@ -108,6 +112,12 @@ public abstract class AbsNormalLoaderUtil implements IUtil { ALog.w(TAG, "启动任务失败,任务已停止或已取消"); return; } + // 兜底:下载目标(Uri 或文件路径)均无效时,直接失败回调,避免后续构建加载器时 new File(null) 抛出 NPE + if (!hasValidTarget()) { + ALog.e(TAG, "启动任务失败,下载目标(Uri 或文件路径)为空"); + fail(new AriaException("下载目标(Uri 或文件路径)为空,无法启动任务"), false); + return; + } mListener.onPre(); // 如果网址没有变,而服务器端端文件改变,以下代码就没有用了 //if (mTaskWrapper.getEntity().getFileSize() <= 1 @@ -128,6 +138,23 @@ public abstract class AbsNormalLoaderUtil implements IUtil { } + /** + * 校验任务是否拥有有效的下载目标:分区存储(Uri)模式或非空的本地文件路径,二者满足其一即可。 + * 用于拦截下载目标无效的任务,避免后续构建加载器时因 filePath 为 null 而抛出 NPE。 + */ + private boolean hasValidTarget() { + AbsTaskWrapper w = mTaskWrapper; + if (w instanceof DTaskWrapper) { + // 分区存储 Uri 任务以 Uri 为目标,downloadPath 为空是正常情况 + return ((DTaskWrapper) w).isUriMode() + || !TextUtils.isEmpty(((DTaskWrapper) w).getTempFilePath()); + } + if (w.getEntity() instanceof AbsNormalEntity) { + return !TextUtils.isEmpty(((AbsNormalEntity) w.getEntity()).getFilePath()); + } + return false; + } + public boolean isStop() { return isStop; } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java index ffb58382..646a7036 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java @@ -24,8 +24,10 @@ import com.arialyy.aria.core.ThreadRecord; import com.arialyy.aria.core.common.AbsNormalEntity; import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.download.DTaskWrapper; +import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.task.IThreadTaskAdapter; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; +import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; import java.io.File; @@ -44,13 +46,24 @@ public abstract class AbsNormalTTBuilderAdapter { this.wrapper = wrapper; String uri = null; if (wrapper instanceof DTaskWrapper) { - uri = ((DTaskWrapper) wrapper).getFileUri(); + DTaskWrapper dw = (DTaskWrapper) wrapper; + uri = dw.getFileUri(); + // 兜底:任务恢复时若瞬时变量 mTempFileUri 为空,则从持久化的实体字段恢复 Uri 模式 + if (TextUtils.isEmpty(uri) && dw.getEntity() instanceof DownloadEntity) { + uri = ((DownloadEntity) dw.getEntity()).getFileUri(); + } } if (!TextUtils.isEmpty(uri)) { mIsUriMode = true; mUri = Uri.parse(uri); } else { - tempFile = new File(((AbsNormalEntity) wrapper.getEntity()).getFilePath()); + String filePath = ((AbsNormalEntity) wrapper.getEntity()).getFilePath(); + if (TextUtils.isEmpty(filePath)) { + // 既没有 Uri 也没有本地文件路径,无法继续下载,避免后续 new File(null) 抛出 NPE + ALog.e(TAG, "下载失败,文件保存路径和 Uri 均为空,无法创建下载任务"); + return; + } + tempFile = new File(filePath); } } diff --git a/build.gradle b/build.gradle index 8cf84239..75530390 100644 --- a/build.gradle +++ b/build.gradle @@ -56,8 +56,8 @@ task clean(type: Delete) { } ext { - versionCode = 390 - versionName = '3.8.16-beta-1' + versionCode = 391 + versionName = '3.8.17-beta-1' userOrg = 'arialyy' groupId = 'com.arialyy.aria' publishVersion = versionName @@ -70,7 +70,7 @@ ext { licences = ['Apache-2.0'] // mavenCentral - mavenVersion = '3.8.16' + mavenVersion = '3.8.17' mavenCentralGroupId = 'me.laoyuyu.aria' mavenCentralUserID = 'laoyuyu' mavenCentralUserName = 'laoyuyu'