Android读取CallLog通话记录时Cursor报Couldn't read row错误如何解决
报错原因
报错信息中的col -1说明c.getColumnIndex(CallLog.Calls.CACHED_PHOTO_URI)调用返回了-1,即当前查询返回的Cursor中不存在指定列,和你查询全列还是单列无关,具体触发原因如下:
CallLog.Calls.CACHED_PHOTO_URI是Android 6.0(API等级23)才新增的系统字段,如果你运行App的设备系统版本低于API 23,系统通话记录Provider不会返回该字段,查询列索引自然返回-1。- 即使设备系统版本≥API 23,部分厂商定制ROM修改了通话记录Provider的实现,可能不会暴露
CACHED_PHOTO_URI字段,也会导致列索引查询失败。 - 你当前贴出的代码中没有调用Cursor指针移动方法(如
moveToFirst()、moveToNext()),Cursor默认指针位置在首行之前(索引为-1),直接取值也会触发类似报错,你报错中的row 305说明你有遍历逻辑只是未贴全,但建议补充指针位置合法性判断。
修复方案
- 增加版本判断,低于API 23的设备不要访问该字段,可通过联系人ID查询Contacts Provider获取头像。
- 取值前先判断列索引是否合法,确认列存在再读取值。
- 操作Cursor时补充指针位置判断,用完及时关闭Cursor避免内存泄漏。
修复后的参考代码如下:
Cursor c = activity.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC "); if (c == null) { // 处理Cursor为空的异常情况 return; } try { // 遍历所有通话记录 while (c.moveToNext()) { String photo = null; // 先判断系统版本是否支持该字段 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { // 先查询列索引,判断是否存在 int photoUriColIndex = c.getColumnIndex(CallLog.Calls.CACHED_PHOTO_URI); if (photoUriColIndex >= 0 && !c.isNull(photoUriColIndex)) { photo = c.getString(photoUriColIndex); Log.d("PHOTO_URI", photo); } } // 剩余逻辑处理 } } catch (Exception e) { Log.e("ERROR_LOG", e.toString()); } finally { // 用完关闭Cursor if (!c.isClosed()) { c.close(); } }
内容的提问来源于stack exchange,提问作者Unknown
相关产品推荐
相关产品推荐

