本文介绍了如何使用支持 FileProvider 将内容共享给其他应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种使用 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.grantUriPermissionContext.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 将内容共享给其他应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-18 22:48