gradle构建多渠道包(多applicationId,多图标,多app名称)

如何利用同一套代码,要打包不同applicationId,不同图标,不同包名,不同启动页等?此时就需要用到构建神器-gradle。
先上代码

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

android {
    compileSdkVersion 25
    buildToolsVersion '25.0.2'

    defaultConfig {
        applicationId "com.edt.edtdoctor"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 124
        versionName "1.2.4"

        ndk {
            abiFilters "armeabi"/*, "x86"*/
        }
        buildConfigField("String", "CHAT_DIRECTION", '"1"')
        buildConfigField("String", "XF_APPID", '"***"')
        buildConfigField("String", "CLIENT_ID", '"doctor"')
        buildConfigField("String", "WECHAT_KEY_VALUE", '"***"')
        //Enabling multidex support
        multiDexEnabled true
    }

    tasks.whenTaskAdded { task ->
        if (task.name.contains("lint")
                //如果instant run不生效,把clean这行干掉
                //||task.name.equals("clean")
                //如果项目中有用到aidl则不可以舍弃这个任务
                ||task.name.contains("Aidl")
                //用不到测试的时候就可以先关闭
                ||task.name.contains("mockableAndroidJar")
                ||task.name.contains("UnitTest")
                ||task.name.contains("AndroidTest")
                //用不到NDK和JNI的也关闭掉
                //|| task.name.contains("Ndk")
                //|| task.name.contains("Jni")
        ) {
            task.enabled = false
        }
    }

    signingConfigs {
        release {
            try {
                storeFile file('./keystore/edt_edtdoctor.jks')
                keyAlias 'china'
                keyPassword '******'
                storePassword '******'
            } catch (ex) {
                throw new InvalidUserDataException(ex.toString())
            }

        }
        debug {
            storeFile file("./keystore/debug.keystore")
        }
    }
    //友盟统计不同渠道(具体值看androidManifest.xml)
    productFlavors {

        huawei {
            applicationId "com.edt.***"
            buildConfigField("boolean", "IS_DEVELOP", "false")
            resValue "string", "app_name", "appName"
            buildConfigField("String", "BUGLY_ID", '"***"')
            manifestPlaceholders = [JPUSH_APPKEY_VALUE  : "***",
                                    EASEMOB_APPKEY_VALUE: "***",
                                    UMENG_APPKEY_VALUE  : "***",
                                    UMENG_CHANNEL_VALUE : "huawei",
                                    START_BACKGROUND    : "@style/Splash_Theme",
                                    app_icon            : "@mipmap/ic_launcher"]
        }
        develop {
            applicationId "com.edt.***"
            buildConfigField("boolean", "IS_DEVELOP", "true")
            resValue "string", "app_name", "another"
            buildConfigField("String", "BUGLY_ID", '"***"')
            manifestPlaceholders = [JPUSH_APPKEY_VALUE  : "***",
                                    EASEMOB_APPKEY_VALUE: "***",
                                    UMENG_APPKEY_VALUE  : "***",
                                    UMENG_CHANNEL_VALUE : "develop",
                                    START_BACKGROUND    : "@style/Three_Splash_Theme",
                                    app_icon            : "@drawable/icon"]
        }

//        productFlavors.all { flavor ->
//            //UMENG_CHANNEL_VALUE即为AndroidManifest.xml中的具体值,此值代表统计渠道
//            flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
//        }

    }


    lintOptions {
        tasks.lint.enabled = false
        checkReleaseBuilds false
        // Or, if you prefer, you can continue to check for errors in release builds,
        // but continue the build even when errors are found:
        abortOnError false

    }

    configurations.all {
        resolutionStrategy.force 'com.android.support:support-annotations:23.0.1'
    }

    buildTypes {
        debug {
            manifestPlaceholders = [JPUSH_APPKEY_VALUE  : "***",
                                    EASEMOB_APPKEY_VALUE: "***",
                                    UMENG_APPKEY_VALUE: "***",
                                    START_BACKGROUND    : "@style/Splash_Theme",
                                    app_icon: "@mipmap/ic_launcher"]
            buildConfigField("String", "BUGLY_ID", '"***"')
            signingConfig signingConfigs.release
        }

        release {//正式发布的时候使用
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            // 批量打包
            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)
                    }
                }
            }
        }
    }

    aaptOptions {
        additionalParameters "--no-version-vectors"
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

}
...

