- 一、高低版本兼容代码及配置
- 1.java代码
- 2.AndroidManifest.xml 配置ContentProvider
- 3.paths xml 配置
- 二、老版本代码
- 三、可能出的问题及处理
高版本提高了sdcard、 app文件空间的访问权限,高低版本的系统api有一定区别,Android7.0 及以上,开放(暴露)私有数据文件的唯一方式是通过 ContentProvider 来实现(我们的app提供我们的文件给系统安装程序)。
基本步骤
1、在AndroidManifest.xml 中配置 ContentProvider 信息;
2、配置要开放的 paths 信息;
3、Java 代码中通过 FileProvider 封装文件信息。
private void install(String path) {
File apk = new File(path);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//注意第二个参数,要保持和manifest中android:authorities的值相同
Uri uri = FileProvider.getUriForFile(context,
context.getPackageName() + ".fileProvider", apk);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apk), "application/vnd.android.package-archive");
}
try {
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
特别注意
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + “.fileProvider”, apk);
第二个参数一定要和provider 的android:authorities="${applicationId}.fileProvider"匹配。
applicationId是包名,context.getPackageName()也是包名,所以
context.getPackageName() + “.fileProvider”和 ${applicationId}.fileProvider 是相同的字符串
配置安装权限
配置ContentProvider
provider 属性说明:
-
android:name 属性填写的是 FileProvider 类的完整名称。这个类可以填写两个值,一个是位于 support(android.support.v4.content.FileProvider) 包下的,另一个是位于 androidx(androidx.core.content.FileProvider) 包下的。这两种都可以填写,本质上没有区别。要根据实际情况来决定用哪个,即要看工程引的是 androidx 支援包还是 support 支援包。
-
android:authorities 属性就是和普通的 ContentProvider 一样的用于访问文件资源的 uri 标签头。值内容根据实际需要来填写即可。
-
android:exported 与 android:grantUriPermissions 两个属性的值照着填就好。大致是指允许其它应用单次使用自己的 Provider 资源。
-
meta-data 标签中的内容需要关注的是 android:resource 属性中的内容。这个属性的值引向一个 xml目录的文件,这份 xml 文件描述要给其他应用访问的文件目录。
在工程 res 目录下新建一个 xml 没有的话新建)目录,则在目录中创建一个file_provider.xml(名称随意,和 android:resource=“@xml/file_provider” 一致即可),并在xml中添加需要对外提供的目录路径
简要说明:
不带external 是程序安装目录下的目录,cache-path 指程序安装目录下的cache目录。
带有external 的是指sdcard 目录下对应包名的专属目录,例如external-cache-path 指sdcard 目录下对应包名的专属cache目录。
例如下图是斗鱼直播的files目录:
对应下图
如果还有子目录,对应的增加接口,例如files 目录下的douyu, 那么xml如下:
二、老版本代码
老版本代码相对简单,粗暴且实用,只要知道 apk 的path,并拥有访问权限(sdcard),
再加上安装权限即可。
File apk = new File(apkPath);
Uri uri = Uri.fromFile(apk);
Intent intent = new Intent();
intent.setClassName("com.android.packageinstaller",
"com.android.packageinstaller.PackageInstallerActivity");
intent.setData(uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
manifest 添加对应的权限
三、可能出的问题及处理
- java.lang.NullPointerException: Attempt to invoke virtual method ‘android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)’ on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:591)
原因:FileProvider.getUriForFile(context, context.getPackageName() + “.fileProvider”, apk); 第二个参数 “包名.fileProvider” 和 provider.xml 中 android:authorities=“${applicationId}.fileProvider” 的值(具体值:如com.eagle.app.fileProvider)不同,请仔细核对和修改一致。 - 权限问题
一般app需要安装权限,除了在清单文件中列出外,还需要手动确认,注意留意并确认 - 下载的安装文件路径与file_provider 中描述的文件不匹配,仔细核对路径与描述。
- 安全提示要选择允许



