使用 android.support.v4.content.FileProvider 在 Android 中共享文件

当我们在 Android 应用程序中需要共享文件给其他应用程序使用时,我们通常使用 Intent 机制来实现。Intent 是 Android 平台提供的一种组件之间进行通信的机制,它可以用于启动一个 Activity、启动服务、发送广播以及共享数据。在共享文件时,我们可以使用 Intent.createChooser() 方法创建一个选择器,让用户选择需要使用的应用程序。

然而,当我们的应用程序升级到 Android 7.0 (API level 24) 或更高版本时,这种方式可能会导致出现 FileUriExposedException 异常。这是因为 Android 7.0 引入了一项新的安全机制,禁止我们使用 file:// URI 共享文件。

为了解决这个问题,Android 提供了一个名为 FileProvider 的类,它可以帮助我们在应用程序之间共享文件,并且能够正确处理 Android 7.0 及以上版本的限制。

使用 FileProvider 共享文件

首先,我们需要在 AndroidManifest.xml 文件中声明 FileProvider。在 <application> 标签内添加以下代码:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.myapp.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

这个代码片段中,我们在 <provider> 标签内定义了一个 FileProvider。android:name 属性指定了 FileProvider 的类名,这里我们使用了 android.support.v4.content.FileProviderandroid:authorities 属性指定了 FileProvider 的授权标识,这个标识在后面会用到。android:exported 属性设置为 false,表示这个 FileProvider 不允许外部应用程序使用。android:grantUriPermissions 属性设置为 true,表示我们希望授予 URI 权限,以便其他应用程序可以访问我们共享的文件。

<provider> 标签内部,我们使用 <meta-data> 标签来指定 FileProvider 的配置文件。在这个例子中,我们把配置文件命名为 file_paths.xml,并将其放在 res/xml 目录下。我们将在下一节中创建这个配置文件。

创建 FileProvider 配置文件

res/xml 目录下,创建一个名为 file_paths.xml 的文件,并添加以下代码:

<paths xmlns:android="
    <external-path name="external_files" path="."/>
</paths>

这个配置文件指定了共享文件的路径。在这个例子中,我们使用 <external-path> 元素来共享应用程序的外部文件目录。name 属性为 external_files,表示我们给共享的目录起了一个名字,可以根据需要自定义。path 属性为 .,表示共享整个外部文件目录。

如果需要共享其他目录下的文件,你可以在 <paths> 标签内添加其他的 <external-path><files-path><cache-path><external-cache-path> 元素。

生成文件 URI

要共享文件给其他应用程序,我们首先需要获取文件的 URI。我们可以使用 FileProvider.getUriForFile() 方法来生成文件的 URI。以下是一个示例代码:

File file = new File(getFilesDir(), "example.txt");
Uri fileUri = FileProvider.getUriForFile(this, "com.example.myapp.fileprovider", file);

在这个例子中,我们创建了一个名为 example.txt 的文件,并通过 FileProvider.getUriForFile() 方法获得了该文件的 URI。this 参数表示当前的上下文,"com.example.myapp.fileprovider" 是我们在 AndroidManifest.xml 中定义的 FileProvider 的授权标识。

启动其他应用程序

我们可以使用 Intent 来启动其他应用程序并共享文件。以下是一个示例代码:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(intent, "Share File"));

在这个例子中,