头图
The original text was first published on the WeChat public account: Practically.

During development, it is often necessary to transfer a certain file to another application, such as uploading pictures to another application, copying and pasting files between different storage paths, etc. All need to share files. It can be understood that the application receiving the file is sending The application providing the file sends the request.

Starting from Android 7.0, Android implements the StrictMode strategy to prohibit the disclosure of file://URL outside of the application. If the application above Android 7.0 does not use FileProvider, FileUriExposedException will be thrown. After Android 7.0, it is necessary to share files between applications. Use content://URL to grant URL temporary access permissions, that is, use FileProvider to grant temporary access permissions. URLs with temporary access permissions are safe. Such temporary URLs will automatically expire. The getUriForFile() provided by FileProvider Used to generate the content of the file.

In all cases, the only safe way to provide a file from your application to another application is to send the content URI of the file to the receiving application and grant temporary access to that URI. Content URIs with temporary URI access are safe because they are only available for the application that receives the URI, and they will automatically expire. The Android FileProvider component provides the getUriForFile() method to generate the content URI of the file.

There is also an exception that often occurs in Android 7.0 and higher versions: FileUriExposedException, which can be solved by using FileProvider. Of course, this is also the result of the continuous improvement of the Android system in security.

  1. Specify FileProvider
  2. Specify file sharing path

Specify FileProvider

Specify the Provider in the AndroidManifest file, refer to the following:

<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>

Specify file sharing path

In the above code, the file directory to be shared is specified in the meta-data directory. The file directory is defined in filepathd.xml. There are the following paths that can be defined in the corresponding xml. The specific reference is as follows:

<?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>

In xml, a path requires two attributes. Path represents the subdirectory of the currently specified directory. If not specified, it represents the root directory and subdirectory of the currently specified directory. Name indicates that the URL appended by name will be used as the The access path of the file is as follows:

//表示当前要共享的文件会在 context.getFileDir() 目录下的 images 子目录下查找要共享的文件
<paths>
    <files-path path="images/" name="myImage" />
</paths>

//表示最终生成的共享的文件URL
content://com.example.myapp.fileprovider/myImage/image.jpg

Get Uri

Finally, after the configuration is completed, all the files related to the need to be used should be obtained as follows when obtaining the Url, as follows:

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;
}

In this way, you can share files happily on Android 7.0 and above. This knowledge point is often encountered in development.

1.png


躬行之
18 声望5 粉丝