Android再也不容许在app中把file://Uri暴露给其余app,包括但不局限于经过Intent或ClipData 等方法。缘由在于使用file://Uri会有一些风险,好比:android
file://Uri
的app没法访问该文件。READ_EXTERNAL_STORAGE
权限,在读取文件时会引起崩溃。所以,google提供了FileProvider
,使用它能够生成content://Uri
来替代file://Uri
。安全
AndroidManifest.xml
中添加providerFileProvider.getUriForFile
()方法得到Url
在 res/xml 目录下新建一个 xml 文件,用于存放应用须要共享的目录文件。这个 xml 文件的内容相似这样:app
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="cam" path="images" /> </paths>
能够看出,这五种子元素基本涵盖内外存储空间全部目录路径,包含应用私有目录。同时,每一个子元素都拥有 name 和 path 两个属性。其中,path 属性用于指定当前子元素所表明目录下须要共享的子目录名称。注意:path 属性值不能使用具体的独立文件名,只能是目录名。而 name 属性用于给 path 属性所指定的子目录名称取一个别名。后续生成 content:// URI 时,会使用这个别名代替真实目录名。这样作的目的,很显然是为了提升安全性。若是咱们须要分享的文件位于同级别目录下不一样的子目录中,就须要添加多个子元素逐一指定要分享的文件目录,或者共享他们通用的父目录也行。ide
不一样的app可能会有要求不一样的共享目录,这个要求的共享目录能够在报错里找到,添加对应的报错路径便可.this
AndroidManifest.xml
中添加provider<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.yt.demo.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider>
请注意authorities这行,须要添加你的包名 加 后缀google
FileProvider.getUriForFile
()方法得到Url例子代码以下:spa
String filePath = Environment.getExternalStorageDirectory() + "/images/"+System.currentTimeMillis()+".jpg"; File outputFile = new File(filePath); if (!outputFile.getParentFile().exists()) { outputFile.getParentFile().mkdir(); } Uri contentUri = FileProvider.getUriForFile(this, getPackageName()+".fileprovider", outputFile);