ant多渠道自动打包咋操作
最近刚忙完了一个项目,本以为可以好好放松一下了,没想到客户提了一个变态的要求,同时要打包上线100多个渠道,需要替换图标,启动页还有一堆烦人的参数,粗略估计一个一个打包,至少两天时间,真是醉了。心中一阵草泥马飞过之后,想着自己的尾款还没到账,只能硬着头皮搞一个自动化的打包脚本。主要分为以下几大部分1、安装ant2、下载Ant-contrib3、生成build.xml4、编写ant.properties5、打开混淆开关6、编写proguard-project.txt7、执行命令ant deploy8、上传到测试发布网站蒲公英Pgyer.com - Free Publish APP|Free In-House Distribution|App Globle Testing下面来细细说说每一步:1、首先安装ant下载地址Apache Ant - Welcome不会安装的可以参考Mac中安装ANT全过程。2、Ant-contrib下载利用Ant批量打包的基本思想是,每次打包后自动替换渠道号,以及自己要替换的参数,比如本demo就要不仅要替换渠道号,一些参数,还要替换图标和启动页面。这样带来了一个问题:Ant不支持循环,怎样循环打包?扩展包Ant-contrib能轻松解决这个问题可以翻墙的同学可以到http://ant-contrib.sourceforge.net/自行下载,或者去我的云空间下载http://frankli.qiniudn.com/ant-contrib-1.0b3.jar,下载后直接把ant-contrib-1.0b3.jar放到Ant的lib文件夹即可。3、生成并改写build.xml 执行如下命令android update project --name textbyfrank -t 1 -p /Users/frank/Documents/workspace/testbyfrank此命令在当前的工程目录生成build.xml, -t 表示targetid 可以通过android list targets查看 -p 指定工程目录修改build.xml 直接上部分主要代码\u0026lt;!-- 使用第三方的ant包,使ant支持for循环 --\u0026gt; \u0026lt;taskdef resource="net/sf/antcontrib/antcontrib.properties" \u0026gt; \u0026lt;classpath\u0026gt; \u0026lt;!-- ant存放路径,自己对应修改 --\u0026gt; \u0026lt;pathelement location="/usr/local/ant/lib/ant-contrib-1.0b3.jar" /\u0026gt; \u0026lt;/classpath\u0026gt; \u0026lt;/taskdef\u0026gt; \u0026lt;target name="deploy" \u0026gt; \u0026lt;foreach delimiter="," list="${market_channels}" param="item_channel" target="modify_manifest" \u0026gt; \u0026lt;/foreach\u0026gt; \u0026lt;/target\u0026gt; \u0026lt;target name="modify_manifest" \u0026gt; \u0026lt;!-- 要替换应用程序名称,学校id参数,还有渠道(\\u65B0\\u77E5:60-xinzhi用:和-分割) --\u0026gt; \u0026lt;propertyregex input="${item_channel}" property="app_name" regexp="(.*):" select="\\1" /\u0026gt; \u0026lt;propertyregex input="${item_channel}" property="app_school" regexp=":(.*)-" select="\\1" /\u0026gt; \u0026lt;propertyregex input="${item_channel}" property="app_channel" regexp="-(.*)" select="\\1" /\u0026gt; \u0026lt;replaceregexp byline="false" encoding="utf-8" flags="g" \u0026gt; \u0026lt;!-- 替换渠道 --\u0026gt; \u0026lt;regexp pattern="android:name=\u0026amp;quot;UMENG_CHANNEL\u0026amp;quot; android:value=https://www.zhihu.com/u0026amp;quot;(.*)/u0026amp;quot;" /\u0026gt; \u0026lt;substitution expression="android:name=\u0026amp;quot;UMENG_CHANNEL\u0026amp;quot; android:value=https://www.zhihu.com/u0026amp;quot;${app_channel}/u0026amp;quot;" /\u0026gt; \u0026lt;fileset dir="" includes="AndroidManifest.xml" /\u0026gt; \u0026lt;/replaceregexp\u0026gt; \u0026lt;replaceregexp byline="false" encoding="utf-8" flags="g" \u0026gt; \u0026lt;!-- 替换学校参数id --\u0026gt; \u0026lt;regexp pattern="android:name=\u0026amp;quot;YJ_XUEXIAO_SCID\u0026amp;quot; android:value=https://www.zhihu.com/u0026amp;quot;(.*)/u0026amp;quot;" /\u0026gt; \u0026lt;substitution expression="android:name=\u0026amp;quot;YJ_XUEXIAO_SCID\u0026amp;quot; android:value=https://www.zhihu.com/u0026amp;quot;${app_school}/u0026amp;quot;" /\u0026gt; \u0026lt;fileset dir="" includes="AndroidManifest.xml" /\u0026gt; \u0026lt;/replaceregexp\u0026gt; \u0026lt;replaceregexp byline="false" encoding="utf-8" flags="g" \u0026gt; \u0026lt;!-- 替换应用程序名称 --\u0026gt; \u0026lt;regexp pattern="name=\u0026amp;quot;app_name\u0026amp;quot;\u0026gt;(.*)\u0026amp;lt;/string\u0026gt;" /\u0026gt; \u0026lt;substitution expression="name=\u0026amp;quot;app_name\u0026amp;quot;\u0026gt;${app_name}\u0026amp;lt;/string\u0026gt;" /\u0026gt; \u0026lt;fileset dir="res/values" includes="strings.xml" /\u0026gt; \u0026lt;/replaceregexp\u0026gt; \u0026lt;delete file="res/drawable-hdpi/ic_launcher.png" /\u0026gt; \u0026lt;delete file="res/drawable-hdpi/splash.png" /\u0026gt; \u0026lt;!-- 从工程目录的logo文件夹下拷贝应用图标,图片名为${app_school}.png --\u0026gt; \u0026lt;copy tofile="res/drawable-hdpi/ic_launcher.png" \u0026gt; \u0026lt;fileset dir="logo" includes="${app_school}.png" /\u0026gt; \u0026lt;/copy\u0026gt; \u0026lt;!-- 从工程目录的splash文件夹下拷贝应用启动页图片,图片名为${app_school}.png --\u0026gt; \u0026lt;copy tofile="res/drawable-hdpi/splash.png" \u0026gt; \u0026lt;fileset dir="splash" includes="${app_school}.png" /\u0026gt; \u0026lt;/copy\u0026gt; \u0026lt;!-- \u0026lt;property name="out.release.file" value="https://www.zhihu.com/api/v4/questions/27167297/${out.absolute.dir}/${channel}.apk"/\u0026gt; --\u0026gt; \u0026lt;antcall target="release" /\u0026gt; \u0026lt;!-- 批量打包生成的apk文件位置 --\u0026gt; \u0026lt;copy tofile="${gos.path}/weixiao_${app_channel}.apk" \u0026gt; \u0026lt;fileset dir="${out.absolute.dir}/" includes="weixiao-release.apk" /\u0026gt; \u0026lt;/copy\u0026gt; \u0026lt;delete includeEmptyDirs="true" \u0026gt; \u0026lt;fileset dir="${out.absolute.dir}" includes="**/*" /\u0026gt; \u0026lt;/delete\u0026gt; \u0026lt;echo message="===========================" /\u0026gt; \u0026lt;/target\u0026gt; \u0026lt;property file="local.properties" /\u0026gt; \u0026lt;property name="sdk.dir" value="https://www.zhihu.com////Users////frank////Downloads////adt-bundle-mac-x86_64-20140321////sdk" /\u0026gt; \u0026lt;!-- 配置Android SDK路径 windows --\u0026gt; \u0026lt;property name="has.keystore" value="https://www.zhihu.com/api/v4/questions/27167297/true" /\u0026gt; \u0026lt;!-- 打包是否需要签名 --\u0026gt; \u0026lt;property name="has.password" value="https://www.zhihu.com/api/v4/questions/27167297/true" /\u0026gt; \u0026lt;!-- 签名是否需要密码 --\u0026gt; \u0026lt;property file="project.properties" /\u0026gt; \u0026lt;!-- 加载sdk version --\u0026gt; \u0026lt;property name="key.store" value="https://www.zhihu.com/api/v4/questions/27167297/xiaoqu_key" /\u0026gt; \u0026lt;!-- 签名文件位置,build.xml同目录下 --\u0026gt; \u0026lt;property name="key.alias" value="https://www.zhihu.com/api/v4/questions/27167297/nearby" /\u0026gt; \u0026lt;!-- 签名标识 --\u0026gt; \u0026lt;property name="key.store.password" value="https://www.zhihu.com/api/v4/questions/27167297/pass123$" /\u0026gt; \u0026lt;!-- 签名的密码 --\u0026gt; \u0026lt;property name="key.alias.password" value="https://www.zhihu.com/api/v4/questions/27167297/pass123$" /\u0026gt; \u0026lt;!-- 签名的密码 --\u0026gt; \u0026lt;property name="proguard.enabled" value="https://www.zhihu.com/api/v4/questions/27167297/true" /\u0026gt; \u0026lt;!-- 是否混淆 --\u0026gt; \u0026lt;property name="proguard.config" value="https://www.zhihu.com/api/v4/questions/27167297/proguard.cfg" /\u0026gt; \u0026lt;!-- 混淆文件位置,build.xml同目录 —\u0026gt;4、生成ant.properties 内容如下:market_channels是用来替换的参数以:和-分割。 java.encoding=utf-8 out.absolute.dir=/Users/frank/Documents/publish_testbyfrank gos.path=/Users/frank/Documents/publish_testbyfrank_bin proguard.config=proguard.cfg app_version=1.5 market_channels=\\u65B0\\u77E5:60-xinzhi,\\u897F\\u5149:18-xiguang5、project.properties文件中打开混淆代码,去掉下面所在行的##proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt6、编写proguard-project.txt由于我的项目中用到的第三方库比较多,所以我粘贴了个比较全的,自己可以根据工程中使用到的库自行删减-optimizationpasses 5 # 指定代码的压缩级别-dontusemixedcaseclassnames -dontskipnonpubliclibraryclassmembers # 是否使用大小写混合-dontskipnonpubliclibraryclasses -dontpreverify # 混淆时是否做预校验-dontshrink-dontoptimize-verbose # 混淆时是否记录日志-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法-keep public class * extends android.app.Activity # 保持哪些类不被混淆-keep public class * extends android.app.Application # 保持哪些类不被混淆-keep public class * extends android.app.Service # 保持哪些类不被混淆-keep public class * extends android.content.BroadcastReceiver # 保持哪些类不被混淆-keep public class * extends android.content.ContentProvider # 保持哪些类不被混淆-keep public class * extends android.app.backup.BackupAgentHelper # 保持哪些类不被混淆-keep public class * extends android.preference.Preference # 保持哪些类不被混淆-keep public class com.android.vending.licensing.ILicensingService # 保持哪些类不被混淆-keepclasseswithmembernames class * { # 保持 native 方法不被混淆 native \u0026lt;methods\u0026gt;;}-keepclasseswithmembers class * { # 保持自定义控件类不被混淆 public \u0026lt;init\u0026gt;(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembers class * { public \u0026lt;init\u0026gt;(android.content.Context, android.util.AttributeSet, int); # 保持自定义控件类不被混淆}-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆 public void *(android.view.View);}-keepclassmembers enum * { # 保持枚举 enum 类不被混淆 public static ** values(); public static ** valueOf(java.lang.String);}-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆 public static final android.os.Parcelable$Creator *;}-libraryjars libs/Android_Location_V1.1.0.jar-libraryjars libs/Android_Map_2.2.0.jar-libraryjars libs/Android_Services_2.2.0.jar-libraryjars libs/android-async-http-1.4.3.jar-libraryjars libs/android-support-v4.jar-libraryjars libs/asmack-2010.05.07.jar-libraryjars libs/gson-2.2.4.jar-libraryjars libs/httpmime-4.1.3.jar-libraryjars libs/jpush-sdk-release1.6.1.jar-libraryjars libs/pinyin4j-2.5.0.jar-libraryjars libs/Android_Location_V1.1.0.jar-libraryjars libs/SocialSDK_QQZone_1.jar-libraryjars libs/SocialSDK_QQZone_2.jar-libraryjars libs/SocialSDK_Shake_Lib.jar-libraryjars libs/SocialSDK_tencentWB_1.jar-libraryjars libs/SocialSDK_tencentWB_2.jar-libraryjars libs/SocialSDK_WeiXin.jar-libraryjars libs/stackblur.jar-libraryjars libs/umeng_sdk.jar-libraryjars libs/umeng_social_sdk.jar-libraryjars libs/weibo.sdk.android.sso.jar-libraryjars libs/zxing.jar-libraryjars libs/Android_Location_V1.1.0.jar-dontwarn cn.jpush.**-keep class cn.jpush.** { *; }-keep class com.umeng.socialize.sensor.**-keep class com.umeng.scrshot.**-keep public interface com.umeng.socialize.sensor.**-keep public interface com.umeng.scrshot.** -dontwarn com.umeng.**-dontwarn org.apache.commons.**-dontwarn com.tencent.weibo.sdk.**-keepattributes *Annotation*-keep class com.umeng*.** {*; }-keep public class .R$*{ public static final int *;}-keep class com.tencent.open.TDialog$*-keep class com.tencent.open.TDialog$* {*;}-keep class com.tencent.open.PKDialog-keep class com.tencent.open.PKDialog {*;}-keep class com.tencent.open.PKDialog$*-keep class com.tencent.open.PKDialog$* {*;}-keep class com.tencent.mm.sdk.openapi.WXMediaMessage {*;}-keep class com.tencent.mm.sdk.openapi.** implements com.tencent.mm.sdk.openapi.WXMediaMessage$IMediaObject {*;}-dontwarn com.hp.**-keep class com.hp.**{*;}-dontwarn com.amap.**-keep class com.amap.**{*;}-dontwarn org.apache.**-keep class org.apache.**{*;}-dontwarn com.weibo.**-keep class com.weibo.**{*;}-dontwarn com.enrique.stackblur.**-keep class com.enrique.stackblur.**{*;}#android-async-http-dontwarn com.loopj.android.http.**-keep class com.loopj.android.http.**{*;}#gson-dontwarn com.google.**-keep class com.google.**{*;} #wheel UI库-keep class kankan.wheel.**{*;}##---------------Begin: proguard configuration for Gson ----------# Gson uses generic type information stored in a class file when working with fields. Proguard# removes such information by default, so configure it to keep all of it.-keepattributes Signature# For using GSON @Expose annotation-keepattributes *Annotation*# Gson specific classes-keep class sun.misc.Unsafe { *; }#-keep class com.google.gson.stream.** { *; }# Application classes that will be serialized/deserialized over Gson-keep class com.yunjuxiaoqu.model.**{*;}-keep class com.yj.model.**{*;}##---------------End: proguard configuration for Gson -----------dontwarn com.google.**-keep class com.google.**{*;}-dontwarn com.tencent.**-keep class com.tencent.**{*;}-dontwarn com.umeng.**-keep class com.umeng.**{*;}-dontwarn com.zxing.**-keep class com.zxing.**{*;}-dontwarn com.support.v4.**-keep class com.support.v4.**{*;}-dontwarn de.measite.**-keep class de.measite.**{*;}-dontwarn com.kenai.**-keep class com.kenai.**{*;}-dontwarn com.novell.**-keep class com.novell.**{*;}-dontwarn org.xbill.**-keep class org.xbill.**{*;}-dontwarn org.jivesoftware.**-keep class org.jivesoftware.**{*;}-dontwarn java.awt.**-keep class java.awt.**{*;}-dontwarn javax.swing.**-keep class javax.swing.**{*;}-dontwarn me.maxwin.**-keep class me.maxwin.**{*;}-dontwarn net.soureceforge.pinyin4j.**-dontwarn demo.**-keep class net.sourceforge.pinyin4j.**{*;}-keep class demo.**{*;}-dontwarn android.net.http.**-keep class android.net.http.**{*;}7、执行命令ant deploy 完成后在目录/Users/frank/Documents/publish_testbyfrank_bin下生成了两个apktestbyfrank_xiguang.apk 和testbyfrank_xinzhi.apk8、上传到蒲公英网站Pgyer.com - Free Publish APP|Free In-House Distribution|App Globle Testing上这个是测试应用的分发神器呀,你可以上传测试期的ipa和apk,测试人员和客户只需要扫描二维码就可以安装,随时随地的给让客户了解项目的最新进展,而且上传下载速度超快,真心不错,强烈赞一个!!!终于大功告成,小手好冰凉呀,冬天到了,大家还要注意多多保暖。自己抽离出来的demo已经经过我的测试没有问题,大家可以通过http://frankli.qiniudn.com/testbyfrank.zip下载示例代码。注意事项及可能遇到的问题1.工程如果引用到其它类库工程,请先生成类库的build.xml2.如果提示invalid resource directory name: /Users/frank/Documents/workspace/appcompat_v7/bin/res/crunch等类似的错误请先手动删除bin目录,重新执行ant deploy命令3.如果出现Can\u0026#39;t read (No such file or directory)类似的错误,表明你没有用到这个类库,请在混淆文件中去掉对应的即可。4.如果xml文件有用到自定义的控件,对应的java文件不能混淆5.如果用的gson的库,对应的实体类不可以混淆。
■网友
推荐阅读
- 环球车讯网|新款领克01起售价17.98万元,自动驾驶辅助等级达到L2+
- 汽车知识|第八代高尔夫到底值不值得买?1.4T自动Pro版全款多少钱?
- 学的自动化却对IT比较感兴趣。。感觉对自己的专业帮助不大,好苦恼,要不要继续是专精还是学点感兴趣的?
- 汽车知识|现代拼了,自动挡6.59万开回家,比普桑皮实,不给飞度留机会
- 中年|如果汽车亏电:自动挡汽车能「推车点火」吗?
- ETtoday生活方式|离手侦测升级!自动辅助驾驶启动 双手请老实握好方向盘
- 被硬盘录像机自动删除的监控视频还能找回来了吗
- 特斯拉|特斯拉将全面发布全自动驾驶软件最新版,曾承诺年底实现完全无人干预
- 自动化专业在大学四年可以做些啥来丰富自己的的简历
- 趣头条|12.28万元起 铃拓皮卡自动挡车型上市
