跨应用通过ContentProvider共享数据失败,查询返回Cursor为null求助
兄弟,我仔细看了你的代码和描述,发现几个很可能导致cursor为null的问题,咱们一个个来排查:
最显眼的拼写错误!这大概率是核心问题
你在第二个App里构建的URI是content://com.example.storge,但第一个App的Manifest里声明的ContentProvider authorities是com.example.storage——注意看,storge少了一个字母a!正确的应该是storage。这个拼写错误会让系统找不到对应的ContentProvider,自然返回null的cursor。先把这个改了试试!Android 11+的跨应用访问限制
如果你的测试设备是Android 11(API 30)及以上版本,第二个App需要在Manifest中添加<queries>标签,明确声明要访问的第一个App的ContentProvider权限,否则系统会默认阻止跨应用的访问请求:<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="你的第二个App包名"> <queries> <provider android:authorities="com.example.storage" /> </queries> <!-- 其他Manifest内容 --> </manifest>ContentProvider缺少URI匹配逻辑(规范优化)
你的Provider类没有使用UriMatcher来校验传入的URI,虽然当前只处理一张表,但没有匹配逻辑的话,后续扩展或者URI写错时更容易出问题。可以按下面的方式优化你的Provider:class Provider : ContentProvider() { private lateinit var db: LoginSqliteHelper private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH) companion object { private const val TABLE_QUERY_CODE = 1 // 定义标准的CONTENT_URI const val CONTENT_URI = "content://com.example.storage/${ConstantValue.Table_Name}" } override fun onCreate(): Boolean { db = LoginSqliteHelper(context!!) // 添加URI匹配规则,指定匹配我们的表 uriMatcher.addURI("com.example.storage", ConstantValue.Table_Name, TABLE_QUERY_CODE) return true } override fun query( uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String? ): Cursor? { // 先匹配URI,只有合法的URI才处理 return when (uriMatcher.match(uri)) { TABLE_QUERY_CODE -> { db.readableDatabase.query( ConstantValue.Table_Name, projection, selection, selectionArgs, null, null, sortOrder ) } else -> null // 不匹配的URI直接返回null } } // 其他方法保持不变... }之后第二个App里的URI就可以直接用
Uri.parse(Provider.CONTENT_URI)(如果能引用到第一个App的常量的话),或者写content://com.example.storage/你的表名,这样更规范,也不容易出错。确认第一个App的数据库中确实存在数据
虽然你说第一个App一切正常,但还是建议在第一个App里直接查询自己的数据库,确认目标表中确实有数据。如果数据库本身是空的,查询返回的cursor会是空的(但不是null),不过先排除这个可能性。
先从第一个拼写错误入手修改,应该能解决大部分问题,要是还有问题再依次排查后面的点!
备注:内容来源于stack exchange,提问作者ANAS AHMED

