命令行打包android程序

来源:互联网 发布:java 开发云平台 编辑:程序博客网 时间:2024/05/01 00:23
因为需要记录不同渠道下apk的使用情况,每一个渠道对应的apk都需要附带自己的渠道号。而当你手动完成92个渠道的打包时,切腹的心都有了!!

现在的任务就是:实现项目的自动更改配置文件的渠道号,自动完成打包,签名工作。

开始的解决方案是,使用ant完成自动打包。据说这个方案是可行的,尝试了N多次build.xml的配置,始终运行出错,以后再慢慢研究吧。

下面详细讲解我的实现方案:
首先普及下,如何手动实现一个android项目的编译,打包,签名的过程。
为了看到效果,先把eclipse的自动编译开关去掉。
新建一个Android工程。里面除了源码什么都没有了,eclipse也没有帮你编译生成R文件和class文件。
开启命令行:
第一步:使用aapt工具生成R文件
命令行进入工程目录:
aapt package -f -m -J gen\(指定R文件存放目录) -S res\ -M AndroidManifest.xml -I ../android-8/android.jar
参数的意思应该不用解释了。执行命令,会看到再gen/目录下生成了对应资源的R文件。
第二步:使用javac编译java文件
javac -encoding utf-8 -target 1.5 -d bin/ src/../../../*.java gen/*.java -bootclasspath ../{sdk-path}/android-8/android.jar

第三步:class文件已经生成,使用dx工具将所有class打包生成dex文件。
dx.bat --dex --output=bin/classes.dex bin/classes/
如果有第三方jar包,需要将jar一并打入到dex文件中。 在命令后面再附带jar的路径。如:
dx.bat --dex --output=bin/classes.dex bin/classes/ libs/***.jar

第四步:dex已经有了,但这些都是java文件编译而成。所以还需要将对应的资源文件打包生成resources.ap_ 文件。依然使用aapt工具
aapt package -f -M AndroidManifest.xml -S res/ -A assets/ -I ../{sdk-path}/android-8/android.jar -F bin/resources.ap_
第五步:将resource和dex封装到一起。生成未签名apk文件。使用apkbuilder工具
apkbuilder bin/unsigned.apk -u -z bin/resources.ap_ -f bin/classes.dex -rf src/
如果引入了第三方jar包,还需要加入jar包的引用。在命令的最后加上: -rj libs/

第六步:对未签名的apk进行签名。使用jarsigner 工具
jarsigner -keystore {keystore path} -storepass *** -keypass {alias pass} -signedjar e:\signed.apk bin/unsigned.apk {alias name}

到此,手动对一个Android工程的编译,打包,签名就完成了。 而我的方案也就出来了。 每个不同的渠道包有一个不同的渠道属性。 可以通过文件流操作循环改变这个这个属性的值。 每次改变完成之后,在程序中调用命令,完成项目的打包签名工作。下面看具体实现:
我的项目中渠道号是写在strings.xml文件中。其实任何地方都可以,只要你的工程能引用到。
因为eclipse能够自动编译,所以我们省去了很多麻烦。不需要手动生成R文件,不需要手动编译java文件。

因为需要替换strings文件中的字段,在strings中设置一个标记变量%channel%,当读取到这个标记时,将标记替换成指定的值。先将strings文件做一个临时备份。读取临时文件,读取的同时修改渠道号并将新的文件写入到res/values/strings.xml 目录下。(读取时,因为strings文件有很多中文,注意编码问题)
下面看具体代码实现:
public static final String PROJECT_PATH = "D:\\workspace\\Idea123_v3\\"; //工程的具体路径。后面很多地方会用到

public static void main(String[] args) {
int minChannel = 10, maxChannel = 20; // 设置最小渠道,最大渠道号
try {
Process process = Runtime.getRuntime().exec("D:\\android-sdk-windows\\platform-tools\\dx.bat --dex --output="+PROJECT_PATH+"bin\\classes.dex "+PROJECT_PATH+"bin\\classes\\ +"PROJECT_PATH"+libs\\pinyin4j-2.5.0.jar" ); process.waitFor(); process.destroy(); // 先完成class--》dex的打包。因为java文件未曾改变过,所以打包一次就够。
replaceChannel(minChannel, maxChannel); // 替换渠道号
System.out.println("batch pack finished!");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) { e.printStackTrace(); } }



public static void replaceChannel(int minChannel, int maxChannel) {
try {
String outPath = PROJECT_PATH + "res\\values\\strings.xml"; //输出文件位置
String tempPath = "e:\\temp.xml"; //临时文件位置
BufferedReader reader;
BufferedWriter writer;
for (int channelid = minChannel; channelid <= maxChannel; ++channelid) {
String line = null;
reader = new BufferedReader(new FileReader(tempPath));
writer = new BufferedWriter(new FileWriter(outPath));
while ((line = reader.readLine()) != null) {
if (line.contains("%channel%"))
line = line.replace("%channel%", channelid + "");//设置渠道号
writer.write(line + "\r\n");
writer.flush();
}
writer.close();
reader.close();
generatePackage(channelid); // 一次渠道号的更改完成。可以进行打包了。
}
} catch (Exception e) {
e.printStackTrace();
}
}


public static void generatePackage(int channelid) {
try {
Process process = null ;
process = Runtime.getRuntime()
.exec("D:\\android-sdk-windows\\platform-tools\\aapt package -f -M "+PROJECT_PATH+"AndroidManifest.xml -S "+PROJECT_PATH+"res -A "+PROJECT_PATH+"assets -I D:\\android-sdk-windows\\platforms\\android-8\\android.jar -F "+PROJECT_PATH+"bin\\resources.ap_"); // 将资源文件打包resources.ap_
process.waitFor();
process.destroy();
process= Runtime.getRuntime()
.exec("D:\\android-sdk-windows\\tools\\apkbuilder.bat "+PROJECT_PATH+"bin\\Idea123_unsigned.apk -u -z "+PROJECT_PATH+"bin\\resources.ap_ -f "+PROJECT_PATH+"bin\\classes.dex -rf "+PROJECT_PATH+"src -rj "+PROJECT_PATH+"\\libs"); // 生成未签名的apk
process.waitFor();
process.destroy();
process = Runtime.getRuntime()
.exec("jarsigner -keystore E:\\idea123 -storepass *** -keypass *** -signedjar E:\\test_apk\\Idea123_"+channelid+".apk "+PROJECT_PATH+"bin\\Idea123_unsigned.apk idea123"); //对apk进行签名
process.waitFor();
process.destroy();
System.out.println(channelid+" finished..."); // 一条渠道的打包完成。文件会输出到指定目录
} catch (Exception e) {
e.printStackTrace();
}

}



android update project -p D:\GSW-1.1.0 -t "Google Inc.:Google APIs:14" -n Warriors

ant clean


D:\developsoft\android-sdk\platforms\android-14\android.jar

aapt package -f -m -J gen -S res\ -M AndroidManifest.xml -I D:\developsoft\android-sdk\platforms\android-14\android.jar

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝拉粘液大便鼻涕状的怎么办 十个月宝宝拉鼻涕一样大便怎么办 7个月宝宝咳嗽反反复复发热怎么办 婴儿3个月突然不吃奶瓶怎么办? 2个月婴儿突然不肯用奶瓶怎么办 喝母乳的宝宝不喝奶瓶怎么办 三个月宝宝不喝奶瓶母乳不够怎么办 七个多月的宝宝不吃辅食怎么办 婴儿光认奶粉不认母乳怎么办 宝宝11个月断奶不吃奶瓶怎么办 4个月的宝宝断奶不肯吃奶瓶怎么办 晚上磨牙齿把牙神经磨坏怎么办 喝母乳的宝宝不喝奶粉怎么办 我宝宝的牙齿长的不整齐怎么办? 宝宝5个月了母乳不够吃怎么办 4个月宝宝母乳不够吃怎么办 11个月宝宝只吃母乳怎么办 10个月宝宝突然不吃母乳怎么办 2个月宝宝咳嗽怎么办是吃母乳的 九个月宝宝不喜欢吃粥和米糊怎么办 9个月宝宝突然不吃辅食怎么办 宝贝8个月不吃辅食怎么办 11个月宝贝不吃辅食怎么办 十一个月宝宝长牙不吃辅食怎么办 八个多月的宝宝不爱吃辅食怎么办 7个月的宝宝不爱吃辅食怎么办 宝宝只吃母乳不吃辅食怎么办 10个月的宝宝不肯吃勺子怎么办 十一个月大宝宝不吃奶吃饭怎么办 十一个月宝宝光吃奶不吃饭怎么办 20个月宝宝爱吃奶不爱吃饭怎么办 宝宝8个多月不肯米糊跟粥怎么办 8个月宝宝突然不肯吃米糊了怎么办 八个月宝宝突然不吃辅食怎么办 八个月宝宝拉屎费劲还干怎么办 两个月的小孩不喜欢吃奶粉怎么办 三个多月的宝宝不爱吃奶怎么办 4个月的宝宝不吃奶怎么办 九个月宝宝一直高烧不退怎么办 8个月宝宝不吃辅食怎么办 孩子七个月了母乳不够了怎么办