其中需要关注的是三部分:
defaultConfig {},buildTypes {},productFlavors {}
这三部分均可以对applicationId,图标及appname进行设置,但是优先级不同。优先级如下:

buildTypes >  productFlavors > defaultConfig  

设置AndroidManifest.xml中的属性可以通过manifestPlaceholders 进行设置,不同场景下的常量可以通过buildConfigField进行设置,资源的引用通过resValue 进行设置。

一、设置不同的app图标:

1、在AndroidManifest.xml中
将icon的属性值修改为”${app_icon}”

 <application
        android:name=".core.global.UserApplication"
        android:allowBackup="true"
        android:icon="${app_icon}"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

    ......

 </application>

2、在app.gradle文件下对”${app_icon}”中的app_icon的值进行设置。如下

manifestPlaceholders = [app_icon: "@mipmap/ic_launcher"]

注意:如果是通用的属性,可以在defaultConfig 中进行设置;不同的属性,通过productFlavors 或者buildTypes (设置debug或者release)进行设置。
3、如果编译是报错,可以加上如下语句:

 lintOptions {
        checkReleaseBuilds false
        // Or, if you prefer, you can continue to check for errors in release builds,
        // but continue the build even when errors are found:
        abortOnError false

    }

二、设置不同app名称

1、注释掉strings.xml中的app_name的资源

<resources>
    <!--<string name="app_name">心伴医生</string>-->
    <string name="ToastError">网络错误,请检查网络后重试</string>
    <string name="sava_success">保存成功</string>
</resources>

2、在app.gradle文件下设置app_name的资源

resValue "string", "app_name", "app名称"

三、修改不同的applicationId

1、在AndroidManifest.xml中修改包名为${applicationId}引用,如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.edt.edtdoctor">
    <permission
        android:name="${applicationId}.permission.JPUSH_MESSAGE"
        android:protectionLevel="signature"/>
    <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE"/>
    <application
        android:name=".core.global.UserApplication"
        android:allowBackup="true"
        android:icon="${app_icon}"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".section.entry.controller.activity.StartActivity"
            android:theme="${START_BACKGROUND}">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <meta-data
            android:name="${applicationId}.GlideModule"
            android:value="GlideModule"/>
        <meta-data
            android:name="UMENG_APPKEY"
            android:value="${UMENG_APPKEY_VALUE}"/>
        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL_VALUE}"/>
        <meta-data
            android:name="DOMAIN_PACKAGE_NAME"
            android:value="${applicationId}"/>
        <meta-data
            android:name="EASEMOB_APPKEY"
            android:value="${EASEMOB_APPKEY_VALUE}"/>
        <meta-data
            android:name="JPUSH_CHANNEL"
            android:value="developer-default"/>
        <meta-data
            android:name="JPUSH_APPKEY"
            android:value="${JPUSH_APPKEY_VALUE}"/>
     </application>

2、在app.gradle文件中根据不同的渠道在productFlavors 中进行设置,如下

productFlavors {
        huawei {
            applicationId "com.edt.***"
        }
        develop {
            applicationId "com.edt.***"
        }

四、其他第三方appkey的设置,参考app_icon的设置方式即可。

做完以上设置以后,通过Build > Generate Signed APK,选择签名后,就可以选择不同的渠道进行打包了。如果想要在debug状态下进行测试,将相关的代码复制一份放到buildTypes的debug{}中即可。

注:如果上面有不当的地方,烦请斧正。

参考文章:

Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)
Android——Gradle 心得 、变量、 多渠道、一些坑
使用Gradle构建多个不同applicationId包

猜你喜欢

转载自blog.csdn.net/Heijinbaitu/article/details/80740655