问题描述
我正在寻找一种使用 Android 支持库的 FileProvider.
I'm looking for a way to correctly share (not OPEN) an internal file with external application using Android Support library's FileProvider.
按照文档中的示例,
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.supportv4.my_files"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_paths" />
</provider>
并使用 ShareCompat 将文件共享给其他应用程序,如下所示:
and using ShareCompat to share a file to other apps as follows:
ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
不起作用,因为 FLAG_GRANT_READ_URI_PERMISSION 只授予在意图的 data
上指定的 Uri 的权限,而不是 EXTRA_STREAM
额外的值(由setStream
).
does not work, since the FLAG_GRANT_READ_URI_PERMISSION only grants permission for the Uri specified on the data
of the intent, not the value of the EXTRA_STREAM
extra (as was set by setStream
).
我试图通过将提供程序的 android:exported
设置为 true
来破坏安全性,但是 FileProvider
在内部检查自身是否被导出,当所以,它抛出一个异常.
I tried to compromise security by setting android:exported
to true
for the provider, but FileProvider
internally checks if itself is exported, when so, it throws an exception.
推荐答案
使用支持库中的 FileProvider
,您必须手动授予和撤销其他应用程序读取特定 Uri 的权限(在运行时).使用 Context.grantUriPermission 和 Context.revokeUriPermission 方法.
Using FileProvider
from support library you have to manually grant and revoke permissions(at runtime) for other apps to read specific Uri. Use Context.grantUriPermission and Context.revokeUriPermission methods.
例如:
//grant permision for app with package "packegeName", eg. before starting other app via intent
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
//revoke permisions
context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
作为最后的手段,如果您不能提供包名称,您可以向所有可以处理特定意图的应用授予权限:
As a last resort, if you can't provide package name you can grant the permission to all apps that can handle specific intent:
//grant permisions for all apps that can handle given intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
...
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
根据文档的替代方法:
- 通过调用 setData() 将内容 URI 放入 Intent.
- 接下来,使用 FLAG_GRANT_READ_URI_PERMISSION 或 FLAG_GRANT_WRITE_URI_PERMISSION 调用方法 Intent.setFlags()或两者.
最后,将 Intent 发送到另一个应用程序.大多数情况下,您可以通过调用 setResult() 来完成此操作.
Intent 中授予的权限在堆栈期间保持有效接收 Activity 处于活动状态.当堆栈完成时,
权限被自动删除.授予一个权限
客户端应用程序中的 Activity 会自动扩展到其他应用程序
该应用的组件.
顺便说一句.如果需要,您可以复制FileProvider的来源 并更改 attachInfo
方法以防止提供程序检查它是否已导出.
Btw. if you need to, you can copy source of FileProvider and change attachInfo
method to prevent provider from checking if it is exported.
这篇关于如何使用支持 FileProvider 将内容共享给其他应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!