使用Gradle与Ant实现不同的apk的打包
说下应用场景:
公司有这样的需求:对于同一份代码,需要生成N多个不同的Apk,包括应用图标不同,启动图不同,包名不同等,而且后续业务发展,可能这些Apk的数量会越来越多,如果我们打包一个就修改一下包名,替换下图片,那这样就会显得非常的麻烦,而且公司也没有多余的人力来做这个,所以就想到了自动打包。早就想写篇博客总结下,一直拖到现在。如果你的公司也有类似的需求,那希望这篇文章会对你有用。
一、ant环境的搭建
1、下载ant压缩包:ant打包工具
2、,解压到任意盘,我电脑上是解压在D盘;
3、配置环境变量,新建一个环境变量,名为ANT_HOME,值为ant的根目录,如D:\apache-ant-1.9.3;然后在path中加入%ANT_HOME%\bin;同时还需要把sdk的tools路径配置到环境变量path中;
4、要使ant支持循环打包,需要下载ant-contrib-1.0b3.jar,这个自行去网上搜索下载,然后将其拷贝到apache-ant-1.9.3\lib目录下;
二、生成build.xml文件
可以从网上下载一个模版,也可以自己通过命令生成:cmd打开dos窗口,切换到你的项目路径,输入命令”android update project -t 2 -p .“,其中的2为androidid,可通过命令android list查看id;执行完后,你会发现在你的项目根目录下,会多出三个文件:local.properties、proguard-project.txt以及build.xml
三、根据实际情况,配置build.xml
要通过自动打包,就要能自动修改appIcon,启动图,keystore的名字(keystore的密码这里默认都是一样的,只是名字不同),如果有添加分享,那这里还会涉及到替换微信分享的WXEntryActivity以及qq分享的id等等;
以两个Apk打包为例,一个appName为demo1,包名为com.test.demo1,另一个叫demo2,包名为com.test.demo2;
1)新建一个xml文件,填入apk需要的信息,
<?xml version="1.0" encoding="UTF-8"?>
<key>
<apkInfo>
<packageName>demo1</packageName>
<alias>aliasdemo1</alias>(ps:打包用的alias)
<appName>示例1</appName>
</apkInfo>
<apkInfo>
<packageName>demo2</packageName>
<alias>aliasdemo2</alias>
<appName>示例2</appName>
</apkInfo>
</key>
保存,放到任意盘,我这里把它放到项目的根目录下;
2)在E盘新建两个个文件夹,一个为icon,用于存放app图标,一个为apkFile,用于存放打包后的apk;
在icon文件夹下新建三个文件夹,分别为mipmap-hdpi、mipmap-xdpi以及mipmap-xxdpi,然后分别在这三个文件夹下新建demo1和demo2两个apk文件夹,名称以包名最后一个字段命名,如果包名为com.test.demo1,那么就命名为demo1,接着就可以在文件夹中放入你的图标和图片了。
3)把apkInfo.xml中的数据解析,拼成字符串,填入local..properties中,这里最好写一个java程序,去解析,记住,涉及到的中文,要转化为ascii码。格式如下:
4)把gradle命令配置到环境变量,用于打包apk
在环境变量的path中加入:
5)配置build.gradle文件
*先在local.properties文件中填入appReleaseDir=E:\apkFile;
*
android {
signingConfigs {
release {
keyAlias "demo1"
keyPassword "123456"
storeFile file(
"E:/demo1.jks"
)
storePassword "123"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
//修改生成的apk名字
applicationVariants.all { variant ->
variant.outputs.each { output ->
if (variant.buildType.name.equals('release')) {
// APK输出文件名规则:aiyou-版本名-市场-release.apk
def releaseApkName = defaultConfig.applicationId + '_' + defaultConfig.versionName + '_release.apk'
// appReleaseDir对应local.properties里面定义的路径
output.outputFile = new File(appReleaseDir, releaseApkName)
}
if (variant.buildType.name.equals('beta')) {
}
if (variant.buildType.name.equals('debug')) {
}
}
}
}
6)配置build.xml文件
先贴出代码:
<project name="demo1" default="packageAPK" basedir=".">
<property name="sdk.dir" location="F:/AppData/Local/sdk" />
<property name="java.dir" location="C:/Program Files/Java/jdk1.8.0_25" />
<property name="project_org.dir" value="G:/project/demo1" />
<property name="manifest.dir" value="G:/project/demo1/app/src/main" />
<property name="strings.dir" value="G:/project/demo1/app/src/main/res/values" />
<property name="srcSplash.dir"
value="G:/project/demo1/app/src/main/java/com/test/demo1/utils" />
<property name="wxapi.dir" value="G:/project/demo1/wxdirectory" />
<property name="apk.out.dir" value="E:/apkFile" />
<property name="app.build.dir" value="G:/project/demo1/app/build" />
<property name="com.test.dir"
value="G:/project/demo1/app/src/main/java/com/test" />
<property name="gradle"
value="C:/Users/Administrator/.gradle/wapper/dists/gradle-2.2.1-all/c64ysjskjslkjlsjlkjskl0w53/gradle-2.2.1/bin/gradle.bat" />
<property name="hdpi.dir" value="G:/project/demo1/app/src/main/res/mipmap-hdpi" />
<property name="xhdpi.dir" value="G:/project/demo1/app/src/main/res/mipmap-xhdpi" />
<property name="xxhdpi.dir" value="G:/project/demo1/app/src/main/res/mipmap-xxhdpi" />
<property name="hdpi.new.dir" value="E:/icon/mipmap-hdpi" />
<property name="xhdpi.new.dir" value="E:/icon/mipmap-xhdpi" />
<property name="xxhdpi.new.dir" value="E:/icon/mipmap-xxhdpi" />
<property name="app_project.dir" value="${project_org.dir}/app" />
<property file="local.properties"/>
<!-- 使用第三方的ant包,使ant支持for循环-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="./ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<!-- 设置路径和初始化环境 -->
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
</path>
<!--循环打包 -->
<target name="deploy">
<foreach target="init" list="${key}" param="nameandchannel" delimiter=","></foreach>
</target>
<!-- 初始化 -->
<target name="init">
<propertyregex override="true" property="packageName" input="${nameandchannel}" regexp="(.*):" select="\1" />
<propertyregex override="true" property="alias" input="${nameandchannel}" regexp=":(.*)%" select="\1" />
<propertyregex override="true" property="appname" input="${nameandchannel}" regexp="%(.*)" select="\1" />
<!--复制程序图片和启动图片-->
<copy todir="${hdpi.dir}" overwrite="true">
<fileset dir="${hdpi.new.dir}/${packageName}" includes="**/*" />
</copy>
<copy todir="${xhdpi.dir}" overwrite="true">
<fileset dir="${xhdpi.new.dir}/${packageName}" includes="**/*" />
</copy>
<copy todir="${xxhdpi.dir}" overwrite="true">
<fileset dir="${xxhdpi.new.dir}/${packageName}" includes="**/*" />
</copy>
<!--修改appname-->
<replaceregexp flags="g" byline="true" encoding="UTF-8">
<regexp pattern='\x3Cstring name="app_name"\x3E(.*)' />
<substitution expression='<string name="app_name">${appname}' />
<fileset dir="${strings.dir}" includes="strings.xml" />
</replaceregexp>
<!--修改清单文件AndroidManifest文件中的包名-->
<replaceregexp flags="g" byline="false" encoding="UTF-8">
<regexp pattern='package="com.test.(.*)"' />
<substitution expression='package="com.test.${packageName}"' />
<fileset dir="${manifest.dir}" includes="AndroidManifest.xml" />
</replaceregexp>
<replaceregexp flags="g" encoding="UTF-8" byline="true">
<regexp pattern="import com.test.(.*).R;"/>
<substitution expression="import com.test.${packageName}.R;"/>
<fileset dir="${manifest.dir}/java" includes="**/*.java"/>
</replaceregexp>
<!--修改build.gradle文件中的applicationId-->
<replaceregexp flags="g" encoding="UTF-8" byline="true">
<regexp pattern='applicationId "com.test.(.*)"' />
<substitution expression='applicationId "com.test.${packageName}"' />
<fileset dir="${app_project.dir}" includes="build.gradle" />
</replaceregexp>
<!--修改build.gradle文件中的alias-->
<replaceregexp flags="g" encoding="UTF-8" byline="true">
<regexp pattern='keyAlias "(.*)"' />
<substitution expression='keyAlias "${alias}"' />
<fileset dir="${app_project.dir}" includes="build.gradle" />
</replaceregexp>
<!--修改build.gradle文件中的keystore地址-->
<replaceregexp flags="g" encoding="UTF-8" byline="true">
<regexp pattern='"E:/(.*).jks"' />
<substitution expression='"E:/${packageName}.jks"' />
<fileset dir="${app_project.dir}" includes="build.gradle" />
</replaceregexp>
<antcall target="gradleRelease" />
</target>
<!--打包编译-->
<target name="generateDebugSources">
<exec executable="${gradle}" failonerror="true">
<arg value="generateDebugSources" />
</exec>
</target>
<target name="generateDebugAndroidTestSources">
<exec executable="${gradle}" failonerror="true">
<arg value="generateDebugAndroidTestSources" />
</exec>
</target>
<target name="gradleRelease" depends="generateDebugSources,generateDebugAndroidTestSources">
<exec executable="${gradle}" failonerror="true">
<arg value="assembleRelease" />
</exec>
</target>
</project>
7)开启自动循环打包
打开cmd命令窗口,切换路径到我们的项目根目录下,输入ant deploy,回车,即可开始自动打包。
PS:准备过程可能有点麻烦,这里使用的build.xml中的命令是通过正则匹配去替换文件中的内容,可能也会有更方便的批量打包方法,没有再去想了,对于上面有不懂的可以自行网上搜索查询,应该都会找到解答的,也可以留言,共同探讨android技术。