起因
项目需要在下载文件后,使用其他app打开该文件,因为targetversion>24,由于众所周知的原因,需要使用ContentProvider来提供app内部文件给其他app使用,这里因为项目中是普通文件,所以选择了FileProvider。
重点
怎么使用FileProvider的文章网上已经很多了,大同小异,我就不多写了。
具体可以看我想把 FileProvider 聊的更透彻一些.
我单独说说filepaths文件的声明。
之前也用过FileProvider,也声明过filepaths文件,就是照着网上的文章写,但是不知道为什么要这么写。
经过
根据我自己的总结,不一定对—— filepaths文件主要关乎两个:
- 文件能否被外部应用访问
- 文件生成的uri的路径名称
先假设一个需求,然后来解决吧:
根据给定url下载一个文件,并保存在内存中,然后使用别的app打开该文件。
假设文件保存在内部存储中,文件名为“image.jpg”:
File shareFile = new File(getFilesDir(), "image.jpg");
需要使用其他app打开这个文件。
首先
1.在AndroidManifest文件中声明FileProvider:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.xxx.xxx.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
其中 @xml/filepaths 需要声明在res/xml文件中,内容为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path
name="root"
path="" />
<files-path
name="files"
path="." />
<cache-path
name="cache"
path="." />
<external-path
name="external"
path="." />
<external-path
name="external_files"
path="." />
</paths>
这里主要讲讲filepaths文件中各个值的作用——我了解的部分。
首先有一个对应关系,这是FileProvider的源码中规定的:
- root-path:表示根目录,『/』。
- files-path:表示 content.getFileDir() 获取到的目录。
- cache-path:表示 content.getCacheDir() 获取到的目录
- external-path:表示Environment.getExternalStorageDirectory() 指向的目录。
- external-files-path:表示 ContextCompat.getExternalFilesDirs() 获取到的目录。
- external-cache-path:表示 ContextCompat.getExternalCacheDirs() 获取到的目录。
filepaths文件的目的之一:声明你允许外部应用临时访问的文件的目录。即:只有在这里声明了的目录才能被外部应用访问到,如果希望通过content.getFileDir()得到的文件能被访问,则声明中需包含
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="files"
path="." />
</paths>
或者
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path
name="root"
path="" />
</paths>
前者表示允许外部应用访问所有content.getFileDir()目前之下的文件,后者表示允许外部应用访问所有应用内部的文件,当然也就包括content.getFileDir()目前之下的文件。所以如果偷懒的话,可以只写后者也是可以的。
同理,如果需要允许外部应用访问 content.getCacheDir() 目录下的文件,则声明中需包含
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path
name="cache"
path="." />
</paths>
或者
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path
name="root"
path="" />
</paths>
以此类推。
如果只允许外部应用访问content.getFileDir()内"cache/image/"目前下的文件,则可以由path来实现。
如果文件的绝对路径为:
/data/user/0/com.xxx.xxx/files/users/126357742779629568/cache/files/aboutaboutaboutaboutabout.html
由前面的内容可知,如果要允许外部应用访问该文件,则filepaths文件可以为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="files"
path="." />
</paths>
此时生成的uri为:
content://com.xxx.xxx.fileprovider/files/users/126357742779629568/cache/files/aboutaboutaboutaboutabout.html
filepaths也可以是:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="files"
path="./user" />
</paths>
此时生成的uri为:
content://com.uneed.yuni.fileprovider/files/126357742779629568/cache/files/aboutaboutaboutaboutabout.html
或者是:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="files"
path="./user/126357742779629568/cache/files" />
</paths>
此时生成的uri为:
content://com.uneed.yuni.fileprovider/files/aboutaboutaboutaboutabout.html
或者其他你猜到的。
即在生成的uri中,path所表示的路径(./user/126357742779629568/cache/files)整个由name字段的files所替代。
最后,其实以上内容通过查看Fileprovide的源码都可以知道。
完。