[Gradle系列]Gradle打包apk多版本,多渠道,多环境,多功能,多模块随心所欲
来源:互联网 发布:数据库技术发展 编辑:程序博客网 时间:2024/06/06 03:43
Tamic: http://blog.csdn.net/sk719887916/article/details/53411771
开始
上篇Gradle发布Module(Maven)到jcenter, 并构建自己的企业Maven私服介绍了怎样从本地module发布自己的maven包到JCenter,包括怎样构建远程maven企业私服,既然有了自己的maven包,对于后期出包版本迭代比中相对容易控制版本,那么版本渠道等相关问题又怎么控制,尤其涉及OEM业务的公司企业定制化更加严重,一般存在以下问题?
渠道定制,比如不同厂商有不同的渠道包,出包是否一个个打包
版本控制,不同厂商不同版本,是否需要不版本不同代码
功能定制,不同厂商的apk要的功能不一样,是否需要二次开发
应用定制, 不同厂商需要的包名,appName, 业务也不一样,是否需要重新构建app
看了以上app问题,发现用一套代码是不行的,有的同学就开始从主分支拉分支了,后期版本越来越多,分支迅速增加,这时候维护成本越来越大,对于一个普通定制的Apk, 很可能只是想关闭一个开关(比如不增加推送),改起来也很快,但是从拉分支,到修改代码,到版本测试到输出包 ,到最后的移交版本,发现一来一回时间浪费太多,因此我们想到了是否有能自动化敏捷的打包机制呢,以前用的eclipse开发的很多朋友喜欢用ANt构建自己的app,将会在远程服务器部署andoid开发环境,使用本地web页面,一个按钮调用部署在远程ant脚本,执行android的bat打包命令,并将远程的code git关联上,输出具体的apk,不管是QA,Bd, Rd,PM都可以操作,无需开发自己动手打包,实际上不同厂商的需求是不一样,BD手里接手的比较全面的需求资料,这时候Bd直接通过可视化的网页来定制所有需求,并一键打包,那么今天的主题并不是教大家怎么构建自动化打包平台,今天先是解决上面的几个问题。等解决了本地基础,我们在试着搭建一个远程智能打包平台(非Jenkins)
ANT方式
在这里大致介绍下ANt流程
echo offrem =========基本参数配置============rem jdk的路径set JAVA_HOME=D:/Program Files/Java/jdk1.6.0_24rem jdk的版本set JDK_Version=1.6rem sdk的路径set AndroidHome=D:/Android/android-sdk-windowsrem 编译的android版本路径set AndroidVersion=/platforms/android-8rem 编译的android项目路径set AndroidProject=D:/yourProjectrem 编译生成的未签名apk文件set unsign_apk=yourProject.apkrem 编译生成的已签名apk文件set sign_apk=yourProject-sign.apkrem 签名用的keyset apk_key=keynameset apk_keypass=keypassset apk_keystore=D:/yourProject/key.keystorefor %%x in ("%AndroidProject%") do set AndroidProject=%%~sxfor %%x in ("%JAVA_HOME%") do set JAVA_HOME=%%~sxfor %%x in ("%AndroidHome%") do set AndroidHome=%%~sxrem jdk工具包set EXE_JAVA=%JAVA_HOME%/bin/javaset JAVAC=%JAVA_HOME%/bin/javacset JAR=%JAVA_HOME%/bin/jarset KeyTool=%JAVA_HOME%/bin/keytoolset Jarsigner=%JAVA_HOME%/bin/jarsignerrem sdk工具包set AndroidAAPT=%AndroidHome%%AndroidVersion%/tools/aapt.exeset AndroidDx=%AndroidHome%%AndroidVersion%/tools/dx.batset AndroidApkBuilder=%AndroidHome%/tools/apkbuilder.batset AndroidJar=%AndroidHome%%AndroidVersion%/android.jarrem android项目引用的扩展jar包set ExternerJar=%AndroidProject%/lib/commons-codec.jar;%AndroidProject%/lib/commons-httpclient-3.1.jar;set ReferJar=%AndroidProject%/lib/commons-codec.jar %AndroidProject%/lib/commons-httpclient-3.1.jarrem android项目基本目录及配置文件set AndroidProjectRes=%AndroidProject%/resset AndroidProjectGen=%AndroidProject%/genset AndroidProjectBin=%AndroidProject%/binset AndroidProjectAsset=%AndroidProject%/assetsset AndroidProjectAndroidMainfest=%AndroidProject%/AndroidManifest.xmlset AndroidProjectSrc=%AndroidProject%/src/weibo/*.javaset AndroidProjectSrc=%AndroidProjectSrc% %AndroidProject%/src/weibo/http/*.javaset AndroidProjectSrc=%AndroidProjectSrc% %AndroidProject%/src/weibo/util/*.javaset AndroidProjectSrc=%AndroidProjectSrc% %AndroidProject%/gen/yourProjectPackageName/*.javarem 编译输出文件set AndroidProjectClassDex=%AndroidProject%/bin/classes.dexset AndroidProjectResources=%AndroidProject%/bin/resources.ap_set AndroidProjectApk="%AndroidProject%/bin/%unsign_apk%"set AndroidProjectSignApk="%AndroidProject%/bin/%sign_apk%"echo 生成R.java%AndroidAAPT% package -f -m -J %AndroidProjectGen% -S %AndroidProjectRes% -I %AndroidJar% -M %AndroidProjectAndroidMainfest%echo 生成class%JAVAC% -encoding UTF-8 -target %JDK_Version% -bootclasspath %AndroidJar% -classpath %ExternerJar% -d %AndroidProjectBin% %AndroidProjectSrc%echo 生成dexcd %AndroidProjectBin%rem 把bin目录下*.class文件打成jar包%JAR% cvf %AndroidProjectBin%/yourProject.jar *.*cd %AndroidProject%rem 生成dex 这里需要注意,因为调用的是bat的脚本,因此必须用Callcall %AndroidDx% --dex --output=%AndroidProjectClassDex% %AndroidProjectBin%/yourProject.jar %ReferJar%echo 打包资源文件%AndroidAAPT% package -f -M %AndroidProjectAndroidMainfest% -S %AndroidProjectRes% -A %AndroidProjectAsset% -I %AndroidJar% -F %AndroidProjectResources%echo 生成未签名的apk文件call %AndroidApkBuilder% %AndroidProjectApk% -v -u -z %AndroidProjectResources% -f %AndroidProjectClassDex% -rf %AndroidProject%/srcecho 生成数字签名key.keystore%KeyTool% -genkey -v -keystore %apk_keystore% -storepass %apk_keypass% -keypass %apk_keypass% -alias myKey -dname CN=Liux,OU=makingware.com,O=makingware,L=sz,ST=gd,C=cn -keyalg RSA -validity 10000 echo 进行数字签名%Jarsigner% -verbose -keystore %apk_keystore% -keypass %apk_keypass% -storepass %apk_keypass% -signedjar %AndroidProjectSignApk% %AndroidProjectApk% myKeyecho 签名成功pause
这里介绍一篇详细的ant打包过程:点击查看Ant打包,本次我就不在介绍 > Tamic: http://blog.csdn.net/sk719887916/article/details/53224544
Gradle
渠道包 ##
对于多渠道版本,gradle提供了productFlavors
节点,
开发者可以通过以下方式制定自己的渠道包
productFlavors { c91mobile{ } c360{ } crelese{ } cdev { } cqa{ }}
上面自定义了五个渠道类型,如果你还有其他渠道可以一次加入自己的渠道名, channelname{}
,需要的来执行具体渠道命令即可。如: gradlew.bat assembleC360就是来打360的渠道包的。如果时候你需要一次性输出所有渠道的包,那么可以执行gradlew.bat build
版本控制
对于厂商版本需求,很可能遇到客户不需要最新apk情况,但是就版本的一些功能又很浪费性能,那么我们不可能用以前的版本直接输出,这时候很可能用最新apk来构建,那么我们可以不降低工程版,只需降低module版本,如果最新版本依赖的1.2.5,那么我们将本地Module(远程maven)降低版本即可。
dependencies {.....compile 'com.tamic.novate:novate:1.2.4'
}
功能定制
还有很多厂商需要的功能不一样,那么我们可以关掉一些常用的配置开关,比如推送,强制升级,启动广告等,那么可以用buildTypes
来进行实现
buildTypes { release { minifyEnabled false shrinkResources true buildConfigField "boolean", "isPush", "false" proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false shrinkResources true buildConfigField "boolean", "IsPush", "true" proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }}
这样我们就给自己的app设置了一个推送标识开关,那么java代码可以这样做:
if (BuildConfig.isPush) { /..todo }
android自己自带一些参数,包括版本号,版本名称,渠道,打包方式等
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "com.tamic.apkdemo360"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = "c360"; public static final int VERSION_CODE = 1; public static final String VERSION_NAME = "1.0"; // Fields from the variant public static final String APP_ENV = "c360 "; }
通过以上这种方式我们可以联想到其他定制需求,比如不同渠道不同服务器,线上和线下不同Url等,输出log等。
简单的可以这么做;
首先我在gradle定义一个宏,
def hostUrl = "https://github.com/Tamicer";
接着我在不同版本定义不同域
productFlavors { c91mobile{ } c360{ } crelese{ } cdev { hostUrl = "http://www.baidu.com/" } cqa{ hostUrl = "http://www.tencent.com/" }}
这样就修改了app自身hostUrl,java代码我们可以直接拿来用了,gradle也会生成一个HOST_URL字段,你想在哪儿用就在哪儿用。
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "com.tamic.apkdemo360"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = "c360"; public static final int VERSION_CODE = 1; public static final String VERSION_NAME = "1.0"; // Fields from the variant public static final String APP_ENV = "c360 "; public static final String HOST_URL = " http://www.tencent.com/"; // Fields from build type: debug public static final boolean LOG_DEBUG = true;
应用定制
除了上面的这些场景外,还有很多需要修改app名称,改包名,已经去除某些代码逻辑的,那么我看依旧可以借助gradle轻松实现
修改包名
productFlavors { c91mobile{ applicationId "com.tamic.apkdemo91" } c360{ applicationId "com.tamic.apkdemo360" } crelese{ }}
修改app名称
我们可以在代码架构层次中创建对应的资源名称和代码逻辑,修改名称和app图标的方式都一样
这样输出的apk也不一样,具体不在详细多说。
* 修改代码*
还有很多时候时候我们本地哟很多模块,但我们不想打和不想关的sdk到我们不想要这个功能的app中,简单可以这样
dependencies {compile 'com.android.support:appcompat-v7:23.2.1'compile 'com.android.support:design:23.2.1'cdevCompile 'com.tamic.novate:novate:1.2.4'testCompile 'junit:junit:4.12'}
比如我开发环境,需要对Novate这个sdk需要,其他渠道去除情况,可以建立一个对应于dev的依赖,这样其他打出包就没这个sdk,那么java代码这么处理呢,
if (BuildConfig.FLAVOR.equals("cdev")) { try { Class.forName("com.tamic.novate.Novate"); Novate novate = new Novate.Builder(MainActivity.this).build();}
如果不想这么判断,也可以在对应的dev文件加下建立java,来处理有这个sdk的逻辑,其他渠道就默认main里面代码了。
延伸
通过上面我们发现输出的apk都是同样的一个名字,难以分辨出,可以将打包类型,渠道,版本号,日期等加入进去,列如:tamic_release_360_ver1.0.0_build20160921.apk
//定制output的apk文件名applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile // 打包类型 def buildTypeName = variant.buildType.name if (outputFile != null && outputFile.name.endsWith('.apk')) { // 打包名称 def flavorName = variant.productFlavors[0].name // 版本名称 def versionName = defaultConfig.versionName // 开发环境 buildConfigField "String", "APP_ENV", "\"${flavorName} // url buildConfigField "String", "HOST_URL", "" ${hostUrl}"" // tamic_release_360_ver1.0.0_build20160921.apk def fileName = "${PRODUCT_NAME}_${buildTypeName}_${flavorName}_V${versionName}_build${BUILD_TIME_FORMAT}.apk" output.outputFile = new File(outputFile.parent, fileName) } }}
其他还有配置不同版本配置的签名,全局配置变量很多技巧,不在今天的话题之内,这里不再介绍,读者可以看看我以前的文章。
结尾
今天常规的打包技巧已全部介绍完毕,通过以上模式,大致满足企业对第三方厂商OEM需求,如果有兴趣的朋友可以再深入研究,下期介绍手把手搭建打包服务器。
第一时间获取各位大佬的技术文章和资讯请关注微信公众号!
Tamic: http://blog.csdn.net/sk719887916/article/details/53411771
- [Gradle系列]Gradle打包apk多版本,多渠道,多环境,多功能,多模块随心所欲
- Gradle 多环境、多渠道打包
- Gradle多环境多渠道打包
- Gradle多渠道多环境打包自动重命名
- Gradle多版本打包
- android studio gradle 多版本多apk打包(打包系列教程之五)
- gradle多渠道打包apk小贴士
- Gradle多渠道打包应用apk
- AndroidStudio-Gradle定制多签名多渠道打包
- 利用 Android Studio 和 Gradle 打包多版本APK( applicationIdSuffix)
- 利用 Android Studio 和 Gradle 打包多 版本APK
- 利用 Android Studio 和 Gradle 打包多版本APK
- 利用 Android Studio 和 Gradle 打包多版本APK
- AndroidStudio工程中的build.gradle中的buildTypes、productFlavors的多构建、多渠道打包APK
- Android项目构建--gradle常用知识小结与多渠道多Apk打包
- gradle多版本打包设计
- [Android]配置Gradle的productFlavors构建项目用于多渠道打包或多环境运行
- Android Studio Gradle 多渠道,多appkey签名打包
- 大小堆 排序
- 简单的来谈一谈angular2.0的表单
- Cocos2dx-CCEditBox输入框中英文检测
- 通过easy_install安装egg库遇到的问题
- 蓝桥杯 历届试题 九宫重排
- [Gradle系列]Gradle打包apk多版本,多渠道,多环境,多功能,多模块随心所欲
- Atitit.软件中见算法 程序设计五大种类算法
- 使用POI是读取excel文件中电话号码及日期出现的问题及解决
- week4_day3_JavaSE
- ibatis对数据库进行批量操作
- 叹息
- 使用 ViewPager+GridView轻松打造可分页的GridView
- 莫名湖
- mysql查询语句where后面加if判断