最近在搞應(yīng)用升級的時候猩谊,7.0以下的手機(jī)都直接升級成功了锭吨。7.0的華為手機(jī)直接報這個錯誤径荔。
先分析一下包解析錯誤的各種原因
1 apk版本不兼容休讳。一般情況下當(dāng)從網(wǎng)上下載的apk程序版本比當(dāng)前設(shè)備的版本高時,就會在安裝程序時出現(xiàn)“解析包時出現(xiàn)錯誤”的警告赵哲。對此類情況的解決辦法是:就該款apk程序,查找同類對應(yīng)的但是版本應(yīng)不高于當(dāng)前設(shè)備版本的應(yīng)用程序進(jìn)行下載君丁、安裝和使用枫夺。
2 apk程序不完整。有些設(shè)備自帶的下載工具不具有斷點(diǎn)續(xù)傳功能绘闷,因而下載的程序可能發(fā)生下載不完全橡庞、程序部分先失等情況。
3 當(dāng)前設(shè)備不支持中文名稱或路徑烂斋,不支持長文件名籽腕。 解決辦法是將文件重命名赏殃,名稱只包含英文字母(但要注意".apk"的后輟名是要保留的),如更名為“abc.apk”等吧趣,更改完成后再次運(yùn)動安裝程序。
4 設(shè)備內(nèi)存不足或U盤質(zhì)量不好等因素導(dǎo)致apk程序無法正常安裝耙厚。即使存入內(nèi)存的數(shù)據(jù)容量大于實(shí)際內(nèi)存容量强挫,程序也不會報錯,但其實(shí)數(shù)據(jù)早已丟失薛躬。對于這種情況俯渤,apk程序肯定無法安裝成功。
5 指定的文件路徑不存在或指定了錯誤的路徑型宝。
6 apk安裝器可能不兼容八匠。
7 設(shè)備可能中毒。 進(jìn)行病毒的查殺趴酣,確保設(shè)備處于最佳安全運(yùn)行狀態(tài)梨树。
二、舉例我一個項(xiàng)目中的例子
我在下載安裝包的時候沒有適配好7.0的一些路徑价卤,導(dǎo)致一直包解析錯誤劝萤。
/**
* @描述 下載更新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("下載進(jìn)度: "+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手機(jī)適配
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);
}
});
}
三、 以下是收集到的一些相關(guān)的說法
(一)原文
開始懷疑是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
分析應(yīng)該是安裝軟件的時候厌处,進(jìn)行了證書的檢查鳖谈,發(fā)現(xiàn)軟件不符合條件,導(dǎo)致不能安裝阔涉。
翻看一下源代碼:scanPackageLI 這個應(yīng)該是對APK里的文件進(jìn)行解析缆娃,但是華為肯定是修改了這個函數(shù),添加了一個checkHwCertification的過程瑰排。
checkHwCertification里面應(yīng)該是檢查了華為特有的東西贯要。
打開代碼 在AndroidManifest.xml 找找有有沒有什么華為比較在乎需要檢查的東西,椭住,一看果然發(fā)現(xiàn)了下個崇渗。
<!--華為角標(biāo)-->
<uses-permissionandroid:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
<uses-permissionandroid:name="com.huawei.permission.sec.MDM"/>
把這兩個權(quán)限一刪除,軟件就可以正常安裝了京郑。
打開華為的官方文檔宅广,找到下面一段說明:
2.3 將華為證書打包到開發(fā)者應(yīng)用中
使用上面提到的“DevPack.exe”工具,將剛剛下載的華為證書打包到開發(fā)者 APK 中:
到這里原因以及很明白了些举,就是開發(fā)這沒有把證書加入到APK里面跟狱,導(dǎo)致安裝的檢查證書不通過。安裝失敗户魏。
但是華為也很不地道驶臊,之前都沒有這個過程,到P9上忽然加上這個限制绪抛,沒有任何說明资铡,直接就是軟件安裝失敗。讓廣大開發(fā)者情何以堪幢码。做android應(yīng)用開發(fā)的小伙伴真是不容易笤休,要應(yīng)付形形色色的奇葩兼容性問題。
解決方案:
1 去掉角標(biāo)功能症副,一般的應(yīng)用是無法通過華為的審核的店雅。在 AndroidManifest.xml刪除下面的權(quán)限申明:
<!--華為角標(biāo)-->
<uses-permissionandroid:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
<uses-permissionandroid:name="com.huawei.permission.sec.MDM"/>
2 把華為的證書打包到應(yīng)用里面。
(二)第二種說法
android 7.0引入了v2的apk簽名方案贞铣,一個新的app簽名方案闹啦,它提供了更快的app安裝時間和更多針對未授權(quán) APK 文件更改的保護(hù)。默認(rèn)情況下辕坝,android studio 2.2和android gradle 插件2.2窍奋,他們都能使用v2和傳統(tǒng)的簽名方式來簽名你的應(yīng)用程序。
雖然我們推薦使用v2的apk簽名方案,這個新方案不是強(qiáng)制的琳袄。當(dāng)使用v2的簽名方案時江场,如果你的應(yīng)用程序不能正確的構(gòu)建,你就可以放棄這個新方案窖逗。禁用過程會導(dǎo)致 Android Studio 2.2 和 Android Gradle 2.2 插件只能夠使用傳統(tǒng)簽名方案來簽署你的應(yīng)用程序址否。對于只使用傳統(tǒng)方式來簽名,打開build.gradle文件碎紊,在你的釋放版本的簽名配置中添加v2SigningEnabled false佑附。
警告:如果你使用v2來簽名你的應(yīng)用程序,并對應(yīng)用進(jìn)一步修改仗考,則app簽名將無效音同。因?yàn)檫@個原因,請在使用v2簽名之前秃嗜,使用zipalign工具瘟斜,而不是之后使用。
關(guān)于更多信息痪寻,請閱讀介紹如何在 Android Studio 中簽名一個app,以及如何使用 Android Gradle 插件來為簽名app配置build文件虽惭。
signingConfigs {
release {
storeFilefile("keystore")
storePassword"keystore的密碼"
keyAlias"keyAlias"
keyPassword"keystore的密碼"
// 作用是只使用舊版簽名橡类,禁用V2版簽名模式
v2SigningEnabled false
}