fix(core): 修复恢复Uri模式任务时目标丢失导致的NPE

- 从持久化实体恢复DTaskWrapper的fileUri
- 启动任务前校验下载目标有效性
- 在适配器中兜底恢复Uri并校验文件路径
- 版本号更新为3.8.17-beta-1
This commit is contained in:
2026-09-04 17:19:27 +08:00
parent 51eb7e9cb7
commit 3f53971e6d
4 changed files with 51 additions and 5 deletions

View File

@@ -64,6 +64,12 @@ public class DTaskWrapper extends AbsTaskWrapper<DownloadEntity> {
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() {

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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'