这几周,一直在倒腾安卓apk相关的东西,前面那一篇命令行修改apk工具就是倒腾的一个中间产物。但是命令行工具还是有它的局限性,随着作死的幅度越来越大已经无法满足我的需求了,便改用python来实现这个工具。大家可以参考这个项目来进行修改https://github.com/z16388/cs_game_lib。后面还有一些扩展的代码没有暂时加入到项目中,打算完善之后提交上去。这篇还会继续更新,可以参考后面的代码结合项目达到你的目的。

关于Apk

  apk就是一个zip,可以直接解压进行修改,这也是我前一篇中修改apk的方式。但是它不是普通的zip,需要一个签名,否则无法进行安装。但是如果直接进行解压,它里面会有一些二进制化的东西,不方便修改。这时候,我们可以使用apktool进行解包,这样得到的都是文本化的内容了。除此之外,解包比解压能得到更多的res信息,而且不需要我们手动删除签名文件夹。

Apktool

  Apktool是一个jar文件,官网是https://ibotpeaches.github.io/Apktool/。可以参考它的文档进行使用,但是会发现,命令行会变得很奇怪,而且是开了一个新的窗口,我们后面命令行的代码不会顺利执行,就很难受。后来发现,它的命令其实是执行同目录下的一个bat脚本文件,而且是加了参数的。所以,在使用apktool时候,我比较推荐直接调用jar,以解包为例。

1
java -jar -Duser.language=zh_cn -Dfile.encoding=UTF-8 apktool.jar d [file name] -o [decode path]

  我们常用的命令其实就是解包和打包:

1
2
apktool d xxx.apk
apktool b xxx

  打包之后,是没有META-INF文件夹的,可以直接签名。关于签名相关的内容可以参考:命令行修改apk工具

APK解包后的结构

  解包后的APK目录是会变的,如果进行了打包,那么回在该目录下生成一个build目录。但是基础的会有下面这些:

  • assest
  • lib
  • original
  • res
  • smali
  • unknown

  除此之外,还有文本化的manifest文件。

  想要修改app安装后的名称,可以去res/values/strings.xml,找到app_ame的字段进行修改。

  想要修改权限可以直接修改manifest文件。

  但是想要修改包名就不是那么简单的事情了,需要反编译smali文件成java,修改目录和包名在反编译回去。这个骚操作还是在计划中,暂时没有实现。

  需要注意的是,如果使用Python原生的xml库区修改安卓的xml的时候,会改变xml文件的名空间。原先满页的android名空间变成了奇怪的ag0。这个问题我还在寻找解决方案。如果完成了,那么关于权限和应用名的修改就可以实现自动化了。

  解包的代码如下,可以替换上面github项目中的解压代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#coding=utf-8
import os,os.path
from shutil import rmtree
def decode_apk(filename, decode_folder):
if os.path.exists(decode_folder):
rmtree(decode_folder)
print "删除已存在的文件夹"+decode_folder
print "开始解包"+filename+"->"+decode_folder
apktool_command = "java -jar -Duser.language=zh_cn -Dfile.encoding=UTF8 apktool.jar d " + filename + " -o " + decode_folder
os.system(apktool_command)
print "解包成功"+filename+"->"+decode_folder
def build_apk(folder, apk_out):
if os.access(apk_out,os.R_OK):
print "删除已存在的"+apk_out
os.remove(apk_out)
print "打包中"+apk_out
apktool_command = "java -jar -Duser.language=zh_cn -Dfile.encoding=UTF8 apktool.jar b " + folder + " -o " + apk_out
os.system(apktool_command)
print "打包成功"+apk_out

  脚本需要和apktool.jar在同一目录下,否则命令中需要指定路径。

关于签名

  打包后签名的方法,在这一篇里已经提到了命令行修改apk工具

  需要注意的是,keystore文件是使用eclipse生成的签名文件,算,如果你的应用是使用Android Studio生成的签名,那将是jks文件。(这可是个不错的番号啊…)

  生成jks文件:在Build菜单中,找到Generate Signed Apk选项,在弹出的窗口中选择Create new,填写相关内容,即可创建签名文件。

  如果非要使用keystore,可以使用keytool进行转换,jks文件经过p12文件中转可以转换成keystore文件,代码:

1
2
keytool -importkeystore -srckeystore xxx.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore xxx.p12
keytool -v -importkeystore -srckeystore xxx.p12 -srcstoretype PKCS12 -destkeystore xxx.keystore -deststoretype JKS

  除此之外,还可以使用keytool直接生成keystore签名。

1
keytool -genkeypair -alias serverkey -keypass 111111 -storepass 111111 -dname "C=CN,ST=GD,L=SZ,O=vihoo,OU=dev,CN=vihoo.com" -keyalg RSA -keysize 2048 -validity 3650 -keystore server.keystore