前言

Android 7.0强制启用了被称作StrictMode的策略,带来的影响就是你的App对外无法暴露file://类型的URI了。

如果你使用Intent携带这样的URI去打开外部App(比如:打开系统相机拍照),那么会抛出FileUriException异常。

官方给出解决这个问题的方案,就是使用FileProvider:

我们来看一段代码:

String cachePath = getApplicationContext().getExternalCacheDir().getPath();

File picFile = new File(cachePath, "test.jpg");

Uri picUri = Uri.fromFile(picFile);

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);

startActivityForResult(intent, 100);

这是常见的打开系统相机拍照的代码,拍照成功后,照片会存储在picFile文件中。

这段代码在Android7.0之前是没有任何问题的(奇葩情况忽略),但是如果你尝试在7.0的系统上运行,会抛出FileUriException异常。

使用FileProvider

FileProvider使用大概分为以下几个步骤:

manifest中申明FileProvider

res/xml中定义对外暴露的文件夹路径

生成content://类型的Uri

给Uri授予临时权限

使用Intent传递Uri

我们分别看下面这几个步骤的具体实现吧

manifest中申明FileProvider

...

...

android:name="android.support.v4.content.FileProvider"

android:authorities="com.mydomain.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

...

...

android:name:provider你可以使用v4包提供的FileProvider,或者自定义你自己的,只需要在name申明就好了,一般使用系统的就足够了。

Android:authorities:类似schema,命名空间之类,后面会用到。

Android:exported:false表示我们的providr不需要对外开发。

Android:grantUriPermissions:申明为true,你才能获取临时共享权限。

res/xml中定义对外暴露的文件夹路径

新建file_paths.xml,文件名随便起,后面会引用到。

name:一个引用字符串

path:文件夹"相对路径",完整路径取决于当前的标签类型。

path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。

这个元素内可以包含一下一个或多个,具体如下:

物理路径Context.getFilesDir()+"/path/"

物理路径Context.getCacheDir()+"/path/"

物理路径Environment.getExternalStorageDirectory()+"/path/"

物理路径Context.getExternalFilesDir(String)+"/path/"

物理路径Context.getExternalCacheDir()+"/path/"

注意:external-cache-path在support-v4:24.0.0这个版本并不支持,直到support-v4:25.0.0才支持。

番外:以上是官方提供的几种path类型,不过如果你想使用外置SD卡,可以用这个:

物理路径相当于/path/

这个官方文档并没有给出,我们可以查看源码可以发现:

![][2]

### 编写好file_paths.xml,我们在manifest中的provider这样使用:

android:name="android.support.v4.content.FileProvider"

android:authorities="com.mydomain.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/file_paths" />

## 生成content://类型的Uri

我们通常通过File生成Uri的代码是这样:

File picFile=xxx;

Uri picUri=Uri.fromFile(picFile);

这样生成的Uri,路径格式为file://xxx。前面我们也说了这种Uri是无法再App之间共享的,我们需要生成content://xxx类型的Uri,方法就是通过context.getUriFromFile来实现:

File imagePath=new File(Context.getFilesDir(),"images");

File newFile=new File(imagePath,"default_image.jpg");

Uri contentUri=getUriForFile(getContext(),"com.mydmain.fleprovider",newFile);

imagePath

使用的路径需要和你在file_paths.xml申明的其中一个符合(或者子文件夹:"images/work")。当然,你可以申明N个你需要共享的路径:

//...

getUriForFile

第一个参数是Context;第二个参数,就是我们之前在manifest#provider中定义的android:authorities属性的值;第三个参数是File.

给Uri授予临时权限intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

FLAG_GRANT_READ_URI_PERMISSION:表示读取权限;

FLAG_GRANT_WRITE_URI_PERMISSION:表示写入权限;

你可以同时或单独使用这两个权限,视你的需求而定。

使用Intent传递Uri

以开头的拍照代码作为示例,需要这样改写:

// 重新构造Uri:content://

File imagePath = new File(Context.getFilesDir(), "images");

if (!imagePath.exists()){imagePath.mkdirs();}

File newFile = new File(imagePath, "default_image.jpg");

Uri contentUri = getUriForFile(getContext(),

"com.mydomain.fileprovider", newFile);

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);

// 授予目录临时共享权限

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION

| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

startActivityForResult(intent, 100);

参考:

Android 7.0适配-应用之间共享文件(FileProvider)

Android 7.0 行为变更 通过FileProvider在应用间共享文件吧

快速使用FileProvider解决Android7.0文件权限问题

Android 7.0 FileProvider的使用

