Android最新打包方式-支持V2


本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


签名机制:

V1:7.0以前默认,使用META-INF目录下三个文件,MANIFEST.MF,CERT.MF,CERT.RSA来保证apk不被修改。

MANIFEST.MF:记录apk资源中除META-INF,所有文件的Base64编码的SHA1值。防止apk资源被修改。

CERT.MF:记录MANIFEST.MF中属性值的Base64。防止MANIFEST.MF被修改。

CERT.RSA:记录通过开发者私钥对CERT.MF计算得到的签名,和开发者公钥。

解析过程是通过PackageManagerService.java和PackageParser.java对上述过程进行逆向操作。如果签名验证成功,则安装成功,否则安装失败。

V2:7.0以后默认此类型签名方式,如不处理安装时显示无证书。V1缺点在于,签名可以被清除,重新签名。

安装时,不用每次再去解压校验每个文件,只需要检验整个APK的数据摘要,发明SigningBlock插入apk修改偏移量满足zip结构要求。安装速度是V1的3倍左右。


将数据摘要、数字证书、额外属性组装成类MF文件

用私钥将MF计算得到类SF文件

将类MF文件和类SF文件,以及开发者公钥,用私钥签名成V2。

结构如下图:


V2严格限制apk不能被重新签名,否则已安装的apk,再替换安装时,检验不通过。



重签名:保证安装。环境:jdk1.8,据说jdk1.7要加入“-digestalg SHA1 -sigalg MD5withRSA”几个参数(未验证)

将apk解压,删除META-INF文件夹,重新压缩成zip格式。


v1:jarsigner -verbose -keystore  “jks路径” -storepass  “存储密码”  -keypass  “键密码”  -signedjar “输出apk 路径”  “转换apk路径”  “alias 别名”


v2:从build-tools/26.0.1左右的包里,拷贝apksigner.jar到tools文件夹内,并进入tools文件夹,执行如下命令

java -jar apksigner.jar sign  --ks “jks路径”  --ks-key-alias “alias 别名” --ks-pass pass:“存储密码”   -key-pass pass:“键密码”   --out  “输出apk 路径”  “转换apk路径” 


验证v2签名:

java -jar apksigner.jar verify -v 输出apk 路径”



实验过程:将一个包含v1和v2签名的apk重签名,在签名前后分别安装。

实验结果:

1、不签名,手机提示“无法安装”

2、v1签名后,可安装所有sdk版本的手机。说明:7.0以下手机验证v1签名通过,7.0以上手机未找到v2签名,所以也验证了v1。

2、v2签名后,结论如上。说明v1和v2签名均生效。如果只有v2签名,则7.0以下手机会报“无证书”。


2017年初,Android7.0出现新的签名机制,如果不适配将出现无签名的问题,华为Mate8最先出现,取巧的方式是将该签名机制取消(它是向下兼容的),build.gradle的release设置如下

