如何配置CWAC-Provider以实现跨应用访问?
嘿,我来帮你捋清楚怎么用StreamProvider实现AppA和AppB之间的图片资源共享~ 你已经开始配置AppA的Provider了,我把完整的实现步骤和细节给你拆解清楚:
实现AppA与AppB的图片资源共享(基于StreamProvider)
先补全AppA里StreamProvider的完整Manifest配置
你给出的配置还没写完,先把Manifest里的Provider配置补完整,尤其是用来指定共享路径的meta-data部分:
<provider android:authorities="org.example.AssetProvider" android:name="com.commonsware.cwac.provider.StreamProvider" android:exported="true" android:grantUriPermissions="true"> <!-- 关联路径配置文件,告诉Provider哪些资源可以共享 --> <meta-data android:name="com.commonsware.cwac.provider.STREAM_PROVIDER_PATHS" android:resource="@xml/stream_provider_paths" /> </provider>
然后创建路径配置文件
在AppA的res/xml目录下新建一个stream_provider_paths.xml文件,用来定义你要开放的资源目录。比如你想共享assets文件夹下的images子目录,内容可以这么写:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- assets/images下的所有资源都允许被访问,"shared_images"是路径别名,隐藏真实路径更安全 --> <asset path="images/" name="shared_images" /> <!-- 如果是共享内部存储的图片,就用<files-path>,比如: <files-path path="images/" name="local_images" /> --> </paths>
给你解释下关键配置的作用
android:authorities:这是你的Provider唯一标识,AppB访问时必须用这个值构建Uri,一定要用唯一的名字,比如加自己的包名前缀,避免和其他应用冲突。android:exported="true":允许其他应用访问这个Provider,必须设为true才能让AppB拿到资源。android:grantUriPermissions="true":支持临时授权,你可以只给AppB访问某一张图片的权限,而不是开放整个目录,安全性更高。
接下来是AppB如何访问AppA的资源
我给你两种方式,推荐用第一种更安全的:
方式1:通过Intent临时授权访问(推荐)
AppA可以在启动AppB的页面时,把授权后的图片Uri传过去。比如在AppA的某个按钮点击事件里:
// 构建要共享的图片Uri,格式是content://[authorities]/[别名]/[文件名] val targetImageUri = Uri.parse("content://org.example.AssetProvider/shared_images/photo1.jpg") // 启动AppB的图片查看页面 val intent = Intent().apply { // 指定AppB的目标Activity组件 component = ComponentName("com.example.appb", "com.example.appb.ImageViewerActivity") action = Intent.ACTION_VIEW setDataAndType(targetImageUri, "image/jpeg") // 给AppB临时授权,让它能读取这个Uri对应的资源 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } startActivity(intent)
然后在AppB的ImageViewerActivity里,就可以拿到Uri并读取图片了:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_image_viewer) val imageUri = intent.data ?: return // 用ContentResolver打开输入流,读取图片 contentResolver.openInputStream(imageUri)?.use { inputStream -> val bitmap = BitmapFactory.decodeStream(inputStream) imageView.setImageBitmap(bitmap) } }
方式2:直接构建Uri访问(不推荐,风险高)
如果不需要临时授权,也可以直接在AppB里构建Uri访问,但这种方式相当于把整个共享目录开放给所有知道authorities和路径的应用,安全性差:
val imageUri = Uri.parse("content://org.example.AssetProvider/shared_images/photo1.jpg") contentResolver.openInputStream(imageUri)?.use { inputStream -> // 这里处理图片流,比如显示到ImageView }
最后提几个注意事项
- 别忘了在AppA的Module级
build.gradle里添加StreamProvider的依赖:
版本号可以根据最新的稳定版调整哈。implementation 'com.commonsware.cwac:provider:0.6.3' - 如果共享的是外部存储的图片,Android 10以下需要动态申请
READ_EXTERNAL_STORAGE权限,Android 10及以上用Scoped Storage,StreamProvider会帮你处理大部分兼容问题。 - 测试的时候要确保AppA和AppB都装在同一设备上,而且AppA的assets/images目录下确实有你要共享的图片哦。
内容的提问来源于stack exchange,提问作者bubakovsky
相关产品推荐
相关产品推荐

