大话FileProvider

戏说江湖静如水,游荡江湖才有情。我就是江湖中的一个戏子。

最近android N出来了,可是呢,原有的程序在androidN上运行却行不通了,最近楼主就遇到这样的一个问题。android.os.FileUriExposedException,网上一查,原来androidN加强了文件共享机制,当传递file:///开头的uri时会抛出SecurityException。需要通过FileProvider来将File转换为content://类型的uri。下面我们就来了解一下今天的主人公FileProvider吧。

what and why

FileProvider是ContentProvider的一个子类,不懂ContentProvider出门右拐上google,FileProvider能够很轻易的通过创建content://类型的uri而不是file:///类型的uri来分享文件,那么为什么通过content://类型uri就更安全呢,是因为分享file:///类型的uri需要拥有文件系统权限,而这个文件系统的权限是针对任何应用都可以申请的,那么你就可以对该文件进行修改,而这种修改严格来说是不安全的。而通过content://来分享,需要获取临时权限,而这种权限是跟随接收的Activity或Service的生命周期来的。

How to use

那FileProvider要怎么使用呢?很简单只需要三步:

第一步:在AndroidMainfest.xml中声明FileProvider
<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="包名.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
              android:name="android.support.FILE_PROVIDER_PATHS"
              android:resource="@xml/file_paths"/>
</provider>

authorities 一般是 包名+.fileprovider。resource是file_paths定义的是需要共享的文件夹路径

第二步:定义file_paths
<paths xmlns:android="http://schemas.android.com/apk/res/android">
         <files-path name="my_images" path="images/"/>  
</paths>

该文件中files_path是共享文件夹路径,在google中定义了几个路径如 下:

参数函数地址
files-pathcontext.getFilesDir()/data/user/0/包名/files
cache-pathcontext.getCacheDir()data/user/0/包名/cache
external-pathEnvironment.getExternalStorageDirectory()/storage/emulated/0
external-files-pathcontext.getExternalFilesDir(null)/storage/emulated/0/Android/data/包名/files
external-cache-pathContext.getExternalCacheDir()storage/emulated/0/Android/data/包名/cache

共享路径就是(上述地址+path后面的参数)所代表的实际地址。

第三步:获取uri

在需要获取uri的地方通过FileProvider获取uri

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      uri = FileProvider.getUriForFile(context,authority,file);
} else {
      uri = Uri.fromFile(file);
}

提醒

// 在传递Intent的时候一定要通过Intent的setFlags来给接收的应用读取权限哦
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

这里的authority就是我们在定义FileProvider中authority是一样的,一般都是以包名+.fileprovider来定义,以避免和其他应用定义的authority相混淆。

总结

通过这三步我们就获得了我们需要的uri,一般的格式为content://包名.provider/path_name/file_name的形式。
这里path_name就是我们在files_path.xml中定义的name。走到这一步就大功告成了,你有没有学会呢?

    原文作者:戏说江湖
    原文地址: https://www.jianshu.com/p/eb90dc163ffd
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