Method of Android 7.0 Behavior Change Adapting File Provider
- 2021-09-05 00:44:22
- OfStack
Two small explanations:
FileProvider is a special subclass of ContentProvider, and ContentProvider replaces file://Uri by creating content://Uri.
On systems above Android 7.0, attempting to pass file://URI may trigger FileUriExposedException
This overview of FileProvider includes the following topics:
1. Define FileProvider
2. Specify available files
3. Content URI for retrieving files
4. Temporary permissions granted to URI
5. Provision of content URI to other applications
Step 1: Define FileProvider:
// In the manifest file
<provider
android:name="android.support.v4.content.FileProvider"// Fixed
android:authorities="${applicationId}.yourname"// Depending on the domain you control, set the property to URI Authority
android:exported="false"//FileProvider Do not need to be made public
android:grantUriPermissions="true">// Allows you to grant temporary access to files
...
</provider>
Step 2: Specify available files
// New 1 A xml Files are used to store directory files that applications need to share
// The following paths Element tells FileProvider Do you intend to work for images/ Subdirectory request content of private file area URI
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
...
</paths>
The element must contain one or more of the following child elements:
// Represents the internal storage space in the private directory of the application files/ Directory, equivalent to Context.getFilesDir() The directory path obtained;
<files-path name = " name " path = " path " />
// Represents the internal storage space in the private directory of the application cache/ Directory, equivalent to Context.getCacheDir() The directory path obtained;
<cache-path name = " name " path = " path " />
// Represents the root directory of external storage space, which is equivalent to Environment.getExternalStorageDirectory() The directory path obtained;
<external-path name = " name " path = " path " />
// Represents the external storage space in the private directory of the application files/ Directory, equivalent to Context.getExternalFilesDir(null) The directory path obtained;
<external-files-path name = " name " path = " path " />
// Represents the external storage space in the private directory of the application cache/ Directory, equivalent to Context.getExternalCacheDir() ;
<external-cache-path name = " name " path = " path " />
// Represents files in the root directory of the external media area. Equivalent to Context.getExternalMediaDirs() .
<external-media-path name = " name " path = " path " />
These child elements all use two identical attributes:
name="name"
1 URI path segment. Used to alias the subdirectory name specified by the path property by 1. For security purposes, this value hides the name of the subdirectory you want to share. The subdirectory name of this value is contained in the path attribute.
path="path"
The subdirectory you are sharing. Although the name attribute is an URI path segment, the path value is the actual subdirectory name. Note that this value refers to 1 subdirectory, not a separate file name. You cannot share individual files by filename or specify a subset of files using wildcard characters.
Step 3: Retrieve the file's Content URI
// Use FileProvider Public static methods provided by the class getUriForFile Generate Content URI
// No. 1 1 Parameters :context Context
// No. 1 2 Parameters : Manifest Register in file FileProvider Set when the authorities Attribute value
// No. 1 3 Parameters : The file to share, and this file 1 Position at the first 2 Step by step, we are path Inside the subdirectory added in the file
Uri contentUri = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".myprovider", myFile);
Step 4: Grant temporary permissions to URI
There are two ways to authorize:
Mode 1:
// Invoke method :
// Parameter 1: Authorized access URI Other application package names of objects
// Parameter 2: Authorized access Uri Object
// Parameter 3: Authorization type FLAG_GRANT_READ_URI_PERMISSION Or FLAG_GRANT_WRITE_URI_PERMISSION
( Or 2 Authorized at the same time. In this form of authorization, the validity period of permission expires until the device is restarted or manually called revokeUriPermission() Method to revoke authorization )
grantUriPermission(package, Uri, mode_flags)
The second way:
// Cooperate intent Use
// Permissions expire until the stack where other applications are destroyed, and 1 Authorize sth 1 After 10 components, other components of the application have the same access rights.
Intent.setFlags() Or Intent.addFlags()
Intent.setData(Uri uri);
Step 5: Provide the content URI to other applications
// Start other applications and pass authorized Content URI Data. Of course, there are other ways to provide services.
startActivity()
Or
startActivityResult()
Or
setResult()
Official text (need to bring your own ladder, click here for your own tutorial): Google Develpers-FileProvider
Here is an example from my side:
Scenario: Open the new version apk file for automatic installation when the version update is completed
// In res/xml New under Directory 1 A filepath Documents And specify subdirectory path information
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_path" path="."/>
<cache-path name="cache_path" path="."/>
</paths>
// New 1 A xml Files are used to store directory files that applications need to share
// The following paths Element tells FileProvider Do you intend to work for images/ Subdirectory request content of private file area URI
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
...
</paths>
0
// New 1 A xml Files are used to store directory files that applications need to share
// The following paths Element tells FileProvider Do you intend to work for images/ Subdirectory request content of private file area URI
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
...
</paths>
1