android7.0适配参见链接
原因:
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)和addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)顺序问题.
如果setFlags在addFlags之后,会将之前的flag清掉,导致读取权限获取不到,进而解压缩出错。
final File file= new File(url);
if(!file.exists()){
return;
}
Intent intent= new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// sdk >= 24
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用一个临时授权.注意8.0手机,setflag new task在前,addflag在后
Uri contentUri = FileProvider.getUriForFile(context,
context.getApplicationContext().getPackageName() + ".provider",
file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
Uri uri = Uri.fromFile(file);//或者 Uri.isPaise("file://"+file.toString()
intent.setDataAndType(uri, "application/vnd.android.package-archive");
}
context.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
添加权限:
判断是否有权限安装,有则直接安装:
/**
* android 8.0以上,安装未知来源app需要添加权限
* @param sdPath
*/
private static void checkUserPermission(String sdPath) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//26 android8.0以上。build.gradle中compile版本必须是26或以上
//判断应用是否有权限安装apk
boolean hasInstallPermission = context.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
((SplashActivity)context).perimissionRequest();
return;
}else {
installApk(context, sdPath);
}
}else {
installApk(context, sdPath);
}
}
无权限,则让用户手动设置权限:
/**
* android8.0请求安装权限
*/
public void perimissionRequest() {
Log.d("android8.0请求安装权限","perimissionRequest()");
//请求安装未知应用来源的权
Intent localIntent = new Intent();
localIntent.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
localIntent.setData(Uri.parse("package:"+getPackageName()));
startActivityForResult(localIntent,GET_UNKNOWN_APP_SOURCES);
ToastUtil.showzidingyiToast(this,1,"请打开未知应用安装权限");
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG,"requestCode = "+requestCode+" resultCode= "+resultCode);
switch (requestCode) {
case GET_UNKNOWN_APP_SOURCES://android8.0
CheckApkUtils.installApk(this, Environment.getExternalStorageDirectory().getAbsolutePath());
break;
default:
break;
}
}
——原因:读取权限获取失败,加固后,代码执行出现偏差,可能先kill掉程序再获取读权限,造成失败。
方法:安装apk时,增加一个weakHandler延迟kill进程
——这种情况避免加固后代码执行出现时间偏差,kill语句先执行导致验证权限失败的情况。【当然,修改后仍存在极低的概率仍会先执行,主要是9.0已经读取出下载的文件了,但是点击“安装”时闪退),需要再加一层判断,即检测本地是否已下载,若是则提示安装,避免之前安装失败的情况】
以上涉及读写权限问题,还有一种解决办法,就是下载apk时,不要存储到外部存储中,直接放到app自身的file目录或cache目录,就不存在读写的权限问题了。
① 服务器-版本请求放在onWindowFocusChanged()或者onResume()中,注意要使用一个flag判断是否已经请求过,避免重复请求
——这种情况,会先弹出权限,权限结束才显示更新内容。避免读写权限问题。
同时还因为,如果放在onCreate()中,检测本地已下载的apk文件信息时,如果是第一次,getPackageArchiveInfo()返回为null,因而被误判本地无下载的最新版本,进而去提示下载更新【其实本地已经有了,应该直接安装】
② 添加本地是否已经下载判断,若已下载直接安装(这里未知app安装权限仍要判断一下)
——避免下载后直接安装时解压缩失败的情况。【初步判定时加固导致的代码执行时间存在偏差,可能还未获取到读的权限就kill了,而如果直接注销kill,有可能无法覆盖安装】
这个值如果不存在,修改build.gradle中的compile版本26或以上:
Build.VERSION_CODES.O
Android检查版本升级应该怎么做?
记 Android 7.0 8.0版本更新安装遇到的坑
【Android开发】app升级报错,解析包时出现错误(华为手机8.0系统)