又是好长一段时间没有写东西了,说忙到没有时间写东西,这个说法在任何时候都是借口。总的来说还是没有写,真的要写的话还是有时间来写的,不说成为一个高产的人吧,但是稍微写一些的时间还是有的,再不济也可以分开到很多天再来写的吧。所以说这到头来还是个人的问题,没有主动有意识的去写这些东西,没有有意识的去学习去分享。这也在一定程度上说自己这段时间主动学习的时间少了。无论如何,还是要好好学习的,虽然已经不再学校,但从另一个角度来说自己应该更能明白知识的重要性。所以以后要多加注意主动学习。

前言

Android 在很多时候需要使用本地的文件,除了需要使用到读写外部存储文件权限之外,有时候还需要使用到内容提供器:ContentProvider。说到这里我真的感叹 Android 开发的混乱,需要使用到各种适配。比如 Android 随着版本的变化带来的 API 的变化,不同生产商自定义的 Android 的功能,不同手机不同屏幕尺寸的适配。总之这就带来了很多问题,原本在这个手机上运行好好的程序到另一个手机上却是 cash 了,十分的蛋疼。这次要说的是对于文件的处理差异,主要涉及的是文件 Uri 的处理。此处以 Android N 为分界,SDK_INT < N 归为一种情况,另外是一种情况。

API < 24

Uri uri = Uri.fromFile(file)

在 Android N 也就是 Android 7.0 之前使用上面这个方法是完全没有问题的,比如

1

2

3

4

5

6Intent intent = new Intent(Intent.ACTION_VIEW);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

File file = new File(path); // path 是外部存储中的一个图片的路径

Uri uri = Uri.fromFile(file);

intent.setDataAndType(uri, "image/*");

startActivity(Intent.createChooser(intent, null));

这个方法可以调用系统中支持打开图片的应用让用户选择并打开对应的图片,而没有任何问题。当时事情到了 7.0 之后就不一样了,这个方法会抛出一个 FileUriExposedException 的异常。

API >= 24

Uri uri = FileProvider.getUriForFile(context, athorty_key, file)

从 7.0 之后提高了文件的安全性,就需要用上述的方法来获取文件的 Uri。总共分为这几步。

在 AndroidManifest.xml 中定义 FileProvider 如下

1

2

3

4

5

6

7

8

9

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

android:authorities="${applicationId}.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

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

其中 name, exported, grantUriPermissions 的值不能改变,authorities 则是在使用 getUriForFile() 方法的第二个参数,用于标识与验证。

添加 @xml/provider_paths 资源如下

1

2

3

4<?xml version="1.0" encoding="utf-8"?>

其中 name 的值会在构成的 uri 中出现,用于隐藏实际的路径,增加安全性;path 则表示文件的读取路径,此处是表示外部存储中的所有文件路径,当然你可以指定为某一个文件夹,比如”image/“,则只有这个文件夹下的文件能正常访问,其他的文件夹不行;至于 external-path 标签则是表示这个提供的是外部存储的读取,如果你需要读取缓存路径或者其他的路径的文件的 uri 则必须要添加对应的标签值。有哪些标签可以去官方看。

使用 Uri uri = FileProvider.getUriForFile(context, athorty_key, file); 把文件转换成 Uri。如

1

2

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

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

Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile); // 官方示例

如果分享到其他应用,还需要进行授权。需要给目标应用添加读取 uri 的权限。

使用 Context.grantUriPermission(package, Uri, mode_flags) 给特定的应用包添加读写权限,mode_flags 包括 FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION,可以都添加,分别是读和写 Uri 的权限。授权期限到重启设备或者使用 revokeUriPermission() 取消权限为止。

除上面的方法之外,也可以使用在自己的要使用的 Intent 中加入这个权限,比如有一个 Intent 为 intent,调用 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 则使用该 intent 的应该可以读取 uri,但下次还需要添加才行。

所以上面的那个分享的方式可以写成如下的形式来调用:

1

2

3

4

5

6

7

8

9

10

11

12Intent intent = new Intent(Intent.ACTION_VIEW);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

File file = new File(path); // path 是外部存储中的一个图片的路径

Uri uri;

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {

uri = Uri.fromFile(file);

} else {

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

uri = FileProvider.getUriForFile(content, authorities, file);

}

intent.setDataAndType(uri, "image/*");

startActivity(Intent.createChooser(intent, null));

后记

时隔很久之后才重新写的分享,发现写起来真的废力啊,耗时比预计时间长,自己的打字速度不行啊。总之,以后也要加油啊。本次分享到这里,下一次,写的应该是关于不同 Android 版本的热点和 Wifi 的管理,这里面套路比这个更深啊,汗颜。。。

链接

--- end ---