android开发 文件分享到应用,Android开发之——7.0适配之应用之间共享文件(FileProvider)...相关推荐

  1. android开发 文件分享到应用,Android 实现文件分享功能(共享多个文件)

    效果如图: 神一样的代码: 针对image代码如下: Intentshare=newIntent(Intent.ACTION_SEND); share.putExtra(Intent.EXTRA_ST ...

  2. Android.mk文件语法规范(Android.mk File)

    1.Android.mk文件概述 Android.mk文件用来告诉NDK编译系统,应该如何编译这些源码.更确切地说,该文件其实就是一个小型的Makefile.该文件会被NDK的编译工具解析多次,所以要 ...

  3. 【Android应用开发】分享一个录制 Android 屏幕 gif 格式的小技巧

    因为写博客总是需要录制 Android 软件的演示效果, 研究了将近一小时找到了合适的工具; 录制流程 : -- 1. 录制 Android 手机屏幕内容 : 使用 拍大师 软件录制 Android ...

  4. android rar文件怎么打开方式,android开发如何打开rar压缩文件

    释放双眼,带上耳机,听听看~! 有些文件是以压缩包的形式存在的,在打开之前需要对其进行解压,虽然大多数手机系统都有自己的解压功能,但当压缩包大于4GB时,使用自己的解压功能会导致文件损坏,那么andr ...

  5. android 原生分享文件,Android原生文件分享

    创建分享 创建Intent并指定Action为Intent.ACTION_SEND. val shareIntent = Intent(Intent.ACTION_SEND) 指定需要发送的内容和类型 ...

  6. Android微信文件分享

    最近在做微信分享相关功能,微信官方提供以下5种分享功能(文字类型分享示例.图片类型分享示例.音乐类型分享示例.视频类型分享示例.网页类型分享示例),官网上有相关demo代码,网址:https://op ...

  7. android studio文件存储路径,配置Android Studio的缓存文件路径(释放你的C盘)

    Android Studio默认安装完后会在C:\Users\YourName.xxx 缓存一些数据,有限的C盘很容易爆增. 如果你的C盘也像我这样捉襟见肘,或者你是处女座的,那么请看完本文,结果会让 ...

  8. 【区块链 | DAPP】Dapp应该怎么开发?分享一篇Dapp开发的逻辑(分享) 更新中~

    写在前面 本篇文章将带领你从零学会一个Dapp开发,笔者从最初的不了解区块链概念到如今精通Dapp.智能合约开发,中间踩过无数的坑,经历过无数困难! 商务合作: telegram: @sicong12 ...

  9. Android在eoe分享一篇推荐开发组件或者框架的文章

    http://www.eoeandroid.com/thread-311194-1-1.html y407827531 5 主题 62 帖子 352 e币 实习版主 积分 314 发消息 电梯直达 楼 ...

最新文章

  1. VSCode如何自动换行,右侧换行间距长度,隐藏右侧代码预览(Minimap代码缩略图滚动条),比对代码差异窗口也自动换行
  2. 花了两天,终于把 Python 的 setup.py 给整明白了
  3. Python语言学习:创建/删除文件/文件夹、获取当前文件/文件夹路径(系统环境路径/目录)、获取当前文件夹下的所有子文件路径等代码(os系列用法)实现之详细攻略
  4. 一霎清明雨,实现考勤管理。
  5. “Abp.AbpBootstrapper – System.MissingMethodException: Method not found: Void Abp.Configuration.Setti
  6. c语言如何扩大字体,C语言图形汉字及放大显示程序
  7. cisco 三层交换机作DHCP服务器的配置
  8. firewalld防火墙配置
  9. xxl_job springboot改造
  10. Agile入门系列-1
  11. Oracle手工创建数据库
  12. Android 导入导出excel xls、xlsx
  13. NLP【07】transformer原理、实现及如何与词向量做对接进行文本分类(附代码详解)
  14. 老板必看:1.初创业团队没有激情,咋办? 2.小股东的选择
  15. 罗格斯大学本科计算机科学,罗格斯大学计算机科学
  16. CSS3与页面布局学习总结(四)——页面布局大全
  17. Java Web基础
  18. 【架构师必知必会】常见的NoSQL数据库种类以及使用场景
  19. 区块链的奥卡姆剃刀在哪里?(1)
  20. Xcode 真机调试失败:Errors were encountered while preparing your device for development

热门文章

  1. 惯性矩和偏心距描述器
  2. 每日签到html特效,前端这种连续签到的效果要怎么写
  3. 软件开发报价模板_定制开发小程序和行业通用(模板)小程序的利弊分析
  4. mulitpartfile怎么接收不到值_和平精英信号接收区和信号值是什么?信号值怎么恢复...
  5. Postman入门到精通01
  6. STL13-list容器(链表)
  7. python3.8.2中文手册chm_3.2.2中文语法考察
  8. mitmproxy抓包 | Python双篡改假请求实战(六)
  9. BZOJ3223文艺平衡树——非旋转treap
  10. maven运行tomcat6出现错误Exception starting filter encodingFilter怎么解决