You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

跨应用访问Android ContentProvider返回空Cursor问题(同应用内访问正常)

跨应用访问Android ContentProvider返回空Cursor问题(同应用内访问正常)

兄弟,我之前也踩过一模一样的坑!同应用内调用ContentProvider完全正常,跨到另一个APP就返回空Cursor,大概率是这几个关键配置没做对,我给你挨个排查:

1. 权限配置是核心大坑

首先得确保App A的ContentProvider已经对外开放权限,并且App B已经申请到对应权限:

  • 在App A的AndroidManifest.xml里,先声明自定义权限,再配置Provider:
<!-- 先声明对外访问的权限 -->
<permission
    android:name="com.example.appa.PROVIDER_ACCESS"
    android:protectionLevel="normal" />

<provider
    android:name=".MyCustomContentProvider"
    android:authorities="com.example.appa.myprovider"
    android:exported="true"
    android:grantUriPermissions="true"
    android:permission="com.example.appa.PROVIDER_ACCESS" />

这里重点注意protectionLevel,别设成signature(除非两个APP用同一个签名文件打包),不然普通权限申请了也不生效。

  • 然后在App B的AndroidManifest.xml里申请这个权限:
<uses-permission android:name="com.example.appa.PROVIDER_ACCESS" />

2. 别搞混Authority!

你在App B里发起query请求的Uri,它的authority必须和App A里Provider声明的完全一致,多一个字母、少一个点都不行!我之前就是手滑把com.example.appa.myprovider写成了com.example.appa.provider,查了俩小时才发现。

3. 检查Provider内部的校验逻辑

如果你在自定义ContentProvider的query方法里加了额外的权限或包名校验,一定要确保没把App B的请求给拦截了:
比如这种错误的校验逻辑会直接返回空Cursor:

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    // 错误示例:权限校验写错导致拦截
    if (!checkCallingPermission("com.example.appa.WRONG_PERMISSION")) {
        return null; // 直接返回空,外部就拿到null Cursor
    }
    // 或者包名校验漏了App B
    String callerPackage = getContext().getPackageManager().getPackagesForUid(getCallingUid())[0];
    if (!callerPackage.equals("com.example.anotherapp")) {
        return null;
    }
    // 正常查询逻辑
    SQLiteDatabase db = mDbHelper.getReadableDatabase();
    return db.query("my_table", projection, selection, selectionArgs, null, null, sortOrder);
}

仔细核对这里的权限字符串、包名,别自己把App B的请求给挡了。

4. Android 10+的包可见性配置

从Android 10开始,系统默认限制了APP对其他应用的可见性,所以App B的AndroidManifest.xml里必须加<queries>标签,声明要访问的App A或者对应的Provider:

<queries>
    <!-- 可以直接声明要访问的App A包名 -->
    <package android:name="com.example.appa" />
    <!-- 或者声明Provider的authority -->
    <provider android:authorities="com.example.appa.myprovider" />
</queries>

没加这个的话,App B可能连App A的Provider都找不到,自然返回空Cursor。

5. 最后再检查打包和安装顺序

  • 如果你的Provider权限设为signature级别,两个APP必须用同一个签名文件打包,不然权限校验通不过。
  • 先安装App A,再安装App B,避免App B安装时无法正确识别App A的权限配置。

备注:内容来源于stack exchange,提问作者danimadmolil

火山引擎 最新活动