Original address: https://blog.csdn.net/soslinken/article/details/70145354
FileProvider
The FileProvider component was added to the Android system under the Android 22.0.0 (that is, Android 5.0) version. This component is a subclass of ContentProvider, and its function is to provide the ability to access files across processes. Don't think that it was only added to Android 7.0.
Why Android 7.0 file sharing uses FileProvider
The reason for this is that, after Android 7.0, the review of StrictMode has been stricter. Just like the exception of NetWorkOnMainThread added after Android 3.0, Google will use strict mode for the parts that cause experience or security problems to the Android system. Limit program developers.
For file access before Android 7.0, you can use file://uri to access, but there is a problem in this place, that is, even if it is not a file generated by your own application, you can call it as long as you know the uri of the other party. risk arises. Therefore, after Android 7.0, the restriction on cross-process access to files has been added. This restriction will cause an exception of android.os.FileUriExposedException if you use file://uri to access.
FileProvider use
Step 1 AndroidManifest, register FileProvider
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.unreal.update"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/update_files" />
</provider>
...
</application>
</manifest>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
The point to pay attention to is the
android:authorities parameter, like ContentProvider, you need to provide a uri authority here, so that content://android:authorities/uri can be accessed, android:authorities can be freely defined
Step 2 Create an xml folder under res, and create update_files.xml under the xml folder
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<files-path path="files" name="files" />
<cache-path path="files" name="cache" />
<external-path path="files" name="external" />
<external-files-path path="files" name="externalfiles"/>
<!-- 此标签需要 support 25.0.0以上才可以使用-->
<external-cache-path path="files" name="externalcache"/>
</paths>
</resources>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
name: name flag string, cannot have the same name!
path: Folder "relative path", the full path depends on the current label type.
Label | path |
---|---|
…….. | * represents the current folder and its subfolders |
file-path | The physical path is Context.getFilesDir() + /files/* |
cache-path | The physical path is Context.getCacheDir() + /files/* |
external-path | The physical path is Environment.getExternalStorageDirectory() + /files/* |
external-files-path | The physical path is Context.getExternalFilesDir(String) + /files/* |
external-cache-path | The physical path is Context.getExternalCacheDir() + /files/* |
After seeing the article about FileProvider by zhuhf in Jianshu, I found that there is a hidden label
Article address: http://www.jianshu.com/p/55eae30d133c
<root-path name="name" path="path" />
- 1
Label | path |
---|---|
…….. | * represents the current folder and its subfolders |
root-path | Physical path is equivalent to /path/* |
Step 3 Get the uri through getUriForFile
data = FileProvider.getUriForFile(context,"之前在AndroidManifest中配置的android:authorities", "7.0后文件的路径");
// 给目标应用一个临时授权
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- 1
- 2
- 3
- 4
FLAG_GRANT_READ_URI_PERMISSION: Indicates read permission;
FLAG_GRANT_WRITE_URI_PERMISSION: Indicates write permission;
according to your needs, choose whether to read or write
Example Install APK
private void installApk(File apk) {
if (!apk.exists()) {
return;
}
Uri data;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// UpdateConfig.FILE_PROVIDER_AUTH 即是在清单文件中配置的authorities
data = FileProvider.getUriForFile(context, UpdateConfig.FILE_PROVIDER_AUTH, apk);
// 给目标应用一个临时授权
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
data = Uri.fromFile(apk);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
}