原文首发于微信公众号:躬行之。

开发中常常须要将某个文件向另一个应用程序传递,如图片上传到另一个应用程序、文件在不同存储门路之间的复制粘贴等都须要共享文件,能够这样了解接管文件的利用是在向提供文件的利用发送申请。

从 Android 7.0 开始,Android 执行 StrictMode 策略,禁止在利用内部公开 file://URL,如果在 Android 7.0 以上的利用不应用 FileProvider ,则会抛出 FileUriExposedException 异样,Android 7.0 当前要在利用之间共享文件要应用 content://URL 授予 URL 长期拜访权限,即要应用 FileProvider 的形式来授予长期拜访权限,具备长期拜访权限的 URL 是平安的,这种长期的 URL 会主动过期,其中 FileProvider 提供的 getUriForFile() 用于生成文件的内容。

在所有状况下,从您的应用程序向另一个应用程序提供文件的惟一平安办法是向接管应用程序发送文件的内容URI,并授予该URI的长期拜访权限。具备长期URI拜访权限的内容URI是平安的,因为它们仅实用于接管URI的应用程序,并且它们会主动过期。 Android FileProvider组件提供getUriForFile()办法,用于生成文件的内容URI。

这里也会提到一个在 Android 7.0 及更高版本时经常出现的异样:FileUriExposedException,通过应用 FileProvider 就能够解决该异样,当然这也是 Android 零碎在安全性上不断完善的后果。

  1. 指定FileProvider
  2. 指定文件共享门路

指定FileProvider

在 AndroidManifest 文件中指定 Provider,参考如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.myapp">    <application        ...>                <!--android:authorities="${applicationId}.yourname"-->        <provider            android:name="android.support.v4.content.FileProvider"            <!--authorities属性指定要用于FileProvider生成的内容URI的URI权限,个别是applicationId.yourname"组成-->            android:authorities="com.example.myapp.fileprovider"            android:grantUriPermissions="true"            android:exported="false">            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"                android:resource="@xml/filepaths" />        </provider>        ...    </application></manifest>

指定文件共享门路

下面代码中在 meta-data 目录中指定了要共享的文件目录,文件目录在 filepathd.xml 中定义,可在相应的 xml 中定义的门路有以下几种,具体参考如下:

<?xml version="1.0" encoding="utf-8"?><resources xmlns:android="http://schemas.android.com/apk/res/android">    <paths>        <!--示意设施的根目录(new File("/"))-->        <root-path name="root" path="" />        <!--示意context.getFileDir()-->        <files-path name="files" path="" />        <!--示意context.getCacheDir()-->        <cache-path name="cache" path="" />        <!--示意Environment.getExternalStorageDirectory()-->        <external-path name="external" path="" />        <!--示意context.getExternalFilesDirs()-->        <external-files-path name="name" path="path" />        <!--示意getExternalCacheDirs()-->        <external-cache-path name="name" path="path" />    </paths></resources>

在 xml 中示意某个门路须要两个属性,path 示意以后指定目录的子目录,如果不指定则示意的是以后指定目录下的根目录及子目录,name 示意会将 name 增加的 URL 前面作为该文件的拜访门路,参考如下:

//示意以后要共享的文件会在 context.getFileDir() 目录下的 images 子目录下查找要共享的文件<paths>    <files-path path="images/" name="myImage" /></paths>//示意最终生成的共享的文件URLcontent://com.example.myapp.fileprovider/myImage/image.jpg

获取Uri

最初,配置实现之后,在所有须要应用文件相干的,在获取 Url 时应该依照如下形式获取,具体如下:

public Uri getUri(File file) {    Uri uri = null;    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {        uri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".youName", file);    } else {        uri = Uri.fromFile(file);    }    return uri;}

这样就能够在 Android 7.0 以上欢快的共享文件了,这个知识点也算是开发中常常会遇到到。