上半年用Android写了个小应用,使用Ant构建,一直都跑得非常顺利。突然有一天,生成的APK不能安装了!在用豌豆夹安装生成的APK时报了个错:
安装失败:该应用签名有问题,无法安装,您可以尝试用豌豆荚手机精灵完整版进行重试。 |
一开始,我以为是Debug版本和正式的keystore冲突造成的,结果即使把已安装的应用删了之后再安装,仍然报错……偶的神啊,我到底干了啥?
回想良久,貌似我只更新了JDK而已,安装了JDK7。于是重设JAVA_HOME和PATH,使之指向JDK6,再重新用Ant构建——APK安装成功。
事实证明了Ant+JDK7构建的APK不能安装,这引起了我的好奇心。我决定研究一下为什么不能。考虑到提示“签名有问题”,所以我将两个APK用压缩软件打开,比较了一下META-INF中的东西,结果发现.SF文件内容有点区别,JDK6生成的那个,是用的SHA1摘要算法,而JDK7生成的那个是用的SHA256。
JDK7居然修改了jarsigner的默认算法!
于是我尝试用jarsigner,指定参数-digestalg SHA1,手工对APK进行了签名。签名后的APK可以成功安装运行。
既然如此,我认为去修改下Android SDK的tools/ant/build.xml,把签名那段配置加个参数就行了吧。没想到一查Ant Document,signjar任务居然不支持指定算法的参数。
B方案,用exec调用jarsigner来签名好啦!
- <!-- <signjar
- jar="${out.packaged.file}"
- signedjar="${out.unaligned.file}"
- keystore="${key.store}"
- storepass="${key.store.password}"
- alias="${key.alias}"
- keypass="${key.alias.password}"
- verbose="${verbose}" /> -->
- <exec executable="jarsigner" failonerror="true">
- <arg line="-verbose -digestalg SHA1 -sigalg MD5withRSA" />
- <arg line="-keystore ${key.store} -storepass ${key.store.password} -keypass ${key.alias.password}" />
- <arg line="-signedjar "${out.unaligned.file}"" />
- <arg line=""${out.packaged.file}" ${key.alias}" />
- </exec>
虽然B方案可行,但是我不甘心,决定上网搜搜,有没有更好的解决办法。一搜之下发现,原来还真有人要求Ant为signjar任务添加digestalg和sigalg参数。不过这在1.8.2里肯定是看不到了,一年了也没见Ant有更新,也许下一个版本里会有吧。
不过Google毕竟是强大的,当然更强大的是聪明的程序员,我还搜到了一个C方案,说起来,跟B方案异曲同工,就是定义一个叫signjarjdk7的宏,调用exec来实现——这和B方案没啥区别,只是貌似改起来方便些:
- <macrodef name="signjarjdk7">
- <attribute name="jar" />
- <attribute name="signedjar" />
- <attribute name="keystore" />
- <attribute name="storepass" />
- <attribute name="alias" />
- <attribute name="keypass" />
- <attribute name="verbose" />
- <sequential>
- <exec executable="jarsigner" failonerror="true">
- <!-- magic key -->
- <arg line="-verbose -digestalg SHA1 -sigalg MD5withRSA" />
- <arg line="-keystore @{keystore} -storepass @{storepass} -keypass @{keypass}" />
- <arg line="-signedjar "@{signedjar}"" />
- <arg line=""@{jar}" @{alias}" />
- </exec>
- </sequential>
- </macrodef>
然后将后面调用signjar的地方改为调用signjarjdk7。这个方便就方便在不用改参数,以后Ant支持digestalg和sigalg了了,改回来容易。
- <!-- <signjar -->
- <signjarjdk7
- jar="${out.packaged.file}"
- signedjar="${out.unaligned.file}"
- keystore="${key.store}"
- storepass="${key.store.password}"
- alias="${key.alias}"
- keypass="${key.alias.password}"
- verbose="${verbose}" />
本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/752398,如需转载请自行联系原作者