欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

gradle动态编译

程序员文章站 2022-04-28 13:31:20
...

开发中需要根据不同的用户或者场景,采用不同的逻辑/效果,生成不同的包,但是大部分代码是不变的。如果同时维护两个大致相同的项目,工作会既枯燥又毫无用处,还浪费时间。这时候就该用到gradle的动态编译了。

最近有个项目app,要求可以切换角色,切换之后,基本上一半的字段名称都要改变,后台接口返回的内容有可能也会不一样,还没想到怎么做....感觉这种动态编译也不能实现,各位大虾有什么好办法么?

一、配置gradle

build.gradle中可以包括两个节点:buildTypes和productFlavors

  • buildTypes默认有release和debug两个选项。

  • 我们这里在productFlavors增加Seller和buyer。(假设买家和卖家两种场景)

    
        productFlavors{
    
            buyer{
                applicationIdSuffix ".buyer"
            }
            Seller{
                applicationIdSuffix ".Seller"
            }
        }

    buildTypes和productFlavors组合就有下面4个版本了。

SellerDebug
SellerRelease
buyerDebug
buyerRelease

二、新建项目文件,与src下新建Seller, buyer两个文件夹,并分别创建包名,与相同的类(方法名相同,方法体不同)。如下

gradle动态编译

这时,只能识别一个buyer,另一个识别不了,没关系,这是在gradle中顺序,默认只编译第一个。在打包时可以选择编译哪个。

三、在mian项目中使用这个方法。

四、为了区分两个包,把apk名改一下。

 //修改生成的apk名字
    applicationVariants.all {
        variant ->
            variant.outputs.each {
                output ->
                    def oldFile = output.outputFile
                    if (oldFile.name.contains('.apk')){
                        def newName = variant.applicationId+'-v' + defaultConfig.versionName + '-'+variant.buildType.name+'.apk'
                        output.outputFile = new File(oldFile.parent, newName)
                    }

                    if (output.zipAlign != null) {
                        output.zipAlign.doLast {
                            output.zipAlign.inputFile.delete()
                        }
                    }
            }
    }

五、打包。

gradle动态编译

如果想动态修改minifest.xml里的应用名和图标,可以在productFlavors中修改,在minifest.xml中使用。

    productFlavors{
        buyer {
            applicationIdSuffix ".buyer"
            manifestPlaceholders = [
                    app_name: "淘宝买家端",
                    app_icon: "@mipmap/icon_launcher_buyer"]
        }

        seller {
            applicationIdSuffix ".seller"
            manifestPlaceholders = [
                    app_name: "淘宝卖家端",
                    app_icon: "@mipmap/icon_launcher_seller"]
        }
    }
    <application
        android:allowBackup="true"
        android:icon="${app_icon}"
        android:label="${app_name}"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

最后介绍下,动态应用名。有时候需要根据选择的productFlavor和buildType来生成不同的应用名,防止调试、测试时搞混。


def appType;
def appName;
android {
    signingConfigs {
        config {
            keyAlias KEY_ALIAS
            keyPassword KEY_PASSWORD
            storeFile file('../app/tong_key.jks')
            storePassword KEYSTORE_PASSWORD
        }
    }
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.lemon.studykit"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            appType="正式"
            debuggable false
            buildConfigField("String", "generalHost", "\"http://192.168.1.224:8089/\"")

            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }
        debug {
            appType="开发"
            buildConfigField("String", "generalHost", "\"http://192.168.1.224:10001/\"")
            signingConfig signingConfigs.config
        }
        inerTest {
            appType="内测"
            buildConfigField("String", "generalHost", "\"http://192.168.1.69:10001/\"")

            debuggable true
            jniDebuggable false
            signingConfig signingConfigs.config
            minifyEnabled false
            zipAlignEnabled true
        }
    }
    productFlavors {
        apple {
            appName="苹果公司"
        }
        lemon {
            appName="柠檬公司"
        }
    }
    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [
                app_name:  "${appName}-${appType}",
                app_icon: "@mipmap/ic_launcher",
                app_icon_round: "@mipmap/ic_launcher_round"
        ]
    }

    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
    //修改生成的apk名字
    applicationVariants.all {
        variant ->
            variant.outputs.each {
                output ->
                    def oldFile = output.outputFile
                    if (oldFile.name.contains('.apk')){
                        def newName = variant.applicationId+'-v' + defaultConfig.versionName + '-'+variant.buildType.name+'.apk'
                        output.outputFile = new File(oldFile.parent, newName)
                    }

                    if (output.zipAlign != null) {
                        output.zipAlign.doLast {
                            output.zipAlign.inputFile.delete()
                        }
                    }
            }
    }

    //如果你的as是3.0以后的,outputFile就不能直接替换了,改为以下写法

    applicationVariants.all { variant ->
        variant.outputs.all { output ->  // each 改为 all
            def newName = variant.applicationId+'-v' + defaultConfig.versionName + '-'+variant.buildType.name+'.apk'
            def outFile = output.outputFile
            if (outFile != null && outFile.name.endsWith('.apk')) {
                outputFileName = newName 
            }
        }
    }
}