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
相关产品推荐
相关产品推荐

