赞
踩
这是我2018年时,在第一家公司时的需求时,开始研究的。
当需要修改apk内的文件,以此切换不同的渠道。所以需要解包和打包的操作。甚至是还考虑过出包含玩家信息的推广包,所以最后连服务器分包的功能都给做出来了。
不过万变不离其宗,掌握好基础的解包和打包就可以了。
工欲善其事必先利其器,解包与二次打包,我们需要使用以下三种工具:
ApkTool用于解包与打包。
JDK在我们重新打包之后的签名环节需要使用到。
由于APK就是个压缩包,所以我们也可以使用解压缩工具进行解压来实现解包。不过使用这种方法无法解密Manifest,需要查看或者修改Manifest还需要使用Apktool来进行实现。
如上一章所说,我们可以使用解压再压缩的方式,对包内添加文件,或者修改我们自身创建的文件。
但是,我们在压缩成新的apk之后,需要对apk进行签名。在文章最后的部分中我们会提到。
Windows不像Linux系统,会提供压缩与解压命令。如果我们需要使用命令行工具来实现分包,就需要准备Windows的压缩解压环境。
如果你是Linux系统或者Mac系统,则可以跳过这一步。
访问http://stahlworks.com/dev/index.php?tool=zipunzip
可以下载zip与unzip的程序。放到C:/windows目录下,即可在命令行中调用压缩加压指令。
# 压缩
zip -r fileName.apk ./*
# 解压
unzip -o -d /path fileName.apk
当然,你也可以在命令行中调用第三方压缩工具来实现这一目的。
如果想要生成一批apk,他们中需要修改的位置都是相同的,只有修改的内容不同。第一时间我们会想到字符串数组。
但是在命令行中是没有数组的,有的文章采用本地文件逐行读取的方法来实现。但我们也可以使用下面的方法来对数组进行模拟:
@echo off
set a[0]=1
set a[1]=2
set a[2]=3
echo The first element of the array is %a[0]%
echo The second element of the array is %a[1]%
echo The third element of the array is %a[2]%
我们对apk直接解压的操作,实际上没有完成解包的过程,只是一种投机取巧的方式。
如果我们没有删除签名相关内容,会在我们二次打包之后,签名时弹出报错:
jarsigner: java.lang.SecurityException:SHA1 digest error for META-INF/CERT.RSA
因此,我们需要在完成自己所需修改之外,还得删除包内的META-INF目录。
@echo off setlocal enabledelayedexpansion rem 拖入apk并获取其路径和文件名 echo 请拖入需要处理的apk set /p input= set apkUrl= for /f "delims=" %%i in ('dir /b %input%') do (set apkUrl=!apkUrl!%%i) set fileName=%apkUrl:.apk=% rem 解包并删除签名 if exist output rmdir /s/q output md output cd output md %fileName% unzip -o -d %fileName% %input% rmdir /s/q %fileName%\META-INF rem 修改文件打包并签名 for do ( [这里填写修改操作] cd !fileName! zip -r [your file name].apk ./* cd.. jarsigner -verbose -keystore [keystore path] -signedjar [out apk name].apk [current apk name].apk [alias name] -storepass [password] ) pause
如果你需要查看或者修改Manifest文件,甚至修改java代码,则需要使用apktool进行解包。
以前会有一个叫做Smali2JavaUI的项目,可以直接解包apk,并将smali文件转换成了java代码。但是由于年久失修,已经无法适用于新版的安卓应用了。因此,这里就不再提及。
Apktool是一个jar文件,官网是https://ibotpeaches.github.io/Apktool/
可以参考它的文档进行使用。
但是下载之后你会发现,如果直接使用命令行调用的它的命令,会单独开一个新的窗口,后面的命令行的代码不会顺利执行。
实际上它的命令其实是执行了同目录下的一个bat脚本文件,而且是加了参数的。
所以,在使用apktool时候,我比较推荐直接调用jar包,以解包为例:
java -jar -Duser.language=zh_cn -Dfile.encoding=UTF-8 apktool.jar d [file name] -o [decode path]
如果是直接下载的jar包可以不用管这一步。
我们常用的命令其实就是解包和打包:
apktool d xxx.apk
apktool b xxx
#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文件,则可以直接使用。如果是jks文件,可以经过p12文件中转,再转换成keystore文件:
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
如果没有keystore文件,可以使用keytool重新生成。这个工具应该是集成在JDK中的:
keytool -genkeypair -alias serverkey -keypass 111111 -storepass 111111 -dname "C=CN,ST=GD,L=SZ,O=haha,OU=dev,CN=haha.com" -keyalg RSA -keysize 2048 -validity 3650 -keystore server.keystore
可以以借助Android Studio进行生成。
签名需要使用jarsigner工具:
jarsigner -verbose -keystore [keystore path] -signedjar [out apk name].apk [current apk name].apk [alias name] -storepass [password]
签名结束之后,也可以进行验证:
jarsigner -verify [out apk name].apk
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。