You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android DownloadManager下载完成广播接收器报错:Cursor索引越界

嘿,这个问题我之前处理过好几次,核心原因其实挺典型的——你忽略了Android Cursor的基础操作规范!下面给你拆解问题根源和具体修复方案:

问题根源拆解

你遇到的CursorIndexOutOfBoundsException(索引-1请求,游标大小为1),本质是:刚查询出来的Cursor默认停在索引-1的位置(还没指向任何数据行),你直接去读取列数据就会触发这个异常。哪怕Cursor的大小显示是1,也必须先把游标移动到有效行才能访问数据。

另外还有两个可能的诱因:

  • 在DOWNLOAD_COMPLETE广播接收器里,没正确处理Intent传递的下载ID,导致查询逻辑顺序出错
  • 多个下载任务同时完成触发广播,造成Cursor操作混乱
具体修复方案

1. 强制让Cursor移动到有效行(最核心的修复)

在你获取Cursor之后,必须先调用moveToFirst()或者moveToPosition(0),而且要判断移动是否成功(防止Cursor为空或无数据的极端情况)。给你改一下状态获取的代码示例:

private void getDownloadStatus(long downloadId) {
    DownloadManager.Query query = new DownloadManager.Query();
    query.setFilterById(downloadId);
    Cursor cursor = downloadManager.query(query);
    
    if (cursor != null) {
        // 先把游标移到第一行,并且确认移动成功
        if (cursor.moveToFirst()) {
            int statusColIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
            int downloadStatus = cursor.getInt(statusColIndex);
            
            // 这里处理下载状态逻辑
            switch (downloadStatus) {
                case DownloadManager.STATUS_SUCCESSFUL:
                    // 处理下载完成后的逻辑,比如获取文件路径
                    String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    break;
                case DownloadManager.STATUS_FAILED:
                    // 处理下载失败逻辑
                    break;
                // 其他状态按需处理
            }
        }
        // 一定要关闭Cursor,避免内存泄漏!
        cursor.close();
    }
}

2. 广播接收器里安全处理下载ID

在接收DOWNLOAD_COMPLETE广播时,要确保从Intent里拿到的下载ID是有效的,避免传入无效ID导致查询异常:

public class DownloadCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
            // 获取下载ID,默认值设为-1用来判断有效性
            Long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            if (downloadId != -1) {
                // 调用状态处理方法
                getDownloadStatus(downloadId);
            }
        }
    }
}

3. 额外的防御性建议

  • 永远要检查Cursor是否为null,用完后必须关闭,不然容易造成内存泄漏
  • 如果你的App同时处理多个下载任务,可以用HashMap把下载ID和对应的任务信息关联起来,避免任务混淆
  • 可以在查询后通过cursor.getCount()确认是否有数据,再进行后续操作
踩坑提醒

很多开发者会误以为“游标大小是1就可以直接读数据”,但Cursor的初始位置永远是-1,这是Android Cursor的设计规范,也是这个异常最常见的触发点,记住这个细节就能避免大部分类似问题。

内容的提问来源于stack exchange,提问作者KZoNE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:16:38