android 多渠道相关

http://www.jianshu.com/p/533240d222d3

Logo写文章 注册登录

首页

下载App

×

Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)

96 Wing_Li 关注

2016.08.16 10:51* 字数 1606 阅读 10163评论 68喜欢 131赞赏 2

如果本文帮助到你,本人不胜荣幸,如果浪费了你的时间,本人深感抱歉。

希望用最简单的大白话来帮助那些像我一样的人。如果有什么错误,请一定指出,以免误导大家、也误导我。

本文来自:http://www.jianshu.com/users/320f9e8f7fc9/latest_articles

感谢您的关注。

最近有个需求一次要打包9个类型的App,而且常量和String.xml都有变量。虽然之前也是一直存在变量,但是每次也仅仅只打包一个。这让我每次改变量,打包9个。要是以后每次都打包9次,我得疯了。

根据之前的了解,gradle 应该是可以解决这个问题的。所以就仔细研究了一番。

先放一个完整的 多渠道/多环境 打包的配置,然后再来讲解。

实现了:

不同环境,不同包名;

不同环境,修改不同的 string.xml 资源文件;

不同环境,修改指定的常量;

不同环境,修改 AndroidManifest.xml 里渠道变量;

不同环境,引用不同的 module。

先放一个完整的配置,可以参考:

apply plugin: 'com.android.application'

android {

compileSdkVersion 22

buildToolsVersion '22.0.1'

// 签名文件

signingConfigs {

config {

keyAlias 'lyl'

keyPassword '123456'

storeFile file('../lyl.jks')

storePassword '123456'

}

}

// 默认配置

defaultConfig {

//applicationId "com.lyl.app"

minSdkVersion 16

targetSdkVersion 22

versionCode 1

versionName "1.0.0"

signingConfig signingConfigs.config

multiDexEnabled true

}

// 多渠道/多环境 的不同配置

productFlavors {

dev {

// 每个环境包名不同

applicationId "com.lyl.dev"

// 动态添加 string.xml 字段;

// 注意,这里是添加,在 string.xml 不能有这个字段,会重名!!!

resValue "string", "app_name", "dev_myapp"

resValue "bool", "isrRank", 'false'

// 动态修改 常量 字段

buildConfigField "String", "ENVIRONMENT", '"dev"'

// 修改 AndroidManifest.xml 里渠道变量

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "dev"]

}

stage {

applicationId "com.lyl.stage"

resValue "string", "app_name", "stage_myapp"

resValue "bool", "isrRank", 'true'

buildConfigField "String", "ENVIRONMENT", '"stage"'

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "stage"]

}

prod {

applicationId "com.lyl.prod"

resValue "string", "app_name", "myapp"

resValue "bool", "isrRank", 'true'

buildConfigField "String", "ENVIRONMENT", '"prod"'

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "prod"]

}

}

dexOptions {

incremental true

// javaMaxHeapSize "4g"

}

//移除lint检测的error

lintOptions {

abortOnError false

}

def releaseTime() {

return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))

}

buildTypes {

debug {

signingConfig signingConfigs.config

}

release {

buildConfigField("boolean", "LOG_DEBUG", "false")

minifyEnabled false

zipAlignEnabled true

//移除无用的resource文件

shrinkResources true

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

signingConfig signingConfigs.config

// 批量打包

applicationVariants.all { variant ->

variant.outputs.each { output ->

def outputFile = output.outputFile

if (outputFile != null && outputFile.name.endsWith('.apk')) {

//输出apk名称为:渠道名版本名时间.apk

def fileName = "${variant.productFlavors[0].name}v${defaultConfig.versionName}${releaseTime()}.apk"

output.outputFile = new File(outputFile.parent, fileName)

}

}

}

}

}

}

repositories {

mavenCentral()

}

