[Android开发笔记]多渠道打包(动态替换包名、常量、资源文件等)

因项目需求,需生成多个具有不同的应用图标、应用名、启动图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')
}

注意

  1. 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>
    
  2. 动态依赖Model

    动态依赖model的依赖方式为xxxImplementation/xxxApi,及原来的依赖方式加上渠道名前缀后变小驼峰

    这种方式可以替换整套素材资源,但需注意以下几点

    • 主项目没有与Model中同名的资源,建议model中资源统一加上Model名前缀
    • 所有资源Model中包含的资源个数应该一致,否则可能会找不到资源
    • 这些资源Model中同一个需要动态替换的资源的命名需要一样,如app_icon资源,无论在哪个Model中都应命名为model_res_app_icon
  3. AndroidManifest.xml文件中替换applicationId(per.goweii.one)为${applicationId},但不要全部替换

猜你喜欢

转载自blog.csdn.net/weixin_33948416/article/details/87012784