Android 7.0 开始执行的 StrictMode API 政策禁止在应用外部公开 file:// URI
,应用间共享文件必须使用FileProvider
,使用content://uri
替代file://uri
使用
- 声明FIleProvider
- 编写
file_paths.xml
文件指定可分享的文件路径 - 使用FileProvider
声明FIleProvider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.shuxun.bom.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
编写file_paths.xml文件
因为要使用content://uri
替代file://uri
,那么,content://
的 uri 如何定义呢?总不能使用文件路径吧?所以,需要一个虚拟的路径对文件路径进行映射,所以需要编写个xml文件,通过path
以及xml节点
确定可访问的目录,通过name
属性来映射真实的文件路径。
<paths>
<root-path name="root" path="" />
<files-path name="name" path="path" />
<cache-path name="name" path="path" />
<external-path name="external_storage_root" path="." />
<external-files-path name="name" path="path" />
<external-cache-path name="name" path="path" />
</paths>
每个节点都支持两个属性:
- path 需要临时授权访问的路径(.代表所有路径)
- name 虚拟的路径,用来映射真实的文件路径
子节点 | 含义 |
---|---|
root-path | Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录 |
external-path | 代表外部存储区域的根目录下的文件,Environment.getExternalStorageDirectory()
|
external-files-path | 代表 context.getExternalFilesDirs() |
external-cache-path | 代表 getExternalCacheDirs() |
files-path | 代表 context.getFileDir() |
cache-path | 代表 context.getCacheDir() |
使用FileProvider
val install = Intent(Intent.ACTION_VIEW)
val apkFile = File(BosApplication.context?.cacheDir, "/$apkPath")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
install.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
val uriForFile = FileProvider.getUriForFile(this, "com.shuxun.bom.fileprovider", apkFile)
install.setDataAndType(uriForFile, "application/vnd.android.package-archive") }
else {
install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
}
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(install)