高版本部分机器安装apk失败
问题:在部分机器,如果通过app内部下载安装一个app,可能会出现 解析包失败
解决:这问题一般是跟机器相关,走正常的系统安装是无法成功的,我们可以自己创建一个PackageInstaller.Session,然后添加到系统中去,并且同时将文件写到PackageInstaller.Session.openWrite
步骤:
1. 获取到系统的PackageInstaller.SessionParams,然后将需要安装的apk的包名设置进去,并且通过反射设置setAllowDowngrade这个属性为true
2.创建出包名为安装应用的PackageInstaller.Session,获取Sessionid,然后获取当前Sessionid的PackageInstaller.Session,通过write的方式,将apk的数据流写入到PackageInstaller.Session中去
3.提交commit,实则通过广播PendingIntent.getBroadcast(context, sessionId,
new Intent(Intent.ACTION_MAIN), 0).getIntentSender()去通知系统,增加一个新的app成功
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static boolean install5(Context context, String apkPath) {
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params =new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
String pkgName =getApkPackageName(context, apkPath);
if (pkgName ==null) {
return false;
}
params.setAppPackageName(pkgName);
try {
Method allowDowngrade = PackageInstaller.SessionParams.class.getMethod("setAllowDowngrade", boolean.class);
allowDowngrade.setAccessible(true);
allowDowngrade.invoke(params, true);
}catch (Exception e) {
e.printStackTrace();
}
OutputStream os =null;
InputStream is =null;
try {
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
os = session.openWrite(pkgName, 0, -1);
is =new FileInputStream(apkPath);
byte[] buffer =new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
session.fsync(os);
os.close();
os =null;
is.close();
is =null;
session.commit(PendingIntent.getBroadcast(context, sessionId,
new Intent(Intent.ACTION_MAIN), 0).getIntentSender());
}catch (Exception e) {
return false;
}finally {
if (os !=null) {
try {
os.close();
}catch (IOException e) {
e.printStackTrace();
}
}
if (is !=null) {
try {
is.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}