通过FileProvider分享文件 - AndroidLink/plaid GitHub Wiki
Android应用的内容分享,官方提供training课程包含三个专题:①通过Intent分享简单数据或有限字符串.②通过FileProvider分享整个文件.③通过NFC协议在设备间分享文件.详细参考构建应用的内容分享
Plaid应用使用了FileProvider, 以下结合官方两个文档FileProvider和安全文件分享,谈谈FileProvider在Plaid中的使用.
FileProvider是安卓官方出品的兼容库support-v4的一个类,派生自ContentProvider,一个应用通过它为文件生成形如content://的URI(不是我们以前常用file:///的uri), 然后使用这个安全的uri进行分享内容. content://使文件发送者可以通过临时授权读或写,通过Intent.setFlag(),直到指定接收app的Activity或Service激活运行,被认为比file:///安全(file:///要控制权限必须通过修改底层文件的权限,对所有应用都一样,文件权限在下次再修改前一直保持,所以基本被认为没有安全性可言).
FileProvider涉及到文件提供者和文件接收者两个app, 和以下几个点
①定义一个FileProvider
在AndroidManifest.xml定义provider节点,name固定为android.support.v4.content.FileProvider, authorities的值用package名.shareprovider, 向外exported为false,grantUriPermissions为true, 通过meta-data的android.support.FILE_PROVIDER_PATHS指定配置文件的xml
②指定可用的文件
在xml文件中,需要事先为FileProvider声明哪些目录可以生成content URI,在paths节点里,一个或多个子节点定义目录.files-path子节点表示在context.getFileDir()得到app在/data/data/包名/file/下的目录,external-path子节点对应context.getExternalFileDir()返回SD卡上目录下的子目录,而cache-path子节点表示context.getCacheDir()返回目录/data/data/包名/cache/下子目录.
Plaid在res/xml/glide_disk_cache_path.xml文件里,使用cache-path声明了name="share" path="image_manager_disk_cache"
③获得一个文件的content URI
见ShareDribbbleImageTask的onPostExecute里,创建文件所在目录路径的File对象,和①Manifest文件声明的authorities一起调用FileProvider.getUriForFile获得URI的格式content:///<path_name>/file_name,如content://io.plaidapp.shareprovider/share/menu-slide-left.jpg
④临时授权给URI
Context.grantUriPermission -> Intent.setData -> Intent.setFlag -> 把intent发送给其他app(如Intent.setResult或android4.1以后的Intent.setClipData).
⑤为其他应用提供content URI
Intent.setResult或android4.1以后的Intent.setClipData. Plaid在AndroidManifest.xml里已经授权, 在ShareDribbbleImageTask里通过ShareCompat.IntentBuilder.setStream()把URI分享到系统.