首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用support FileProvider将内容分享给其他应用程序?

如何使用support FileProvider将内容分享给其他应用程序?
EN

Stack Overflow用户
提问于 2013-08-15 16:34:47
回答 6查看 159.5K关注 0票数 161

我正在寻找一种方法,以正确共享(而不是打开)内部文件与外部应用程序使用安卓支持库的FileProvider

按照文档上的示例,

代码语言:javascript
复制
<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将文件共享到其他应用程序,如下所示:

代码语言:javascript
复制
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 extra的值(由setStream设置)。

我试图通过将提供程序的android:exported设置为true来折衷安全性,但FileProvider在内部检查自身是否已导出,如果是,它将抛出异常。

EN

回答 6

Stack Overflow用户

发布于 2015-10-05 21:54:31

这个解决方案适用于我从OS4.4开始的版本。为了让它在所有设备上都能工作,我为旧设备添加了一个变通方法。这确保始终使用最安全的解决方案。

Manifest.xml:

代码语言:javascript
复制
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.package.name.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>

file_paths.xml:

代码语言:javascript
复制
<paths>
    <files-path name="app_directory" path="directory/"/>
</paths>

Java:

代码语言:javascript
复制
public static void sendFile(Context context) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    String dirpath = context.getFilesDir() + File.separator + "directory";
    File file = new File(dirpath + File.separator + "file.txt");
    Uri uri = FileProvider.getUriForFile(context, "com.package.name.fileprovider", file);
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    // Workaround for Android bug.
    // grantUriPermission also needed for KITKAT,
    // see https://code.google.com/p/android/issues/detail?id=76683
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, attachmentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }
    if (intent.resolveActivity(context.getPackageManager()) != null) {
        context.startActivity(intent);
    }
}

public static void revokeFileReadPermission(Context context) {
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
        String dirpath = context.getFilesDir() + File.separator + "directory";
        File file = new File(dirpath + File.separator + "file.txt");
        Uri uri = FileProvider.getUriForFile(context, "com.package.name.fileprovider", file);
        context.revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
}

在片段或活动的onResume和onDestroy()方法中使用revokeFileReadPermission()撤消权限。

票数 24
EN

Stack Overflow用户

发布于 2013-09-03 12:01:10

正如Phil在他对原始问题的评论中所说的那样,这是独一无二的,在google中没有其他信息,我想我也应该分享我的结果:

在我的应用程序中,FileProvider开箱即用来使用共享意图来共享文件。除了设置FileProvider之外,不需要任何特殊的配置或代码。在我的manifest.xml中,我放置了:

代码语言:javascript
复制
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.my.apps.package.files"
        android:exported="false"
        android:grantUriPermissions="true" >
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/my_paths" />
    </provider>

在my_paths.xml中,我有:

代码语言:javascript
复制
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="files" path="." />
</paths>

在我的代码中,我有:

代码语言:javascript
复制
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("application/xml");

    Uri uri = FileProvider.getUriForFile(this, "com.my.apps.package.files", fileToShare);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);

    startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.share_file)));

而且,我可以毫不费力地将存储在我的应用程序私有存储中的文件与Gmail和google drive等应用程序共享。

票数 16
EN

Stack Overflow用户

发布于 2014-01-20 06:37:09

据我所知,这只能在较新版本的Android上运行,所以你可能不得不想出一种不同的方法来实现它。这个解决方案适用于我的4.4版本,但不适用于4.0或2.3.3版本,所以对于一个本应在任何Android设备上运行的应用程序来说,这不是一个有用的分享内容的方式。

在manifest.xml中:

代码语言:javascript
复制
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.mydomain.myapp.SharingActivity"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

请仔细注意您如何指定权限。您必须指定您将从中创建URI并启动共享意图的活动,在本例中,该活动称为SharingActivity。这一要求在谷歌的文档中并不明显!

file_paths.xml:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="just_a_name" path=""/>
</paths>

请注意指定路径的方式。以上内容默认为私有内部存储的根目录。

在SharingActivity.java中:

代码语言:javascript
复制
Uri contentUri = FileProvider.getUriForFile(getActivity(),
"com.mydomain.myapp.SharingActivity", myFile);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share with"));

在本例中,我们共享了一张JPEG图像。

最后,最好确保您已经正确地保存了该文件,并且可以使用以下内容访问它:

代码语言:javascript
复制
File myFile = getActivity().getFileStreamPath("mySavedImage.jpeg");
if(myFile != null){
    Log.d(TAG, "File found, file description: "+myFile.toString());
}else{
    Log.w(TAG, "File not found!");
}
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18249007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档