存储适配系列文章:
androids-存储基础androids-10、11-存储完全适配(上)androids-10、11-存储完全适配(下)androids-FileProvider-轻松掌握
之前在分析androids 存储相关知识点的时候,有同学提出希望也分析一下FileProvider,那时忙于总结线程并发知识点,并没有立即着手分享。本次,将着重分析androids 应用之间如何使用第三方应用打开文件,如何分享文件给第三方应用。 通过本篇文章,你将了解到:
1、androids 应用间共享文件 2、FileProvider 应用与原理 3、FileProvider Uri构造与解析
1、androids 应用间共享文件共享基础提到文件共享,首先想到就是在本地磁盘上存放一个文件,多个应用都可以访问它,如下:
理想状态下只要知道了文件的存放路径,那么各个应用都可以读写它。
比如相册里的图片存放目录:/sdcard/DCIM/、/sdcard/Pictures/ 。
再比如相册里的视频存放目录:/sdcard/DCIM/、/sdcard/Movies/。
共享方式一个常见的应用场景:
应用A里检索到一个文件my.txt,它无法打开,于是想借助其它应用打开,这个时候它需要把待打开的文件路径告诉其它应用。
假设应用B可以打开my.txt,那么应用A如何把路径传递给应用B呢,这就涉及到了进程间通信。蜜桃成人网站入口知道androids进程间通信主要手段是Binder,而四大组件的通信也是依靠Binder,因此蜜桃成人网站入口应用间传递路径可以依靠四大组件。
可以看出,Activity/Service/Broadcast 可以传递Intent,而ContentProvider传递Uri,实际上Intent 里携带了Uri变量,因此四大组件之间可以传递Uri,而路径就可以存放在Uri里。
2、FileProvider 应用与原理以使用其它应用打开文件为例,分别阐述androids 7.0 前后的不同点。
androids 7.0 之前使用上面说到了传递路径可以通过Uri,来看看如何使用:
private void openByOtherForN() { Intent intent = new Intent(); //指定Action,使用其它应用打开 intent.setAction(Intent.ACTION_VIEW); //通过路径,构造Uri Uri uri = Uri.fromFile(new File(external_filePath)); //设置Intent,附带Uri intent.setData(uri); //跨进程传递Intent startActivity(intent); }其中
external_filePath=“/storage/emulated/0/fish/myTxt.txt”构造为uri 后uriString=“file:///storage/emulated/0/fish/myTxt.txt”可以看出,文件路径前多了"file:///"字符串。 而接收方在收到Intent后,拿出Uri,通过:
filePath = uri.getEncodedPath() 拿到发送方发送的原始路径后,即可读写文件。
然而此种构造Uri方式在androids7.0(含)之后被禁止了,若是使用则抛出异常:
可以看出,Uri.fromFile 构造方式的缺点:
1、发送方传递的文件路径接收方完全知晓,一目了然,没有安全保障。 2、发送方传递的文件路径接收方可能没有读取权限,导致接收异常。
androids 7.0(含)之后的使用先想想,若是蜜桃成人网站入口自己操刀,如何规避以上两个问题呢?针对第一个问题: 可以将具体路径替换为另一个字符串,类似以前密码本的感觉,比如: “/storage/emulated/0/fish/myTxt.txt” 替换为"myfile/Txt.txt",这样接收方收到文件路径完全不知道原始文件路径是咋样的。
不过这也引入了另一个额外的问题:接收方不知道真实路径,如何读取文件呢?
针对第二个问题 既然不确定接收方是否有打开文件权限,那么是否由发送方打开,然后将流传递给接收方就可以了呢?
androids 7.0(含)之后引入了FileProvider,可以解决上述两个问题。
FileProvider 应用先来看看如何使用FileProvider 来传递路径。 细分为四个步骤:
一:定义FileProvider 子类public class MyFileProvider extends FileProvider {}定义一个空的类,继承自FileProvider,而FileProvider 继承自ContentProvider。注:FileProvider 需要引入androidsX
二:androidsManifest 里