Android N 7.0 应用间共享文件(FileProvider)
来源:互联网 发布:网络剧老炮儿2 编辑:程序博客网 时间:2024/06/10 08:38
Android N 中共享文件
Android N 系统,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI。
如果一项包含文件 URI 的 Intent 离开您的应用,应用会停止运行,并出现 FileUriExposedException异常。
android.os.FileUriExposedException: file:///storage/emulated/0/Download/appName-2.3.0.apk exposed beyond app through Intent.getData()
若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限。
进行此授权的最简单方式是使用 FileProvider类。
如何共享文件,简单4步:
1、在AndroidManifest.xml中<application>标签下添加如下代码
<provider android:name="android.support.v4.content.FileProvider" android:authorities="自定义的权限名" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /></provider>
注意:
authorities:权限名称,可自己定义()
grantUriPermissions:必须是true,表示授予 URI 临时访问权限 ( readPermission, writePermission, and permission attributes)
exported:true: The provider is available to other applications. false: The provider is not available to other applications.
resource:自定义的xml文件(下面会介绍)
2、在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件(如下图)
3、打开file_paths.xml文件,添加指定的分享目录:
向paths 标签中添加需要的item,item有以下内容:
name:给这个访问路径起个名字
path:需要临时授权访问的路径(.代表所有路径)
path类型:
<files-path/>代表的根目录: Context.getFilesDir()
<external-path/>代表的根目录: Environment.getExternalStorageDirectory()
<cache-path/>代表的根目录: getCacheDir()
<?xml version="1.0" encoding="utf-8"?><paths xmlns:android="http://schemas.android.com/apk/res/android"> <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/DCIM/camerademo目录--> <external-path name="DCIM" path="DCIM/camerademo" /> <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/目录--> <external-path path="." name="external_storage_root" /> <!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/Pictures/camerademo目录--> <external-path name="Pictures" path="Pictures/camerademo" /> <!--代表app 私有的存储区域 Context.getFilesDir()目录下的images目录 /data/user/0/com.hm.camerademo/files/images--> <files-path name="private_files" path="images" /> <!--代表app 私有的存储区域 Context.getCacheDir()目录下的images目录 /data/user/0/com.hm.camerademo/cache/images--> <cache-path name="private_cache" path="images" /> <!--代表app 外部存储区域根目录下的文件 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)目录下的Pictures目录--> <!--/storage/emulated/0/Android/data/com.xx.xxxxxx/files/Pictures--> <external-files-path name="external_files" path="Pictures" /> <!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的images目录--> <!--/storage/emulated/0/Android/data/com.xx.xxxxxx/cache/images--> <external-cache-path name="external_cache" path="" /></paths>
4、修改代码适配Android N
Intent intent = new Intent(Intent.ACTION_VIEW);//判断是否是AndroidN以及更高的版本if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { /* 这句要记得写:这是申请权限,之前因为没有添加这个,打开裁剪页面时,一直提示“无法修改低于50*50像素的图片”,开始还以为是图片的问题呢,结果发现是因为没有添加FLAG_GRANT_READ_URI_PERMISSION。 如果关联了源码,点开FileProvider的getUriForFile()看看,注释就写着需要添加权限。 */ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); /*getUriForFile(Context context, String authority, File file):此处的authority需要和manifest里面保持一致。以前直接用 Uri.fromFile(apkFile)构建出一个Uri,现在我们使用FileProvider.getUriForFile(); */ Uri contentUri = FileProvider.getUriForFile(context, 自定义的权限名, imageFile); intent.setDataAndType(contentUri, "application/vnd.android.package-archive");} else { intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);}startActivity(intent);
下面FileProvider的getUriForFile()方法的注释:
/** * Return a content URI for a given {@link File}. Specific temporary * permissions for the content URI can be set with * {@link Context#grantUriPermission(String, Uri, int)}, or added * to an {@link Intent} by calling {@link Intent#setData(Uri) setData()} and then * {@link Intent#setFlags(int) setFlags()}; in both cases, the applicable flags are * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. A FileProvider can only return a * <code>content</code> {@link Uri} for file paths defined in their <code><paths></code> * meta-data element. See the Class Overview for more information. * * @param context A {@link Context} for the current component. * @param authority The authority of a {@link FileProvider} defined in a * {@code <provider>} element in your app's manifest. * @param file A {@link File} pointing to the filename for which you want a * <code>content</code> {@link Uri}. * @return A content URI for the file. * @throws IllegalArgumentException When the given {@link File} is outside * the paths supported by the provider. */ public static Uri getUriForFile(Context context, String authority, File file) { final PathStrategy strategy = getPathStrategy(context, authority); return strategy.getUriForFile(file); }
错误分析
报错
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/DCIM/camerademo/20170226_110056248725175.jpg
分析
在生成Uri 的时候,指定的文件所在的路径没有包含在path所指定的路径中
参考:
https://developer.android.com/guide/topics/manifest/provider-element.html
Android7.0须知–应用间共享文件(FileProvider)
解决 Android N 7.0 上 报错:android.os.FileUriExposedException
FileProvider无法获取外置SD卡问题解决方案 | Failed to find configured root that contains
FileProvider 的使用(Failed to find configured root that contains/storage/emulated/0/DCIM/ )
- Android N 7.0 应用间共享文件(FileProvider)
- android 7.0应用间共享文件----FileProvider
- Android 应用间共享文件(FileProvider)
- Android 7.0 通过FileProvider实现应用间文件共享
- Android 7.0 适配-应用之间共享文件(FileProvider)
- Android 7.0 应用间文件访问方法(FileProvider)
- Android7.0须知--应用间共享文件(FileProvider)
- Android7.0须知--应用间共享文件(FileProvider)
- Android7.0须知--应用间共享文件(FileProvider)
- Android7.0 应用间共享文件 FileProvider
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android 7.0 行为变更 通过FileProvider在应用间共享文件
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
- Android实践 -- 使用FileProvider安全的共享文件 应用篇
- 用json方法使宽高同时变.html
- vue.js 部署中碰到的图片路径问题
- 两个10G的文件中,求含有相同整数
- Linux上安装pyTorch
- 【Leetcode-Medium-647】Palindromic Substrings
- Android N 7.0 应用间共享文件(FileProvider)
- 独立任务最优调度(双机调度)问题
- 洛谷 1083||NOIP 2012 借教室 二分答案+差分 解题报告
- NOIP 2017.10.20 总结+心得
- urlencode/base64/sha1/md5学习
- Hololens之固定语音命令总结
- win10配置TensorFlow GPU出现Failed to load the native TensorFlow runtime."
- 【Deep Learning】BP网络手写识别
- 简析String --StringBuffer--StirngBuilder