因项目需求,需生成多个具有不同的应用图标、应用名、启动图APP,并且可以被同时安装。
之前使用过多渠道打包去给友盟生成不同的渠道包,觉得应该也可以实现上面的需求,所以在此记录一下。
具体的配置
在app:build.gradle中添加如下配置,注释比较全,就不过多介绍了
android {
...
defaultConfig {
applicationId "per.goweii.one"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0.0"
...
}
...
flavorDimensions "app"
productFlavors {
one {
// 动态替换applicationId
// AndroidManifest.xml文件中用到applicationId的地方替换为${applicationId}
// 不要把用到包名的地方也替换了,如per.goweii.one.MainActivity
applicationId "per.goweii.one"
// 动态生成常量
// 引用方法为BuildConfig.HTTP_DOMAIN
buildConfigField "String", "HTTP_DOMAIN", '"http://api.app.one/"'
buildConfigField "String", "WECHAT_APP_ID", '"WECHAT_APP_ID"'
buildConfigField "String", "WECHAT_APP_SECRET", '"WECHAT_APP_SECRET"'
// 动态生成资源文件,需要确保资源文件中没有同名资源
// 引用方式为R.string.app_name/@string/app_name
resValue "string", "app_name", "ONE"
resValue "bool", "is_show_wechat_pay", 'true'
// 动态生成AndroidManifest.xml文件引用
// 引用方法为${UMENG_CHANNEL_VALUE}
manifestPlaceholders = [
UMENG_CHANNEL_VALUE: "one",
UMENG_APP_KEY : "UMENG_APP_KEY",
]
}
two {
applicationId "per.goweii.two"
buildConfigField "String", "HTTP_DOMAIN", '"http://api.app.two/"'
buildConfigField "String", "WECHAT_APP_ID", '"WECHAT_APP_ID"'
buildConfigField "String", "WECHAT_APP_SECRET", '"WECHAT_APP_SECRET"'
resValue "string", "app_name", "TWO"
resValue "bool", "is_show_wechat_pay", 'false'
manifestPlaceholders = [
UMENG_CHANNEL_VALUE: "two",
UMENG_APP_KEY : "UMENG_APP_KEY",
]
}
}
// 动态修改打包的文件名
android.applicationVariants.all {
variant ->
variant.outputs.all {
output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// 输出apk名称为one_v1.0.0.apk
def fileName = "${variant.productFlavors[0].name}_v${defaultConfig.versionName}.apk"
outputFileName = fileName
}
}
}
}
...
dependencies {
...
// 如果资源文件替换过多,此时不建议采用上面动态生成资源文件的方式
// 建议采用动态依赖Model的形式,这种方式可以替换整套素材资源,但需确保主项目没有与Model中同名的资源
oneImplementation project(':model_res_one')
twoImplementation project(':model_res_two')
}
注意
style中第三方控件的属性不要加包名前缀,否则打非默认渠道包时会报错找不到该属性
<style name="TabLayoutDefault"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">match_parent</item> <!-- <item name="per.goweii.one:tabBackground">@color/transparent</item> --> <item name="tabBackground">@color/transparent</item> </style>
动态依赖Model
动态依赖model的依赖方式为xxxImplementation/xxxApi,及原来的依赖方式加上渠道名前缀后变小驼峰
这种方式可以替换整套素材资源,但需注意以下几点
- 主项目没有与Model中同名的资源,建议model中资源统一加上Model名前缀
- 所有资源Model中包含的资源个数应该一致,否则可能会找不到资源
- 这些资源Model中同一个需要动态替换的资源的命名需要一样,如app_icon资源,无论在哪个Model中都应命名为model_res_app_icon
AndroidManifest.xml文件中替换applicationId(per.goweii.one)为${applicationId},但不要全部替换