最近作者又碰到因为android 7.0 引起的兼容问题了。

在7.0以前的版本:
//创建临时图片
File photoOutputFile = SDPath.getFile("temp.jpg", SDPath.PHOTO_FILE_STR);
Uri photoOutputUri = Uri.fromFile(photoOutputFile);

这个file文件直接非常简单的转换成"file://XXX/XXX/XXX"的uri格式

7.0后的版本:

当把targetSdkVersion指定成24及之上并且在API>=24的设备上运行时。这种方式则会出现FileUriExposedException异常

android.os.FileUriExposedException:         file:///XXX exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:)
at android.net.Uri.checkFileUriExposed(Uri.java:)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:)
at android.content.Intent.prepareToLeaveProcess(Intent.java:)
...
原因

Android不再允许在app中把file://Uri暴露给其他app,包括但不局限于通过Intent或ClipData 等方法。

原因在于使用file://Uri会有一些风险,比如:

  • 文件是私有的,接收file://Uri的app无法访问该文件。
  • 在Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。

因此,google提供了FileProvider,使用它可以生成content://Uri来替代file://Uri

解决方案

首先在AndroidManifest.xml中添加provider

  • android:authorities
    是用来标识provider的唯一标识,在同一部手机上一个"authority"串只能被一个app使用,冲突的话会导致app无法安装。
  • android:exported必须设置成false,后面异常会讲为什么
  • android:grantUriPermissions用来控制共享文件的访问权限,也可以在java代码中设置。
因此,google提供了FileProvider,使用它可以生成content://Uri来替代file://Uri。

解决方案
首先在AndroidManifest.xml中添加provider android:authorities
是用来标识provider的唯一标识,在同一部手机上一个"authority"串只能被一个app使用,冲突的话会导致app无法安装。
android:exported必须设置成false,后面异常会讲为什么
android:grantUriPermissions用来控制共享文件的访问权限,也可以在java代码中设置。
解决方案

首先在AndroidManifest.xml中添加provider

  • android:authorities
    是用来标识provider的唯一标识,在同一部手机上一个"authority"串只能被一个app使用,冲突的话会导致app无法安装。
  • android:exported必须设置成false,后面异常会讲为什么
  • android:grantUriPermissions用来控制共享文件的访问权限,也可以在java代码中设置。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.zhongjh.phone.ui"
··· <provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.zhongjh.phone.ui.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider> </manifest >

res/xml/provider_paths.xml
这是指定路径和转换规则
<paths>中可以定义以下子节点

子节点 对应路径 例子
files-path Context.getFilesDir()
cache-path Context.getCacheDir()
external-path Environment.getExternalStorageDirectory() /storage/emulated/0/
external-files-path Context.getExternalFilesDir(null)
external-cache-path Context.getExternalCacheDir()

加入我要替换的目录是
/storage/emulated/0/diary sdcard/photo/
那么配置应该写成

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="diary sdcard/photo"/>
</paths>

然后修改代码

//创建临时图片
File photoOutputFile = SDPath.getFile("temp.jpg", SDPath.PHOTO_FILE_STR);
//Uri photoOutputUri = Uri.fromFile(photoOutputFile);
Uri photoOutputUri = FileProvider.getUriForFile(
mContext,
mActivity.getPackageName() + ".fileprovider",
photoOutputFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoOutputUri);
我所碰到的异常处理
  • java.lang.SecurityException: Provider must not be exported
    解决方案:android:exported必须设置成false
  • Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
    解决方案:AndroidManifest.xml处的android:authorities必须跟mActivity.getPackageName() + ".fileprovider"一样