dependencies {

compile 'com.facebook.android:facebook-android-sdk:4.0.0'

compile project(':qrscan')

compile 'com.android.support:appcompat-v7:22.0.0'

compile 'com.google.code.gson:gson:2.3'

compile files('libs/android-async-http-1.4.6.jar')

compile 'com.google.android.gms:play-services:7.5.0'

compile 'com.android.support:support-annotations:22.1.1'

compile 'com.github.bumptech.glide:glide:3.7.0'

compile 'de.hdodenhof:circleimageview:2.1.0'

}

接下来我们来详细看看修改特定的字段。

不同环境的设置基本都是在 productFlavors 里设置的,

而且在里面你想添加多少个环境都可以。

1. 不同环境,不同包名;

productFlavors {

dev {

applicationId "com.lyl.dev"

}

stage {

applicationId "com.lyl.stage"

}

prod {

applicationId "com.lyl.prod"

}

}

这里注意,在 defaultConfig 中,大家应该都是写了个默认的 applicationId 的。

经测试,productFlavors 设置的不同环境包名会覆盖 defaultConfig 里面的设置,

所以我们可以推测,它执行的顺序应该是先执行默认的,然后在执行分渠道的,如果冲突,会覆盖处理,这也很符合逻辑。

<br />

2. 不同环境,添加 string.xml 资源文件;

利用 resValue 来定义资源的值,顾名思义 res 底下的内容应该都可以创建,最后用 R.xxx.xxx 来引用。

如下就根据不同的类型,添加了不同的 app_name 字段,以及定义了 布尔值,可以通过 R.string.app_name 来引用。

注意,这里是添加,是在 string.xml 里面添加了一个字段app_name,所以在现有的 string.xml 中不能有这个字段,否则会报错!!!

productFlavors {

dev {

resValue "string", "app_name", "dev_myapp"

resValue "bool", "isrRank", 'false'

}

stage {

resValue "string", "app_name", "stage_myapp"

resValue "bool", "isrRank", 'true'

}

prod {

resValue "string", "app_name", "myapp"

resValue "bool", "isrRank", 'true'

}

}

通过以上我们大概可以推测出 color、dimen 也可以通过类似的方法添加。

<br />

3. 不同环境,动态修改指定的常量;

使用 BuildConfig 的变量。

①定义字段

当我们定义如下字段之后,编译后自动生成文件,在 app/build/source/BuildConfig/dev/com.lyl.dev/BuildConfig 目录,

打开这个文件,我们就能看到我们所定义的字段了。

productFlavors {

dev {

buildConfigField "String", "ENVIRONMENT", '"dev"'

}

stage {

buildConfigField "String", "ENVIRONMENT", '"stage"'

}

prod {

buildConfigField "String", "ENVIRONMENT", '"prod"'

}

}

②引用字段

在我们自己的任意的类中,来直接通过 BuildConfig 就可以调用我们定义的字段。

public class Constants {

public static final String ENVIRONMENT = BuildConfig.ENVIRONMENT;

}

注意:这里有个小细节,看其中第三个参数,是先用了“'”,然后在用了“"”,这种语法在 Java 里可能比较陌生,但是在很多其他语言中,这种用法是很常见的。

它的意思是 "dev" 这个整体是属于一个字符串,至于为什么要这么写,你把单引号去掉,然后去 app/build/source/BuildConfig/dev/com.lyl.dev/BuildConfig 这个文件看一看就知道了。

<br />

4. 不同环境,修改 AndroidManifest.xml 里渠道变量

①在 AndroidManifest.xml 里添加渠道变量

<application

android:icon="${app_icon}"

android:label="@string/app_name"

android:theme="@style/AppTheme">

...

<meta-dataa

android:name="UMENG_CHANNEL"

android:value="${ENVIRONMENT}" />

...

</application>

②在 build.gradle 设置 productFlavors

