最近在搞应用升级的时候,7.0以下的手机都直接升级成功了。7.0的华为手机直接报这个错误。
先分析一下包解析错误的各种原因
1 apk版本不兼容。一般情况下当从网上下载的apk程序版本比当前设备的版本高时,就会在安装程序时出现“解析包时出现错误”的警告。对此类情况的解决办法是:就该款apk程序,查找同类对应的但是版本应不高于当前设备版本的应用程序进行下载、安装和使用。
2 apk程序不完整。有些设备自带的下载工具不具有断点续传功能,因而下载的程序可能发生下载不完全、程序部分先失等情况。
3 当前设备不支持中文名称或路径,不支持长文件名。 解决办法是将文件重命名,名称只包含英文字母(但要注意".apk"的后辍名是要保留的),如更名为“abc.apk”等,更改完成后再次运动安装程序。
4 设备内存不足或U盘质量不好等因素导致apk程序无法正常安装。即使存入内存的数据容量大于实际内存容量,程序也不会报错,但其实数据早已丢失。对于这种情况,apk程序肯定无法安装成功。
5 指定的文件路径不存在或指定了错误的路径。
6 apk安装器可能不兼容。
7 设备可能中毒。 进行病毒的查杀,确保设备处于最佳安全运行状态。
二、举例我一个项目中的例子
我在下载安装包的时候没有适配好7.0的一些路径,导致一直包解析错误。
/**
* @描述 下载更新app
*/
private void downLoadApk(String url) {
/*okttp下载*/
OkHttpUtils.get()
.url(url)
.build()
.execute(new FileCallBack(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(), dowmApkNames)
{
@Override
public void onError(Call call, Exception e, int id) {
LogUtils.log("下载失败");
}
@Override
public void inProgress(float progress, long total, int id) {
super.inProgress(progress, total, id);
LogUtils.log("下载进度: "+progress+" -total: "+total+" -id:"+id);
}
@Override
public void onResponse(File response, int id) {
LogUtils.log("下载成功"+");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 以新压入栈
if (GlobalConfig.VerMoreThenM) {//7.0手机适配
Uri apkUri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".provider", response);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
}else{
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(response.getAbsoluteFile()),
"application/vnd.android.package-archive");
}
mContext.startActivity(intent);
}
});
}
三、 以下是收集到的一些相关的说法
(一)原文
开始怀疑是android的版本问题,后来看了一下在华为Mate8上面也能正常安装,华为Mate8和华为P9都是android6.0
华为P9 用的是 EMUI 4.1版本,但是华为Mate8用的是EMUI4.0, 初步怀疑是EMUI升级后的问题
05-14 19:51:04.094: E/HwCertificationManager(1004): read cert error:read certification file error!
05-14 19:51:04.094: E/HwCertificationManager(1004): read cert failed
05-14 19:51:04.094: E/HwCertificationManager(1004): checkHwCertification parse error
05-14 19:51:04.095: E/installd(534): Couldn't opendir /data/data/com.shb.assistant: No such file or directory
05-14 19:51:04.096: W/PackageManager(1004): Package couldn't be installed in /data/app/com.shb.assistant-1
05-14 19:51:04.096: W/PackageManager(1004): com.android.server.pm.PackageManagerException: hwcertification parse error
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.HwPackageManagerService.checkCertificationInner(HwPackageManagerService.java:3042)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.HwPackageManagerService.checkHwCertification(HwPackageManagerService.java:3024)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService.scanPackageLI(PackageManagerService.java:6941)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService.scanPackageLI(PackageManagerService.java:6930)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService.installNewPackageLI(PackageManagerService.java:12494)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:13215)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService.-wrap29(PackageManagerService.java)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.pm.PackageManagerService$10.run(PackageManagerService.java:10799)
05-14 19:51:04.096: W/PackageManager(1004): at android.os.Handler.handleCallback(Handler.java:743)
05-14 19:51:04.096: W/PackageManager(1004): at android.os.Handler.dispatchMessage(Handler.java:95)
05-14 19:51:04.096: W/PackageManager(1004): at android.os.Looper.loop(Looper.java:150)
05-14 19:51:04.096: W/PackageManager(1004): at android.os.HandlerThread.run(HandlerThread.java:61)
05-14 19:51:04.096: W/PackageManager(1004): at com.android.server.ServiceThread.run(ServiceThread.java:46)
05-14 19:51:04.115: I/art(1004): Starting a blocking GC Explicit
分析应该是安装软件的时候,进行了证书的检查,发现软件不符合条件,导致不能安装。
翻看一下源代码:scanPackageLI 这个应该是对APK里的文件进行解析,但是华为肯定是修改了這个函数,添加了一个checkHwCertification的过程。
checkHwCertification里面应该是检查了华为特有的东西。
打开代码 在AndroidManifest.xml 找找有有没有什么华为比较在乎需要检查的东西,,一看果然发现了下个。
<!--华为角标-->
<uses-permissionandroid:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
<uses-permissionandroid:name="com.huawei.permission.sec.MDM"/>
把这两个权限一删除,软件就可以正常安装了。
打开华为的官方文档,找到下面一段说明:
2.3 将华为证书打包到开发者应用中
使用上面提到的“DevPack.exe”工具,将刚刚下载的华为证书打包到开发者 APK 中:
到這里原因以及很明白了,就是开发这没有把证书加入到APK里面,导致安装的检查证书不通过。安装失败。
但是华为也很不地道,之前都没有这个过程,到P9上忽然加上这个限制,没有任何说明,直接就是软件安装失败。让广大开发者情何以堪。做android应用开发的小伙伴真是不容易,要应付形形色色的奇葩兼容性问题。
解决方案:
1 去掉角标功能,一般的应用是无法通过华为的审核的。在 AndroidManifest.xml删除下面的权限申明:
<!--华为角标-->
<uses-permissionandroid:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
<uses-permissionandroid:name="com.huawei.permission.sec.MDM"/>
2 把华为的证书打包到应用里面。
(二)第二种说法
android 7.0引入了v2的apk签名方案,一个新的app签名方案,它提供了更快的app安装时间和更多针对未授权 APK 文件更改的保护。默认情况下,android studio 2.2和android gradle 插件2.2,他们都能使用v2和传统的签名方式来签名你的应用程序。
虽然我们推荐使用v2的apk签名方案,这个新方案不是强制的。当使用v2的签名方案时,如果你的应用程序不能正确的构建,你就可以放弃这个新方案。禁用过程会导致 Android Studio 2.2 和 Android Gradle 2.2 插件只能够使用传统签名方案来签署你的应用程序。对于只使用传统方式来签名,打开build.gradle文件,在你的释放版本的签名配置中添加v2SigningEnabled false。
警告:如果你使用v2来签名你的应用程序,并对应用进一步修改,则app签名将无效。因为这个原因,请在使用v2签名之前,使用zipalign工具,而不是之后使用。
关于更多信息,请阅读介绍如何在 Android Studio 中签名一个app,以及如何使用 Android Gradle 插件来为签名app配置build文件。
signingConfigs {
release {
storeFilefile("keystore")
storePassword"keystore的密码"
keyAlias"keyAlias"
keyPassword"keystore的密码"
// 作用是只使用旧版签名,禁用V2版签名模式
v2SigningEnabled false
}