做一个测试工具时,需要将被测应用重新签名。re-sign.jar用顺手了,想在代码中也调用它来进行重签名工作,但转念一想干嘛不在代码里把它实现了呢?
re-sign.jar工具可以将一个apk文件重签名,使用的是android自带的debug签名,也就是你在eclipse里build后在bin目录生成的apk文件的签名。
下面是它的实现原理,非常简单,就是下面两个命令:
D:\java\jdk1.6.0_43/bin/jarsigner(jarsigner工具,在JDK的bin目录下) -sigalg MD5withRSA -digestalg SHA1 -keystore C:\Users\zhuming/.android/debug.keystore(android的debug.keystore路径) -storepass android -keypass android -signedjar C:/Users/zhuming/Desktop/temp.apk(重签名后生成的临时文件,不是最终文件) C:/Users/zhuming/Desktop/source_debug.apk(要签名的apk文件路径) androiddebugkey
这个命令完成了重签名的操作。
D:\android\sdk\build-tools\19.1.0/zipalign(zipalign工具,在android SDK的build-tools目录下) -f 4 C:/Users/zhuming/Desktop/temp.apk(刚才生成的临时文件路径) C:/Users/zhuming/Desktop/source_debug.apk(目标文件路径)
这个命令对重签名后的包进行了优化,即对资源文件做了“对齐”处理,详参点击打开链接。
了解了这些,再想在代码中执行重签名操作,就非常简单了(下面是我的代码,注意使用前需要配置JAVA_HOME和ANDROID_HOME)。
public static boolean debugSignApk(String sourcePath){
if (sourcePath == null) {
return false;
}
String temp[] = sourcePath.replaceAll("\\\\","/").split("/");
String name=sourcePath;
if (temp.length > 1) {
name = temp[temp.length - 1];
}
name=name.split("_unsigned")[0]+"_debug.apk";
JDK_JARSIGNER="jarsigner";
String sign_cmd = JDK_JARSIGNER+" -sigalg MD5withRSA -digestalg SHA1 -keystore "+
ANDROID_KEYSTORE+" -storepass android -keypass android -signedjar "+"./temp.apk "+"./"+sourcePath+" androiddebugkey";
String zip_cmd="zipalign -f 4 "+"./temp.apk "+name;
try {
Process process = Runtime.getRuntime().exec(sign_cmd);
if (process != null) {
InputStream inputStream = process.getErrorStream();
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
reader.close();
inputStream.close();
process.destroy();
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
try {
Process process = Runtime.getRuntime().exec(zip_cmd);
if (process != null) {
InputStream inputStream = process.getErrorStream();
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
reader.close();
inputStream.close();
process.destroy();
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
如果不想用debug签名,而想使用自定义签名怎么办呢?见下一篇文章吧。