我们知道现在Android开发现在一般用gradle进行项目管理,所以这里就说说怎么么通过gradle配置来实现多渠道打包的问题。在讲怎么实现多渠道打包之前,先说说为什么要使用多渠道打包。比如我们开发一款app,有两个版本一个是付费版本,一个是免费的版本,这个两个个版本实现的大部分功能都是一样的但是有部分功能不一样,这时该怎么办呢,当然我们可以建两个android项目,一个付费项目,一个免费的项目,但是这个就复杂了,因为大部分的功能都是一样的啊,那我么怎么在一个项目中进行差异化的开发呢,这时就可以用到多渠道打包了。所谓的多渠道打包,说到底就是在一个项目中,通过配置gradle来实现通过不同的打包命令,编译出包含不同res和java的apk。
这里可以通过三种方式来实现差异化打包,一是BuildConfig,再就是多版本res,或者是多版本java,这里先从总得角度来看看如何在gradle中进行配置。
flavorDimensions("money")
productFlavors{
free{
//android:app_name="${app_name}"
manifestPlaceholders = [app_name: "@string/app_name"]
//getResources().getString(R.string.flovor_log)
resValue("string","flovor_log","this is free log")
//下面的常亮会被加到BuildConfig中
buildConfigField("String", "HTTP_BASE", '"https://www.baidu.com/api/release/"')
}
vip{
manifestPlaceholders = [app_name: "@string/app_name"]
resValue("string","flovor_log","this is vip log")
}
}
sourceSets{
main{
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
manifest.srcFile 'AndroidManifest.xml'
}
free{
java.srcDirs = ["money/free/src"]
}
vip{
java.srcDirs = ["money/vip/src"]
res.srcDirs = ["money/vip/res"]
}
}
以上代码由三个模块组成,一个是flavorDimensions模块,二是productFlavors模块,三是sourceSets模块,下面就分别针对这几个配置模块来说说。
1、flavorDimensions模块
这个模块定义多渠道的维度,所谓的委屈就是版本是根据什么区分的,比如这里是根据是否收钱来区分,如果再有在不同app store发布版本也有区别的话,就得再多定义一个维度了,关于维度的理解可以可以看看 Android Gradle(3)— FlavorDimensions,构建变体 这篇文章。
2、productFlavors模块
上面通过flavorDimensions模块定义个一个money维度,然后再这个模块定义了money维度下的两个渠道,一个是收费的vip渠道一个是免费的free渠道。
如果vip和free两个版本差异不大,就是改改不同字段的值什么的,或者小范围的代码差异,那么既可以在这一模块解决这些差异,由以上代码可以看出,有三种方式可以实现小范围的代码差异化。
2.1、manifestPlaceholders
由manifestPlaceholders定义的关键字,能够去替换manifest.xml中的对应值,如代码中定义的
manifestPlaceholders = [app_name: "@string/app_name"]
这里的app_name可以替换manifest.xml中的,如下配置中的app_name中的值
android:app_name="${app_name}"
2.2、resValue
由resValue中定字段,可以再java代码中使用,去替换对应资源字段的值
resValue("string","flovor_log","this is free log")
这个定义,在java代码中通过一下代码,便能够获取“this is free log”的值。
getResources().getString(R.string.flovor_log)
2.3、BuildConfig
BuildConfig的配置,通过buildConfigField这个字段来实现
buildConfigField("String", "HTTP_BASE", '"https://www.baidu.com/api/release/"')
这个配置,会在编译的时候生成一个BuildConfig.java的文件,其中就包含了一个名为HTTP_BASE的公共静态字段,其值就是这里配置的”https://www.baidu.com/api/release/”
,于是乎我们能够在java代码中通过不同渠道的BuildConfig中配置的值不一样来获取不同的值。
这个小节基本就对应着上面我们说的实现多渠道的BuildConfig方式了(虽然不仅仅是BuildConfig方式哈)。
3、sourceSets模块
如果版本之间的差异化太大了,我们总不能导出通过manifestPlaceholders 、resValue以及BuildConfig来实现,我们就希望能够有写在一个项目中写多个版本的res或者多个版本的java代码,这样以后维护代码也会容易的多,这就是我们在sourceSets模块中,干的事情了。
3.1、多res版本
实现多res版本比较简单,只需要在对应渠道中进行一下配置
res.srcDirs = ["money/vip/res"]
根据配置的路径在src同级目录下,创建money/vip/res的目录,因为在主代码中存在一套res代码,于是我们实现多渠道的时候,只需要在对应渠道资源目录中放需要同主代码不一样的res资源就行了。
3.2、多java版本
实现多res版本也是比较简单的,同样通过以下配置
java.srcDirs = ["money/vip/src"]
这个同样需要在src同级目录下创建money/vip/src目录,然后按照主分支中的对应java文件的路径继续创建对应包名路径,然后再包名路径下放对应的java文件。
这和多res版本还有差别,多res版本多渠道打包的时候会检查渠道res目录下是否有对应资源,如果有则优先使用渠道资源,没有的话就会去主项目中res目录下找资源。而多java版本在打包的时候则只会去对应渠道中找java文件,如果发现主项目中也存在同名java文件就会报错,所以多java版本的多渠道实现,如果一个版本的java文件要差异化则每个渠道的对应目录下都得放一个对应的改java文件(因为主项目中没有改java文件公用)。
这第三节就说清楚了,多渠道打包的多res版本方式和多java版本方式。