[html]  view plain  copy
  1. release {  
  2.       // 如果要支持最新版的系统 Android 7.0  
  3.       // 这一行必须加,否则安装时会提示没有签名  
  4.       // 作用是只使用旧版签名,禁用V2版签名模式  
  5.       v2SigningEnabled false  

接上篇:Ant、Gradle、Python三种打包方式的介绍

上一组的打包机制是修改META-INF,在它的目录下面,使用python快速复制apk,并添加一个channel文件,用来读取作为项目的渠道名,显然这样做是不够严谨的,一直在关注并期待有新的方式解决这两个问题,那么walle应运而生。

其原理:在signiture block里的ID-VALUE对象添加channel-huawei,这样的键值对,再来读取渠道号即可,避免开发者修改apk造成安全问题,同时开放接口给开发者为自己业务注入新的解决方案,walle就是一例。

操作方式:

1、配置build.gradle

在位于项目的根目录 build.gradle 文件中添加Walle Gradle插件的依赖, 如下:

buildscript {
    dependencies {
        classpath 'com.meituan.android.walle:plugin:1.0.3'
    }
}

并在当前App的 build.gradle 文件中apply这个插件,并添加上用于读取渠道号的AAR

apply plugin: 'walle'

dependencies {
    compile 'com.meituan.android.walle:library:1.0.3'
}

2、如何获取渠道信息

在需要渠道等信息时可以通过下面代码进行获取

String channel = WalleChannelReader.getChannel(this.getApplicationContext());

3、如何生成渠道包

生成渠道包的方式是和assemble指令结合,可以通过传入参数决定是否生成渠道包,渠道包的生成目录存放在 build/outputs/apk/

下面是各类用法示例:

  • 生成单个渠道包 ./gradlew clean assembleRelease -PchannelList=meituan
  • 支持 productFlavors ./gradlew clean assembleMeituanRelease -PchannelList=meituan
  • 生成多个渠道包 ./gradlew clean assembleRelease -PchannelList=meituan,dianping
  • 通过渠道配置文件来生成渠道包 ./gradlew clean assembleRelease -PchannelFile=channel

渠道号设置两种方式:

第一种:在项目目录下新建一个channel文件,利用上面第4条通过配置文件生成渠道包

[html]  view plain  copy
  1. samsungapps #三星  
  2. hiapk  
  3. anzhi  
  4. xiaomi # 小米  
第二种:直接配合gradle clean assembleRelease 命令使用,采用build.gradle中原始的渠道号方式

[html]  view plain  copy
  1. productFlavors {  
  2.      official {}  
  3.      baidu {}  
  4.  }  

4、更多用法

插入额外信息

如果想插入除渠道以外的其他信息,请在生成渠道包时使用

./gradlew clean assembleRelease -PchannelList=meituan -PextraInfo=buildtime:20161212,hash:xxxxxxx

extraInfo以key:value形式提供,多个以,分隔。

注意:

  • extraInfo需要搭配channelList或者channelFile使用,plugin不支持只写入extraInfo。
  • extraInfo 不要出现以channel为key的情况

而对应的渠道信息获取方式如下:

ChannelInfo channelInfo= WalleChannelReader.getChannelInfo(this.getApplicationContext());
if (channelInfo != null) {
   String channel = channelInfo.getChannel();
   Map<String, String> extraInfo = channelInfo.getExtraInfo();
}
// 或者也可以直接根据key获取
String value = WalleChannelReader.get(context, "buildtime");

而对应的渠道信息获取方式如下:

应用签名方案APK Signature Scheme v2原理:http://tech.meituan.com/android-apk-v2-signature-scheme.html

官方地址:https://github.com/Meituan-Dianping/walle


PR:

walle最新版本是1.1.5支持flavor和walle两种配置渠道号的方式.

如果两者均存在build.gradle中,则使用gradle assembleReleaseChannels命令时,会报"Task 'assembleReleaseChannels' not found in root project".错误。

walle支持flavor,但flavor不支持walle。

如果想执行walle配置,则需要加入渠道号即gradle assembleXiaoMiReleaseChannels,则只会执行walle命令。

如果想执行flavor配置,则需要删除walle,执行gradle assembleReleaseChannels即可。 


使用walle打包,则在数据统计时需要手动加入渠道号。


walle打包优点:打包速度快。一个母包打完,修改渠道号即要生成新包。

缺点:不能灵活修改应用的logo、包名等


flavor打包优点:可以灵活修改应用信息(http://blog.csdn.net/stimgo/article/details/77480154),

缺点:需要一个个打包,速度太慢;无法用脚本批量打包。


解决加固后无渠道号的问题:https://github.com/Meituan-Dianping/walle/tree/master/walle-cli

下载完walle-cli后,在其目录下执行   java -jar walle-cli-all.jar put -c 渠道号 目标apk即可。


猜你喜欢

转载自blog.csdn.net/liuxian13183/article/details/78489821
v2