版本更新是每个应用必不可少的功能之一.但是官方又没有一个实例来说明具体应该怎么做,于是就都是baidu别人的各种方案.但是网上的答案有的相当坑.吃了一个大亏.特此记录下.
现象:
加固前能正常更新,使用第三方加固乐固加固或者360加固后就不能正常安装
原因:
我的版本更新流程如下
String mimeDefault = "application/vnd.android.package-archive";
if (mFile == null) {
return;
}
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
//兼容7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//必须是addFlag setFlags 是覆盖权限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//这里牵涉到7.0系统中URI读取的变更
String authority = BuildConfig.APPLICATION_ID + ".fileprovider";
Uri contentUri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".fileprovider", mFile);
intent.setDataAndType(contentUri, mimeDefault);
//兼容8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = mContext.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
startInstallPermissionSettingActivity();
return;
}
}
} else {
intent.setDataAndType(Uri.fromFile(mFile), mimeDefault);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (mContext.getPackageManager().queryIntentActivities(intent, 0).size() > 0) {
//如果APK安装界面存在,携带请求码跳转。使用forResult是为了处理用户 取消 安装的事件。外面这层判断理论上来说可以不要,但是由于国内的定制,这个加上还是比较保险的
startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
} else {
startActivity(intent);
}
} catch (Throwable e) {
e.printStackTrace();
}finally {
//特此记录不能加,不然加固包解析错误
// android.os.Process.killProcess(android.os.Process.myPid());
}
关键代码
android.os.Process.killProcess(android.os.Process.myPid());
加了这个killProcess方法在加固前和加固后体现不一样.为什么要加这个呢,是因为
看了某些博主加的这个.因此就被坑惨了.至于具体是什么原因导致的呢,腾讯是这么回复的.
意思是他们也不知道什么原因导致的,据我分析,可能是因为加固需要当前应用存活才能启动成功.为此做了一个实验.
String mimeDefault = "application/vnd.android.package-archive";
if (mFile == null) {
return;
}
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
//兼容7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//必须是addFlag setFlags 是覆盖权限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//这里牵涉到7.0系统中URI读取的变更
String authority = BuildConfig.APPLICATION_ID + ".fileprovider";
Uri contentUri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".fileprovider", mFile);
intent.setDataAndType(contentUri, mimeDefault);
//兼容8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = mContext.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
startInstallPermissionSettingActivity();
return;
}
}
} else {
intent.setDataAndType(Uri.fromFile(mFile), mimeDefault);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (mContext.getPackageManager().queryIntentActivities(intent, 0).size() > 0) {
//如果APK安装界面存在,携带请求码跳转。使用forResult是为了处理用户 取消 安装的事件。外面这层判断理论上来说可以不要,但是由于国内的定制,这个加上还是比较保险的
startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
} else {
startActivity(intent);
}
} catch (Throwable e) {
e.printStackTrace();
}finally {
//手动休眠5秒
Thread.sleep(5000);
//特此记录不能加,不然加固包解析错误
android.os.Process.killProcess(android.os.Process.myPid());
}
手动休眠5秒再kill当前进程,可以正常版本更新!!!
这是有多坑,希望看到的人都不会出现这个问题!!!