关于Android7.0的FileUriExposedException异常解决方法

我在学习网络存储时,遇到的一个异常
FileUriExposedException异常
翻看Google的异常文档:
https://developer.android.google.cn/reference/android/os/FileUriExposedException.html
在7.0及以后开始
应用程序向另一个应用程序公开时引发的异常。file://Uri
由于接收应用程序可能无法访问共享路径, 因此不鼓励此风险敞口。例如, 接收应用程序可能没有请求运行时权限, 或者平台可以共享跨用户配置文件边界。READ_EXTERNAL_STORAGEUri
相反, 应用程序应该使用 uri, 这样平台就可以扩展接收应用程序的临时权限来访问资源。content://
这仅用于针对目标或更高的应用程序。以早期 SDK 版本为目标的应用程序可以共享, 但强烈劝阻。Nfile://Uri
另请参见:
FileProvider
FLAG_GRANT_READ_URI_PERMISSION
使用FileProvider可以解决这个异常:
FileProvider官方文档:
https://developer.android.google.cn/reference/android/support/v4/content/FileProvider.html
1>:在配置文件中声明FileProvider
<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mydomain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">            
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
            ...
        </provider>
        ...
    </application>
</manifest>

android:name 是固定写法
android:authorities 可自定义,是用来标识该provider的唯一标识,建议结合包名来保证authority的唯一性
android:exported 必须设置成 false,否则运行时会报错java.lang.SecurityException: Provider must not be exported 
android:grantUriPermissions 用来控制共享文件的访问权限

<meta-data>节点中的android:resource指定了共享文件的路径。此处的file_paths即是该Provider对外提供文件的目录的配置文件,存放在res/xml/下

2>配置共享路径
我们在 res/xml/ 的目录下创建 file_paths.xml 文件
<paths>  
    <files-path name="name" path="path"/>  
    ...  
</paths> 
其中根元素<paths>是固定的,内部元素可以是以下节点:
<files-path name="name" path="path" /> 对应getFilesDir()。
<cache-path name="name" path="path" /> 对应getCacheDir()。
<external-path name="name" path="path" /> 对应Environment.getExternalStorageDirectory()。
<external-files-path name="name" path="path" /> 对应getExternalFilesDir()。
<external-cache-path name="name" path="path" /> 对应getExternalCacheDir()。
举个栗子:
我将服务器下载的APK文件存储在 sdcard中的Android/data/<package>/files/Download/下
则 xml 的配置是:
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path path="Download" name="files_path" />
</paths>
3>在代码中调用:
  private void installAPK(Context context, File file) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri data;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            data = FileProvider.getUriForFile(context, "com.project.pulis.fileprovider",file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            data = Uri.fromFile(file);
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive");
        startActivity(intent);
    }
}


猜你喜欢

转载自blog.csdn.net/pulis_sl/article/details/79871516