Ant和JDK7构建Android应用

 上半年用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来签名好啦!


  1. <!-- <signjar 
  2.         jar="${out.packaged.file}" 
  3.         signedjar="${out.unaligned.file}" 
  4.         keystore="${key.store}" 
  5.         storepass="${key.store.password}" 
  6.         alias="${key.alias}" 
  7.         keypass="${key.alias.password}" 
  8.         verbose="${verbose}" /> --> 
  9. <exec executable="jarsigner" failonerror="true"> 
  10.     <arg line="-verbose -digestalg SHA1 -sigalg MD5withRSA" /> 
  11.     <arg line="-keystore ${key.store} -storepass ${key.store.password} -keypass ${key.alias.password}" /> 
  12.     <arg line="-signedjar &quot;${out.unaligned.file}&quot;" /> 
  13.     <arg line="&quot;${out.packaged.file}&quot; ${key.alias}" /> 
  14. </exec> 

  虽然B方案可行,但是我不甘心,决定上网搜搜,有没有更好的解决办法。一搜之下发现,原来还真有人要求Ant为signjar任务添加digestalg和sigalg参数。不过这在1.8.2里肯定是看不到了,一年了也没见Ant有更新,也许下一个版本里会有吧。

  不过Google毕竟是强大的,当然更强大的是聪明的程序员,我还搜到了一个C方案,说起来,跟B方案异曲同工,就是定义一个叫signjarjdk7的宏,调用exec来实现——这和B方案没啥区别,只是貌似改起来方便些:


  1. <macrodef name="signjarjdk7"> 
  2.     <attribute name="jar" /> 
  3.     <attribute name="signedjar" /> 
  4.     <attribute name="keystore" /> 
  5.     <attribute name="storepass" /> 
  6.     <attribute name="alias" /> 
  7.     <attribute name="keypass" /> 
  8.     <attribute name="verbose" /> 
  9.     <sequential> 
  10.         <exec executable="jarsigner" failonerror="true"> 
  11.             <!-- magic key --> 
  12.             <arg line="-verbose -digestalg SHA1 -sigalg MD5withRSA" /> 
  13.             <arg line="-keystore @{keystore} -storepass @{storepass} -keypass @{keypass}" /> 
  14.             <arg line="-signedjar &quot;@{signedjar}&quot;" /> 
  15.             <arg line="&quot;@{jar}&quot; @{alias}" /> 
  16.         </exec> 
  17.     </sequential> 
  18. </macrodef> 

  然后将后面调用signjar的地方改为调用signjarjdk7。这个方便就方便在不用改参数,以后Ant支持digestalg和sigalg了了,改回来容易。


  1. <!-- <signjar --> 
  2. <signjarjdk7 
  3.         jar="${out.packaged.file}" 
  4.         signedjar="${out.unaligned.file}" 
  5.         keystore="${key.store}" 
  6.         storepass="${key.store.password}" 
  7.         alias="${key.alias}" 
  8.         keypass="${key.alias.password}" 
  9.         verbose="${verbose}" /> 

 本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/752398,如需转载请自行联系原作者

上一篇:《机器学习与数据科学(基于R的统计学习方法)》——2.5 读取CSV文件


下一篇:[Git] Git fetch和git pull的区别