Android用外部应用打开文件,Android N 以上使用其他应用打开文件 FileProvider相关推荐

  1. (最新)Android(安卓)FileProvider配置实现文件由其他app(应用)打开或者分享

    文章目录 一.AndroidManifest.xml文件配置 二.编写paths 三.intent具体实现 四.总结 参考资料 最近在做一个安卓app,需要实现对ListView所列的特定后缀的文件进 ...

  2. android studio 如何导出,打开数据库.db文件以及通过navicat Premium的安装打开数据库文件

    昨天整整弄了好几个小时再加上今天一个早上,终于搞定了.当初是想看一下/data/data/com.android.providers.downloads/database.db 里面到底是什么样的内容 ...

  3. 【Android 逆向】arm 汇编 ( 使用 IDA 解析 arm 架构的动态库文件 | 使用 IDA 打开 arm 动态库文件 | 切换 IDA 中汇编代码显示样式 )

    文章目录 一.使用 IDA 打开 arm 动态库文件 二.切换 IDA 中汇编代码显示样式 一.使用 IDA 打开 arm 动态库文件 分析 Android SDK 中的 arm 架构的动态库 , 动 ...

  4. 【Android 逆向】x86 汇编 ( 使用 IDA 解析 x86 架构的动态库文件 | 使用 IDA 打开动态库文件 | IDA 中查找指定的方法 )

    文章目录 一.使用 IDA 打开动态库文件 二.IDA 中查找指定的方法 一.使用 IDA 打开动态库文件 分析 Android SDK 中的 x86 架构的动态库 , 动态库位置 : D:\001_ ...

  5. android studio 本地html,android - 从当前HTML文件Android Studio中打开本地HTML文件? - 堆栈内存溢出...

    我在Android Studio上制作了一个WebView应用. 它会正确打开我的默认索引HTML页面 @Override protected void onCreate(Bundle savedIn ...

  6. java android 读取微信文件,Android 实现微信,QQ文件在其他应用打开并获取到路径

    例如: 1.想实现其他应用打开出现自己的应用,需要在清单文件中增加配置 注:自己需要什么样的文件格式自己可以配置,其中 minType 代表要打开的文件类型. 常用的类型: {".3gp&q ...

  7. android打开教程,Android 打开网络上pdf文件

    1.基本思路: 打开网络pdf 思路整体还是来源与图片的加载. android中加载网络图片的框架有很多个.如image-laoder, fresco.glide等,首先都是从内存中找图片,如果内存中 ...

  8. android studio创建md,如何在Android Studio中设置*md文件打开方式

    最近在Android Studio中写一些Demo的时候,会顺便在里面创建一个.md文件用来进行Demo笔记的书写.然而Android Studio不带有markdown预览功能,所以我就琢磨如何在A ...

  9. kotlin读取sd卡里的文件_Kotlin Android读写外部存储

    本文概述 Android外部存储空间是我们执行读写操作的存储空间.外部存储器中的文件存储在/ sdcard或/ storage文件夹等中.保存在外部存储器中的文件是可读的, 并且可由用户修改. 在访问 ...

最新文章

  1. linux nginx cdn,linux – Nginx Proxy_Pass到CDN与直接击中CDN. P...
  2. JVM的监控工具之jinfo
  3. 文末送书丨深度迁移学习方法的基本思路
  4. 什么样的程序员会让人讨厌?大家注意,千万不要成为这种程序员!
  5. php+fpm+apache
  6. Linux下Apache与Tomcat的完全分布式集群配置(负载均衡)
  7. Markdown语法(一)标题段落分割线
  8. python的Singleton模式实现
  9. ffmpeg下载视频
  10. [网络] 数字签名和数字证书的原理机制
  11. 高老师架构设计思考短句集(2)
  12. 更改系统时区为东八区
  13. linux服务器留后门,Linux下留本地后门的两个方法
  14. 计算机硬件知识总结,计算机硬件知识总结(二)
  15. 柠檬ban软件测试之python高级测试开发学习笔记
  16. Vue.js 实战总结
  17. 无盘服务器网线接法,无盘经验:解析网吧千兆网线的标准做法
  18. 国内智能视频分析监控技术的出路
  19. python tell方法_Python3 File tell() 方法
  20. 【NETGEAR网件】WNDR3700V4 或 WNDR4300 刷OpenWrt及恢复(刷回)

热门文章

  1. Python+numpy实现矩阵QR分解
  2. axure选中状态的值_关于编写Axure的心得
  3. linux打开mysql某张表_Linux——MySQL多表连接
  4. php百度语音合成,Drupal 与百度云语音合成(PHP SDK)的集成
  5. qtplaintextedit如何删除内容_数据库中的数据如何进行批量修改
  6. mysql 查看collation_MySQL collation方法
  7. linux的can通信busoff,socketCAN内核源码分析是否支持busoff自恢复--Apple的学习笔记
  8. led数字字体_技术丨体育场馆LED显示屏设计与安装要求
  9. 点击按钮刷新_Chrome扩展推荐:抢票太累?后台监视网页,页面自动刷新和提醒...
  10. oracle 表的移动,oracle 表移动表空间