跨应用访问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




