Android Studio多渠道打包及自动化构建
创始人
2024-05-25 22:47:39
0

Android 有不同的应用市场,也就是不同的渠道,需要为每个应用市场打一个安装包,但主要的代码是一样的,可能部分资源不一样,部分代码不一样,如果每个渠道都需要修改,然后打包,非常耗时。所以 AS 是提供了多渠道打包的。

可能遇到的需求

  1. 不同渠道 applicationId 不一样;
  2. 不同渠道配置参数不一样;
  3. 不同渠道签名文件不一样;
  4. 不同渠道资源文件不一样;
  5. 不同渠道部分代码不一样;
  6. 不同渠道依赖不一样;

这里会先说一下初级版配置,再说升级版配置—— Grovvy 进行自动化构建。

初级版多渠道配置

productFlavors :不同产品口味,就是AS自带的不同渠道打包关键字。可以进行多渠道配置,有两种方式。

1、在 app 模块下的 build.gradle 配置

// 读取不同的签名文件
def getSignProperties(filename){File signConfigFile = file("${rootProject.rootDir}/app/keystore/${filename}.properties")Properties signProperties = new Properties()signProperties.load(new FileInputStream(signConfigFile))return signProperties
}android {compileSdk 32defaultConfig {applicationId "com.XXX"minSdk 21targetSdk 32versionCode 5versionName "3.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}// 不同渠道的签名
signingConfigs {release {def signProperties = getSignProperties('signing')storeFile file(signProperties['KEYSTORE_FILE'])storePassword signProperties['KEY_PASSWORD']keyAlias signProperties['KEY_ALIAS']keyPassword signProperties['KEY_PASSWORD']}//不同的渠道,定义不同的签名文件huawei {def signProperties = getSignProperties('signing-huawei')storeFile file(signProperties['KEYSTORE_FILE'])storePassword signProperties['KEY_PASSWORD']keyAlias signProperties['KEY_ALIAS']keyPassword signProperties['KEY_PASSWORD']}xiaomi {def signProperties = getSignProperties('signing-xiaomi')storeFile file(signProperties['KEYSTORE_FILE'])storePassword signProperties['KEY_PASSWORD']keyAlias signProperties['KEY_ALIAS']keyPassword signProperties['KEY_PASSWORD']}}// 配置不同渠道参数productFlavors{huawei{applicationId ="com.xxx"//渠道参数buildConfigField "String", "token", "\"XXXX\""// manifest 读取的参数,在 manifest 里如何使用,见后文manifestPlaceholders=["app_name":"CCCCC"]}// 其他渠道类似}	// 配置打包签名buildTypes {debug {minifyEnabled falsedebuggable trueshrinkResources falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'signingConfig signingConfigs.release}release {minifyEnabled truedebuggable falseshrinkResources falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'//signingConfig signingConfigs.releaseproductFlavors.xiaoxing236.signingConfig signingConfigs.huaweiproductFlavors.xiaoxing238.signingConfig signingConfigs.xiaomi}}// 指定打包输出的路径applicationVariants.all { variant ->// 打包完成后输出路径def name = variant.flavorName +"_" + variant.buildType.name +"_" + variant.versionName +"_" + new Date().format('yyyyMMddhhmm') + ".apk"//相对路径app/build/outputs/apk/huawei/release/def path = "../../../../../apk/" //相当于路径 app/apk/variant.outputs.each { output ->def outputFile = output.outputFileif (outputFile != null && outputFile.name.endsWith('.apk') && outputFile.name.contains('release')) {//指定路径输出output.outputFileName = new File(path, name)}}}//不同渠道不同资源文件// sourceSets{ } 源文件目录设置sourceSets {// 公共代码及资源main {jniLibs.srcDirs = ['libs']}// 不同资源huawei.res.srcDirs 'src/huawei/res'xiaomi.res.srcDirs 'src/xiaomi/res'// 其他渠道类似,以下不再重复//不同代码huawei.java.srcDirs 'src/huawei/java'xiaomi.java.srcDirs 'src/xiaomi/java'// 不同渠道 manifest 文件huawei.manifest.srcFile 'src/huawei/AndroidManifest.xml'xiaomi.manifest.srcFile 'src/xiaomi/AndroidManifest.xml'}}// 不同渠道的依赖
dependencies {// 公共的依赖implementation 'ccccc'// 不同渠道依赖xiaomiApi('xxxxxxx')huaweiImplementation('xxxxxxxx')
}

不同渠道配置的参数需要在 manifest 里使用




在代码里使用 buildconfig 参数

private final String TOKEN = BuildConfig.token;

2、可以把以上不同渠道的配置单独放在一个 flavor.gradle 文件里,该文件与 setting.gradle 目录同级。 然后在 app 模块的 build.gradle 引用 flavor.gradle 文件即可。

apply from: ("${rootProject.rootDir}/flavor.gradle")

升级版渠道配置

按照以上配置方式,每增加一个渠道,就得每个渠道重新写一遍 huawei.manifest.srcFile 等这种操作,会让 build.gradle 显得非常臃肿。可以通过固定规则,写脚本解决以上问题。

1、在项目中创建出打包脚本文件夹 buildSrc,在此文件夹下创建 src/resource/**META-INF/gradle-plugins 路径及文件夹名固定。**

在这里插入图片描述

2、定义自动构建插件路径,在 src/resource/**META-INF/gradle-plugins 路径下创建一个 xxx.properties 文件,文件内定义构建脚本路径。**

// 路径是写脚本的文件路径
implementation-class=com.xxx.plugin.PackagePlugin

3、在 build.gradle 里引入相关仓库

//依赖 groovy 插件,这个是 Gradle 内置的插件
plugins {`kotlin-dsl``java-gradle-plugin`groovy
}val androidGradlePlugin = "com.android.tools.build:gradle:4.2.2"
val kotlin_version = "1.6.10"//引入相关的仓库
dependencies {// 导入androidGradlePlugin,这样buildSrc可以使用gradle相关apiimplementation(androidGradlePlugin)// Depend on the kotlin plugin, since we want to access it in our pluginimplementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}")// Depend on the default Gradle API since we want to build a custom pluginimplementation(gradleApi())implementation(localGroovy())
}

4、在主模块(app)模块的 build.gradle 中引入插件。

// plugin 的名字是第 2 步创建 properties 的名字
apply plugin: 'PackPlugin'

5、在 PackagePlugin 中开始编写自动构建脚本

编写脚本用的是 groovy 语法,可以参考这篇文章:Gradle插件从入门到进阶

class PackagePlugin : Plugin {// plugin 必须实现的方法override fun apply(target: Project) {// 获取 android extensionvar appExtension = target.extensions.getByName("android") as AppExtension// 多渠道构建appExtension.productFlavors {var channelList = getChannelList()channelList.forEach { channelModel ->register(channelModel.channelName) {// 每个渠道的需要配置的参数,可以根据自己的规则订applicationId = channelModel.packageNameversionCode = channelModel.versionCodeversionName = "${channelModel.versionCode}.0"// manifest 需要配置的参数manifestPlaceholders["ads_id"] = channelModel.adsIdmanifestPlaceholders["app_name"] = channelModel.appName// 代码里需要使用的不同渠道配置参数buildConfigField("String", "XXX", "\"${channelModel.定义的属性名}\"")buildConfigField("String", "XXX", "\"${channelModel.定义的属性名}\"")}}}// 签名文件appExtension.signingConfigs {var channelList = getChannelList()channelList.forEach { channelModel ->var channelName = channelModel.channelNameregister(channelName) {// 可以单独处理不一样的包storeFile(getKeyStoreFile(channelName, target))storePassword(channelName)keyAlias(channelName)keyPassword(channelName)}}}// 不同渠道配置不同的签名文件,签名文件的名字、别名、密码可以自行定义appExtension.signingConfigs.forEach { signingConfig ->println("PackagePlugin signing:${signingConfig.keyAlias.toString()}")appExtension.productFlavors.getByName(signingConfig.keyAlias.toString()).signingConfig =signingConfig}// 不同渠道的不同代码、资源、和 manifestappExtension.sourceSets {var channelList = getChannelList()channelList.forEach { channelModel ->var channelName = channelModel.channelNamegetByName(channelName) {res.srcDirs("src/${channelName}/res")java.srcDirs("src/${channelName}/java")manifest.srcFile("src/${channelName}/AndroidManifest.xml")}}}}}

相关内容

热门资讯

金融监管总局副局长丛林:已通过... 5月8日,金融监管总局副局长丛林在国新办新闻发布会上表示,金融监管总局协同创建信息对接共享机制。在线...
蔡姓股民向*ST沐邦发起索赔 ...   受损股民可至Hehson股民维权平台登记该公司维权:http://wq.finance.sina...
捷克央行下调基准利率至3.5% 中新网北京5月8日电 布拉格消息:捷克国家银行(央行)7日将基准利率下调25个基点至3.5%。捷克央...
宁波建工涨2.01%,成交额1... 5月8日,宁波建工盘中上涨2.01%,截至11:18,报5.57元/股,成交1.39亿元,换手率2....
天齐锂业涨2.00%,成交额3... 5月8日,天齐锂业盘中上涨2.00%,截至11:13,报29.56元/股,成交3.04亿元,换手率0...
菲艇企图侵闯我黄岩岛领海,南部... 据微信公众号“南部战区”消息,南部战区新闻发言人田军里空军大校表示,5月5日,菲35号护卫艇企图侵闯...
连平:适度宽松货币政策进一步发... 建议进一步调降政策利率0.2~0.3个百分点,设立5000亿元稳外贸专项再贷款。 5月7日,中国人民...
金智科技涨2.41%,成交额7... 5月8日,金智科技盘中上涨2.41%,截至11:23,报9.34元/股,成交7161.89万元,换手...
央行购金需求继续提供支撑 沪金... 来源:申银万国期货 作者:申银万国期货研报正文宏观消息 美联储如期按兵不动,维持联邦基金利率...
Abraxas Capital... 吴说获悉,据 @ai_9684xtpa 监测,Abraxas Capital 四小时前在 ETH 反...
菲35号护卫艇企图侵闯中国黄岩... 南部战区新闻发言人田军里空军大校表示,5月5日,菲35号护卫艇企图侵闯中国黄岩岛领海,中国人民解放军...
“拒绝”特朗普?美联储连续第三... 中新网5月8日电(宫宏宇)美东时间5月7日,美联储宣布,联邦基金利率目标区间保持4.25%至4.5%...
甘肃省平凉市泾川县汭丰镇市场监... 中国质量新闻网讯 农村假冒伪劣食品专项整治行动部署开展以来,甘肃省平凉市泾川县汭丰镇市场监督管理所高...
商络电子涨2.26%,成交额9... 5月8日,商络电子盘中上涨2.26%,截至11:08,报11.30元/股,成交9073.43万元,换...
贝仕达克涨2.13%,成交额9... 5月8日,贝仕达克盘中上涨2.13%,截至11:07,报21.58元/股,成交9205.62万元,换...
徐姓股民向*ST中程发起索赔 ...   受损股民可至Hehson股民维权平台登记该公司维权:http://wq.finance.sina...
甘肃省玉门市启动食品安全专项监... 中国质量新闻网讯 为持续强化食品安全风险防控,充分发挥监督抽检在行政执法中的技术支撑作用,近日,甘肃...
新闻发布会 | 聚焦“两持续”... 转自:陕西发布5月7日,省政府新闻办举行新闻发布会,解读省委、省政府《关于进一步深化农村改革扎实推进...
山东省在产钢铁企业全面完成全过... 按照《山东省中央生态环境保护督察整改任务验收销号工作规定》(鲁环督改办〔2022〕8号)相关规定,拟...
南部战区刚刚发声! 南部战区新闻发言人发表谈话南部战区新闻发言人田军里空军大校表示,5月5日,菲35号护卫艇企图侵闯中国...