问题
在SDK升级到Android N,通过Uri.fromFile(file)获取Uri报 android.os.FileUriExposedException异常,因为在Android 7.0系统上,Android框架强制执行了StrictMode API政策禁止向应用外公开file:// URI, 如果Intent包含了file://类型的URI离开应用,抛出异常,退出程序。
解决办法
使用FileProvider获取URI。
第一步:清单文件注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
${applicationId }:你的应用包名
exported="false":设置成false就好了,true会抛异常
grantUripermissions="true":表示授予访问URI权限
resources="@xml/filepaths":指定共享目录的配置文件
第二步:创建共享目录配置文件:filepaths.xml(第一步中指定的resource文件)
<!--FileProvider提供的共享目录配置文件-->
<paths>
<!--内置SD卡 Environment.getExternalStorageDirectory() .表示共享所有的目录,也可以指定共享的目录-->
<external-path
name="external-path"
path="."/>
<!--内置SD卡 Context.getExternalCacheDir() .表示共享所有的目录,也可以指定共享的目录-->
<external-cache-path
name="external-cache-path"
path="."/>
<!--内置SD卡 Context.getExternalFilesDir(null) .表示共享所有的目录,也可以指定共享的目录-->
<external-files-path
name="external-files-path"
path="."/>
<!--data目录下 Context.getFilesDir() .表示共享所有的目录,也可以指定共享的目录-->
<files-path
name="files_path"
path="."/>
<!--data缓存目录 Context.getCacheDir() .表示共享所有的目录,也可以指定共享的目录-->
<cache-path
name="cache-path"
path="."/>
<!--这个标签Android官方文档中是没有提及,Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录-->
<root-path
name="name"
path="."/>
</paths>
通过这写目录配置,基本覆盖了手机中所有目录的权限, 外置SD卡对应共享目录的权限需要配置自定义的root-path中。
第三步:通过FileProvider.getUriForFile(context,authorities,file)获取URI
/**
* 根据文件转换成对应的Uri
*
* @param ctx
* @param file
* @return
*/
public static Uri file2Uri(Context ctx, File file) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return FileProvider.getUriForFile(ctx, BuildConfig.APPLICATION_ID + ".fileprovider", file);
} else {
return Uri.fromFile(file);
}
}
BuildConfig.APPLICATION_ID:应用包名
file:需要转换成URI的文件,这里file路径必须在filepaths.xml中配置path,否则,报 java.lang.IllegalArgumentException: Failed to find configured root异常。
总结
主要是通过设置配置文件来控制共享目录, 主要涉及URI适配的功能:拍照,裁剪,安装应用等等。