Android Studio使用Cursor获取通话记录时报值需>=0的错误如何解决
问题根因
你遇到的CursorIndexOutOfBoundsException: Index -1 requested报错由以下几处代码错误共同导致:
- Cursor刚通过ContentResolver查询返回时,初始位置为**-1**,不指向任何有效数据行,你还未移动游标到有效位置就直接调用
cursor.getString()读取数据,直接触发索引越界 - 读取通话记录字段的逻辑写在循环外部,即便修复越界问题也只能获取到第一条记录的字段值,无法遍历全部通话记录
- 存储数据的
ArrayList<ModelCalls>没有初始化,后续调用add方法会触发空指针异常 - 游标遍历逻辑错误:先调用
moveToFirst()再调用moveToNext(),会漏掉第一条通话记录 - Cursor使用完成后未关闭,会产生内存泄漏
- 权限申请为异步逻辑,你在启动权限申请弹窗的同时就加载了CallLogFragment,此时权限还未获得用户授权,也会引发查询失败问题
修复方案
1. 修正CallLogFragment的getCallLog方法
private ArrayList<ModelCalls> getCallLog() { // 先初始化集合 ArrayList<ModelCalls> arrayList = new ArrayList<>(); Cursor cursor = null; try { cursor = getContext().getContentResolver().query( CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " ASC" ); // 判空再处理 if (cursor != null && cursor.moveToFirst()) { do { // 循环内读取每条记录的字段 String number = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER)); String duration = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.DURATION)); String date = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE)); String name = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.CACHED_NAME)); ModelCalls modelCalls = new ModelCalls(date, number, duration, name); arrayList.add(modelCalls); } while (cursor.moveToNext()); } } catch (SecurityException e) { // 处理未授权异常 e.printStackTrace(); } finally { // 最后关闭Cursor释放资源 if (cursor != null && !cursor.isClosed()) { cursor.close(); } } return arrayList; }
2. 修正权限加载逻辑
不要在MainActivity的onCreate中直接加载CallLogFragment,需要等用户授权完成后再加载:
- 先移除onCreate中直接替换Fragment的代码
- 新增EasyPermissions的权限回调监听,用户同意权限后再执行Fragment初始化逻辑
内容的提问来源于stack exchange,提问作者Aymane
相关产品推荐
相关产品推荐

