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

Related articles: