问题重现
BackgroundDownload.recreate() 方法在如下代码行存在崩溃风险:
Uri dest = Uri.parse(cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
如果下载未完成或本地路径尚未生成,COLUMN_LOCAL_URI 可能为 null,从而导致 Uri.parse(null) 抛出 NullPointerException。
现象
- 下载任务过程中(未完成前)调用 recreate() 恢复任务会因上述代码崩溃。
- cursor 其他字段如 COLUMN_URI 也可能不合法。
- cursor 没有保证始终关闭(close)。
合理修复建议
- 增加 null 检查:若
COLUMN_LOCAL_URI 为空,则用 Uri.EMPTY(或 null)占位,允许后续行为正常继续。
- 优化 cursor 管理,使用 try-finally 保证 close。
- 兼容 COLUMN_URI 为 null 时直接返回 null,防止恢复损坏任务。
- 示例修改:
public static BackgroundDownload recreate(Context context, long id) {
DownloadManager manager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = manager.query(query);
try {
if (cursor.getCount() == 0)
return null;
cursor.moveToFirst();
String urlStr = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
if (urlStr == null) {
return null;
}
Uri url = Uri.parse(urlStr);
String destStr = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
Uri dest = (destStr != null) ? Uri.parse(destStr) : Uri.EMPTY;
return new BackgroundDownload(manager, id, url, dest);
} finally {
cursor.close();
}
}
- 建议对 checkFinished、getProgress 等 cursor 操作同样统一用 try-finally。
修复好处
- 避免 NPE,提升稳定性。
- cursor 安全释放,防内存泄漏。
- 更易理解和扩展,兼容不同状态的下载任务。
问题重现
BackgroundDownload.recreate()方法在如下代码行存在崩溃风险:如果下载未完成或本地路径尚未生成,
COLUMN_LOCAL_URI可能为 null,从而导致Uri.parse(null)抛出 NullPointerException。现象
合理修复建议
COLUMN_LOCAL_URI为空,则用Uri.EMPTY(或 null)占位,允许后续行为正常继续。修复好处