Android Nougat 与 apksigner

2,758 阅读4分钟

apksigner使用实践

apksigner是Android Build Tools从24.0.3版本引入的一个新的apk文件签名工具,用它可以替代以往一直在使用的jarsigner,而且只要apk文件的AndroidManifest声明支持的sdk范围包含24或者以上(就是安卓7.0或者以上),那么工具会自动为apk文件打入新的签名格式,名为APK Signature Scheme v2。经测试该签名方式在安卓7.0或者以上的系统上能大大的提高安卓的速度(这里可能存疑,不确定是否是新的签名格式导致的)。而且使用旧有的签名方法我这边测试到部分apk文件无法在安卓7.0的机子上安装,一般都是提示哪个文件size不对,或者签名对不上,然后我使用apksigner重新签名之后就可以了。根据这篇文章,谷歌说到新系统是兼容旧的V1的签名格式的(没有V2的签名就用V1的方式来验证),但是我的的确确遇到了安装包只有V1签名的只能在7.0以下机子安装无法在7.0或者以上机子安装的情况,谷歌了一大轮也没找到结果,所以为了确保我们的安装包能够正常的安装在各个版本的机子上,我们还是有必要对我们的包打上两个版本的签名的(这里如果是使用Android Stuidio来打包的话就可以忽略了,只要把gradle配置文件的buildToolsVersion设置到24.0.3或者以上的话(文章发表当前最新的版本为25.0.1),IDE会自动为我们打上兼容7.0的签名)。下面就将我迁移新的签名工具遇到的坑和解决方法分析给大家。

apksigner签名的命令

$ apksigner sign --ks  --ks-key-alias  --ks-pass pass: --key-pass pass: --out  
  • ks 对应build.gradle里面的SigningConfig里面的storeFile
  • ks-key-alias 对应build.gradle里面的SigningConfig里面的keyAlias
  • ks-pass 对应build.gradle里面的SigningConfig里面的storePassword
  • key-pass 对应build.gradle里面的SigningConfig里面的keyPassword

apksigner具体的参数定义和使用方法可以参考谷歌的这篇文章 其中我再提下其中2个需要注意下的参数,一个是ks-type一个是ks-provider-name,这两个字段可以通过

$ keytool -list -v -keystore *.keystore

这个命令来查看到,一般我们的keystore文件的type都是JKS的,apksigner的这个type的默认值也是JKS,所以如果是JKS的话这个参数可以不填。

要验证签名是否成功,我们可以使用以下这个命令来验证

$ apksigner verify -v apk文件路径

如果出现类似这样的提示就代表签名是兼容7.0以下和以上的。如果v2 scheme为false即代表在7.0上安装时是用旧的验证签名的方式。

$ Verifies
$ Verified using v1 scheme (JAR signing): true
$ Verified using v2 scheme (APK Signature Scheme v2): true
$ Number of signers: 1

但是第一个坑即将来临,你安装上诉签好名并对齐后的应用的时候就会提示

$ SHA-256 digest of contents did not verify

谷歌了一通,发现这个提示,原文链接

Caution: You must use zipalign at one of two specific points in the app-building process, depending on which app-signing tool you use:

  • If you use apksigner, zipalign must only be performed before the APK file has been signed. If you sign your APK using apksigner and make further changes to the APK, its signature is invalidated.
  • If you use jarsigner, zipalign must only be performed after the APK file has been signed.

因为我们对齐应用都是在签名之后,但是新的打签方式有点不一样,如果这样做的话就会破坏掉apk的信息,导致验签失败,所以我们需要把对齐的步骤提前到签名之前。 在高高兴兴的以为已经解决了问题的时候,我修改了打签对齐的流程然后安装包,结果仍然提示这个……然后我到处谷歌百度,无奈关于apksigner使用的文章几乎没有,只能自己硬着头皮去尝试找出解决方案。在几乎要放弃的时候,我突然想起最新的sdk build tools好像可以更新了,于是我打开SDK Manager将其更新到25.0.1,并将命令行apksigner的执行转到25.0.1的目录去,重启下terminal,然后重新签名、安装。然后居然安装成功了……好吧,可能是新版本修复了这个问题,可以谷歌上没有人讨论过……这个测试出来的情况都是基于小米5最新推送的7.0系统的,由于买的Pixel还没到货,等到机子到货了再测试一波看看会不会有类似的情况,如果有就可能是7.0开发板的bug了,因为我尝试过同一个包有时候可以安装的上有时候不行,有点灵异)可能他们都不用像我这样苦逼的只能用命令行来打包文件。 至此,打包工具的更新已完结。顺利的使得apk的签名兼容到所有的版本。

关于无法安装的情况补充。经过不同情况的测试,终于发现了规律,只有通过adb install来安装才会有几率出现各种验签失败的情况,如果我是把安装包先传到手机上,再在手机上直接找到安装包来安装则可以正常安装。

参考文章: