You need to enable JavaScript to run this app. Android Content Resolver点击加载崩溃、返回空Cursor的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Android Content Resolver点击加载崩溃、返回空Cursor的问题排查

崩溃定位与修复方案

直接崩溃原因

触发崩溃的直接原因:getContentResolver().query() 方法执行后返回了null空对象,代码未做非空校验直接调用cursor.moveToFirst(),触发空指针异常。
跨进程访问场景下,只要Provider注册、URI匹配、SQL查询任何一个环节出错,系统都不会把具体异常抛给Resolver端,只会返回空cursor,这是ContentProvider跨应用调用类崩溃的典型表现。

分步修复方案

  • 修正Content Provider应用的Manifest配置
    ContentProvider必须显式声明在Manifest中,跨应用访问时必须开启导出权限,否则系统无法识别该Provider,所有跨进程调用都会返回空cursor:
    <provider
        android:name=".database.SeekersContactsProvider"
        android:authorities="com.example.connectly"
        android:exported="true" />
    
    注意三个校验点:
    • authorities值必须和代码里定义的AUTHORITY字符串完全一致,不能有拼写错误
    • Android 12及以上版本必须显式声明android:exported="true",否则应用安装时会报错,Provider根本不会注册到系统服务
    • provider的类路径要和实际的Provider全类名完全匹配
  • 修复Content Provider端的query逻辑缺陷
    现有Provider代码存在两个会导致跨进程返回空cursor的隐患:
    1. 硬编码使用内置ALL_COLUMNS作为查询列,完全忽略Resolver端传入的projection参数,如果Resolver传入的列名不存在,SQL查询会直接抛异常,跨进程场景下异常被系统捕获后就会返回空cursor
    2. 当URI不匹配时直接抛出IllegalArgumentException,跨进程场景下这个异常同样会被系统捕获,最终返回空cursor给调用方
      修复后的核心query逻辑:
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        int uriMatch = uriMatcher.match(uri);
        // 不匹配的URI直接返回null,不要抛出跨进程异常
        if (uriMatch != SEEKER) {
            return null;
        }
        // 外部未传排序规则时,使用默认的firstname升序
        String orderBy = sortOrder != null ? sortOrder : "firstname ASC";
        // 外部传入projection就使用外部规则,未传就用默认全列
        String[] queryColumns = projection != null ? projection : ALL_COLUMNS;
        Cursor queryCursor = seekerSQLiteDatabase.query(
                SEEKER_TABLE_NAME,
                queryColumns,
                selection,
                selectionArgs,
                null,
                null,
                orderBy
        );
        queryCursor.setNotificationUri(getContext().getContentResolver(), uri);
        return queryCursor;
    }
    
  • 给Resolver端的查询逻辑增加防护
    不管前期配置是否完善,都要对query返回的cursor做非空校验,避免任意场景下直接崩溃;同时cursor使用完成后必须关闭,避免内存泄漏:
    修复后的按钮点击逻辑:
    @Override
    public void onClick(View v) {
        TextView resultView = findViewById(R.id.textView);
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(
                    Uri.parse("content://com.example.connectly/seekers"),
                    null, null, null, null
            );
            // 必须先校验cursor非空,再执行遍历
            if (cursor != null && cursor.moveToFirst()) {
                StringBuilder strBuild = new StringBuilder();
                while (!cursor.isAfterLast()) {
                    strBuild.append("\n")
                            .append(cursor.getString(cursor.getColumnIndex("firstname")))
                            .append("-")
                            .append(cursor.getString(cursor.getColumnIndex("lastname")))
                            .append(cursor.getString(cursor.getColumnIndex("email")))
                            .append(cursor.getString(cursor.getColumnIndex("phone")))
                            .append(cursor.getString(cursor.getColumnIndex("age")))
                            .append(cursor.getString(cursor.getColumnIndex("dob")))
                            .append(cursor.getString(cursor.getColumnIndex("gender")));
                    cursor.moveToNext();
                }
                resultView.setText(strBuild);
            } else {
                resultView.setText("No Records Found");
            }
        } finally {
            // 关闭cursor释放资源
            if (cursor != null) {
                cursor.close();
            }
        }
    }
    
  • 排查其他隐藏问题
    • 安装顺序:Content Provider应用必须先于Resolver应用安装,否则系统找不到对应的Provider服务
    • 代码笔误:Resolver端代码第一行包名漏了开头的p,写成了ackage com.example.App2ContentProvider;,实际开发中要修正这类拼写错误
    • 全局变量优化:不要把Cursor定义成Provider的全局成员变量,多并发调用时会出现数据错乱,应该在方法内部声明局部Cursor变量

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.13 18:36:04