继上文输出之后,偶逢流感,又遇节日、停电。现在继续未完成的内容。


一、Provider的使用概述

本文暂且介绍FileProvider;至于后续遇到安卓新版本适配的其他Provider,到时再进行补充。

FileProvider:ContentProvider的子类,安卓提供唯一的安全接口用来访问File文件,通过getUriForFile()方法获取File的Uri,以Intent的方式分享给其他应用,并以ContentResolver进行解析此数据;


二、FileProvider

1、清单文件声明

...  ...  ...

FileProvider在V4包中已经包含,所以,可以在使用过程中,无需进行子类继承该类,直接使用。

① 根据您控制的域将android:authorities属性设置为URI权限; 例如,如果您控制域mydomain.com,则应使用权限com.mydomain.fileprovider;

②将android:exported属性设置为false; FileProvider不需要是公共的,即其他应用无法访问;

③将android:grantUriPermissions属性设置为true,授予其他应用对文件的临时访问权限。

2、创建并声明分享文件的路径

①在res/xml中创建file_paths.xml文件,说明需要分享文件的路径;

...





②在file_paths.xml中,对需要分享的文件路径进行说明,如下:



③将file_paths.xml文件以元数据的形式,声明于清单文件中:



④获取需要分享文件的Uri



⑤为Uri设置临时访问权限

两种方式,为Uri赋予临时访问权限,可以是只读、只写,或者,二者兼有;两种方式赋予的权限,会辐射到该应用的其他组件;不同的赋予方式,对权限回收的期限也有不同的影响。

a. Context 提供了两个方法

  • grantUriPermission(String toPackage, Uri uri, int modeFlags)
  • revokeUriPermission(Uri uri, int modeFlags);

可以看到 grantUriPermission() 方法需要传递一个包名,就是你给哪个应用授权,但是很多时候,比如分享,我们并不知道最终用户会选择哪个 app,所以我们可以这样:

List resInfoList = context.getPackageManager() .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; context.grantUriPermission(packageName, uri, flag);}

根据 Intent 查询出所有符合的应用,都给他们授权,然后在不需要的时候通过 revokeUriPermission 移除权限。

链接:https://www.jianshu.com/p/be817f3aa145

b. 配合 Intent.addFlags() 授权

既然这是一个 Intent 的 Flag,Intent 也提供了另外一种比较方便的授权方式,那就是使用 Intent.setFlags() 或者 Intent.addFlag 的方式

使用这种形式的授权,权限截止于该 App 所处的堆栈被销毁。也就是说,一旦授权,知道该 App 被完全退出,这段时间内,该 App 享有对此 Uri 指向的文件的对应权限,我们无法主动收回该权限了。

链接:https://www.jianshu.com/p/be817f3aa145



⑥通过Intent分享内容



⑦获取返回值

以不同的requestCode、resultCode,判断是从哪个业务逻辑返回的值,并从intent中获取对应的值;