productFlavors {

dev {

manifestPlaceholders = [ENVIRONMENT: "dev",

app_icon : "@drawable/icon_dev"]

}

stage {

manifestPlaceholders = [ENVIRONMENT: "stage",

app_icon : "@drawable/icon_stage"]

}

prod {

manifestPlaceholders = [ENVIRONMENT: "prod",

app_icon : "@drawable/icon_prod"]

}

}

这样我们可以在不同环境使用不同的 key 值。

<br />

5. 不同环境,引用不同的 module

这个就很强大了,根据不同的环境,引用对应的 module。

你可以替换大量的图片,string,color,vaule等等。

首先,要建立跟渠道对应的 module,然后再引用。

引用方式如下:

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

// 引用本的项目

devCompile project(':devModule')

stageCompile project(':stageModule')

prodCompile project(':prodModule')

// 也可以分渠道引用网络的。因为这里都相同,所以地址也就都一样了

devCompile 'com.roughike:bottom-bar:2.0.2'

stageCompile 'com.roughike:bottom-bar:2.0.2'

prodCompile 'com.roughike:bottom-bar:2.0.2'

}

xxxCompile 代表 各个渠道的名称。

然后把需要分渠道的文件,放到不同的 module 里面,把主项目的文件删掉。

千万注意:如果这样做了,每次需要引用的时候,在各个渠道的 module 里面都必须要放置文件哦,不然会找不到资源。

通过这种方式可以替换整套素材资源,具体如何使用还得看项目需求。

<br />

<br />

通过以上方式,我们基本可以 通过 gradle 动态设定应用标题,应用图标,替换常量,设置不同包名,更改渠道等等。

打包编译

最后,做完所有的配置之后,然后就是打包操作了。

打包某一个(日常编译)

因为 buildTypes 里面有两种,所以每个渠道都会有两种模式。

打包所有的,就是正常打包流程

如图所示:

图片来源网络

图片来源网络

图片来源网络

图片来源网络

<br />

打包完成之后,然后就可以在我们指定的目录下,看到我们所生成的apk包。

使用 local.properties 存放私密配置

以上就可以基本实现 gradle 的设置,但是如果我们要将我们的项目上传到 Github ,或者要将项目发送给别人。上面有些私密的东西就会被别人看到。比如:.jks 文件的密码。

在项目跟目录下,有个 local.properties 文件,我们可以使用它来存放一些私密的属性,然后在 gradle 中读取,而 local.properties 文件不需要上传。

local.properties 文件里设置如下:

sdk.dir=D:\Android\android-sdk

gaodeKey=e348025dd034d1c347dd0345e34802

keyPassword=123456

在 build.gradle 读取 local.properties 字段信息

// 加载 local.properties 资源

Properties properties = new Properties()

InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream() ;

properties.load( inputStream )

android {

...

// 签名文件

signingConfigs {

config {

keyAlias 'lyl'

// 获取 local.properties 字段信息

keyPassword properties.getProperty( 'keyPassword' )

storeFile file('../lyl.jks')

storePassword properties.getProperty( 'keyPassword' )

}

}

...

}

这样就可以将自己想要隐藏的一些数据隐藏起来。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 简介;夜,大风盘旋回绕,黑云压城,银色闪电穿梭其中,经久不落,风雨欲来! 宁王府,艳红灯笼染成血色,大红喜布风中凋...
    八千万1阅读 565评论 0 1
  • 关于作者 罗伯特·弗里茨(Robert Fritz),世界著名的创造力研究大师。他是著名的音乐家,开创了关于创造的...
    陋室鳴阅读 549评论 0 0
  • 我在想着,作为一个二十多岁的人,如果我的生活过得像老年人一样规律,我大概是很心满意足的,每年总结的时候会心一笑,写...
    吴端端阅读 1,411评论 2 0
  • 此属性已经被废除,虽然到目前为止仍然有浏览器支持这个属性,但是不再建议使用此属性,建议使用 clip-path (...
    ghwaphon阅读 3,009评论 0 8