Android 7.0 因为file://引起的FileUriExposedException异常的更多相关文章

  1. Android 7.0 FileProvider 使用说明

    FileProvider FileProvider 这个组件在Android 22.0.0 (也就是 Android 5.0 ) 版本下加入进Android系统,该组件是ContentProvider ...

  2. android 7.0以上共享文件(解决调用系统照相和图片剪切出现的FileUriExposedException崩溃问题)

    在android7.0开始试共享“file://”URI 将会导致引发 FileUriExposedException. 如果应用需要与其他应用共享私有文件,则应该使用 FileProvider, F ...

  3. android 7.0拍照问题file:///storage/emulated/0/photo.jpeg exposed beyond app through ClipData.Item.getUri

    Android7.0调用相机时出现新的错误: android.os.FileUriExposedException: file:///storage/emulated/0/photo.jpeg exp ...

  4. Android 7.0 出现 ”FileUriExposedException“ 和 ”解析包出现错误“ 异常的解决办法

    问题1 :android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.xxx.xxx.xxx.rel ...

  5. Android 7.0系统代码调用安装apk时报错FileUriExposedException完美解决

    项目更新遇到问题   Android项目开发中经常遇到下载更新的需求,以前调用系统安装器执行安装操作代码如下: Intent intent = new Intent(); intent.setActi ...

  6. Android studio3.0打开Device File Explore(文件管理器)的方法(图文教程)

    Android studio3.0打开Device File Explore(文件管理器)的方法(图文教程) 看到网上AS3.0新增加的查看手机文件的新功能,全部都是转载的,没有几个人心细的把如何打开 ...

  7. 关于Android 7.0(API24)相机的问题汇总

    在开发Android项目的时候,我们会用到相机,有些时候只是开发一个普通的扫码,仅仅赋予一下 权限 就好了,但是有些时候是需要拍照和从相册中获取照片的.我们在Android 5.0以及5.0之前调用相 ...

  8. Android开发之深入理解Android 7.0系统权限更改相关文档

    http://www.cnblogs.com/dazhao/p/6547811.html 摘要: Android 6.0之后的版本增加了运行时权限,应用程序在执行每个需要系统权限的功能时,需要添加权限 ...

  9. Android 7.0 通过FileProvider共享文件

    一.概述 Android 7.0后,提供了很多新特性,其中最主要的是禁止了通过file://URI直接在文件操作共享文件(该操作会触发FileUriExposedException),而是通过cont ...

随机推荐

  1. EA生成实体类代码

    引言 在做机房个人版重构的时候,就听说了EA是一个强大的软件.仅仅只是知道的时候,已经画完了图,没有怎么用EA其它的功能,所以一直没有见识过罢了.如今到了机房合作了,想到EA一定要好好用,这样能省不少 ...

  2. Android之——监听手机开机事件

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47028535 本文中,主要通过监听开机广播来达到监听手机开机状态的操作.在Andr ...

  3. 云Hbase数据库在亿方云实践之路

    本文主要先介绍了亿方云,进而谈及了数据架构,着重分析了HBase实践等 2017云栖大会HBase专场,亿方云科技CTO 王成军带来HBase在亿方云客户端同步系统中的应用实践的演讲.本文主要先介绍了 ...

  4. Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content

    Content-Type https://tools.ietf.org/html/rfc7231#section-3.1.1.5 https://tools.ietf.org/html/rfc7231 ...

  5. HDU4185 Oil Skimming —— 最大匹配

    题目链接:https://vjudge.net/problem/HDU-4185 Oil Skimming Time Limit: 2000/1000 MS (Java/Others)    Memo ...

  6. 强大的DataGrid组件[7]_自定义DataGrid——Silverlight学习笔记[15]

    基本知识讲解 1)两种状态 DataGrid的单元格的状态有两类,即编辑状态和非编辑状态. 在实际开发中,如果一个单元格所在的列不设为只读的话(即要求可读写),那么这个单元格就存在这两种状态.按需要, ...

  7. 浅谈JAVA中如何利用socket进行网络编程(一)

    转自:http://developer.51cto.com/art/201106/268385.htm Socket是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以 ...

  8. 11_传智播客iOS视频教程_NS前缀和@符号

    NS前缀的有NSLog和NSString Cocoa就是用来开发带界面的应用程序. Foundation框架之中的类.函数绝大多数都是从NextStep来的.看到NS前缀就知道这个类是从哪里来的.是很 ...

  9. Spring注解详细

    1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spr ...

  10. HDU 4891 The Great Pan (题意题+模拟)

    题意:给定一个文章,问你有多少种读法,计算方法有两种,如果在$中,如果有多个空格就算n+1,如果是一个就算2的次方,如果在{}中, 那么就是把每个空格数乘起来. 析:直接模拟,每次计算一行,注意上一行 ...