1. 程式人生 > >Gradle配置及同一應用不同版本配置不同資原始檔,不同簽名,包名進行打包

Gradle配置及同一應用不同版本配置不同資原始檔,不同簽名,包名進行打包

公司的專案,一個專案也就是同一套程式碼要針對多個客戶打出多個版本的apk,不同版本的apk中一些程式碼是不同的,比如伺服器的地址,app的名字,圖片資源以及簽名檔案等都是不同的。剛開始的時候,把這些相同的程式碼,資原始檔提取出來,打包的時候進行替換就可以了,隨著客戶越來越多,每為一個客戶打包,替換一次資原始檔,很浪費時間,還容易出錯。其實,我們可以在build.gradle中進行配置,來解決問題。

我們先看一下build.gradle中的一些相關配置

android {
    compileSdkVersion 25
    buildToolsVersion "24.0.3"
    //預設的一些配置
    defaultConfig {
        applicationId "com.app.springboot" //應用的包名
        minSdkVersion 14     //支援的最低版本
        targetSdkVersion 25	//目標版本
        versionCode 1	
        versionName "1.0"
    }

    //debug和release版本的簽名配置
    signingConfigs {
        release {
            storeFile file("D:/other/test.jks")
            storePassword "12345678"
            keyAlias "test"
            keyPassword "123456"
        }
    }
    //構建型別,通常有release和debug兩種
    buildTypes {
        release {
            minifyEnabled false //是否開啟混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release //指定打包時的簽名
	}
    }
    //用來配置APP的不同版本
    productFlavors{
            demo1{
		applicationId "com.app.demo1" //為不同版本指定的包名
		manifestPlaceholders=[umeng_app_key:"替代的內容"] //可以替換清單檔案AndroidManifest中指定的內容	
	    }
	    demo2{
		applicationId "com.app.demo2"
		manifestPlaceholders=[umeng_app_key:"替代的內容"]
	    }
	}
}
	//新增需要的依賴
  dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'
    testCompile 'junit:junit:4.12'
    compile 'com.squareup.okhttp:okhttp:2.6.0'
}
上面是一些build.gradle的基本的配置,
因為我們的app需要打不同版本的包,不同版本的包需要配置不同的資原始檔和簽名檔案,所以在build.gradle中這樣配置
 android {
    compileSdkVersion 25
    buildToolsVersion "24.0.3"
    defaultConfig {
        applicationId "com.app.springboot" 
        minSdkVersion 14     
        targetSdkVersion 25	
        versionCode 1	
        versionName "1.0"
    }

    //debug和release版本的簽名配置
    signingConfigs {
        demo1{
            storeFile file("D:/demo/demo1/demo1.jks")
            storePassword "12345678"
            keyAlias "test"
            keyPassword "123456"
        }
	demo2{
            storeFile file("D:/demo/demo2/demo2.jks")
            storePassword "12345678"
            keyAlias "test"
            keyPassword "123456"
        }
    }
    buildTypes {
        release {
            minifyEnabled false 
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
	}
    }
    //用來配置APP的不同版本
    productFlavors{
            demo1{
		applicationId "com.app.demo1" 
		manifestPlaceholders=[umeng_app_key:"替代的內容"] 
		signingConfig signingConfigs.demo1   //指定打包時的簽名
	    }
	    demo2{
		applicationId "com.app.demo2"
		manifestPlaceholders=[umeng_app_key:"替代的內容"]
		signingConfig signingConfigs.demo2 
	    }
	}
     // 針對不同的客戶,編譯不同的目錄,
     sourceSets{
        demo1.res.srcDirs=['src/main/res-demo1'] //指定編譯的目錄
        demo2.res.srcDirs=['src/main/res-demo2']
    }
}

如上,在sourceSets{}中,針對不同的客戶,編譯不同的目錄,不同的版本可以選擇不同的編譯目錄進行編譯,,如果指定一個目錄,其他目錄沒有指定,那麼就會把指定的目錄和預設的目錄一起打包到apk中。如果指定了res-demo1,打包的時候res-demo1會替換掉res下的同名檔案。


因為不同版本的簽名檔案也需要不同,所以在signingConfigs {}中為每個版本配置了一個簽名檔案,但是這種方法不太安全,建議不要在build.gradle檔案中寫上簽名檔案的密碼,因為build.gradle檔案一般都會整合到程式碼的版本控制中,這樣所有人都會有簽名檔案的密碼。所以應該把簽名檔案的密碼隔離起來,寫到一個配置檔案中,此配置檔案不包含在程式碼版本控制中,這樣其他開發者就不會知道簽名檔案的密碼。
我們先新建一個signing.properties檔案:

STORE_FILE=yourapp.keystore
STORE_PASSWORD=your password
KEY_ALIAS=your alias
KEY_PASSWORD=your password
接下在guild.gradle檔案中讀取signing.properties配置檔案,讀取的程式碼如下:
File propFile = file('signing.properties');
if (propFile.exists()) {
    def Properties props = new Properties()
    props.load(new FileInputStream(propFile))
    if (props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
            props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {
        android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
        android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
        android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
        android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
    } else {
        android.buildTypes.release.signingConfig = null
    }
} else {
    android.buildTypes.release.signingConfig = null
}

我們還可以在gradle中配置我們打出包的包名:
在buildTypes{}中新增如下程式碼:
android.applicationVariants.all { variant ->
            // each遍歷variant
            variant.outputs.each { output ->
                def outputFile = output.outputFile
                if (outputFile != null) {
                    println "======outputFile.name======" + outputFile.name;
                    def fileName;
                    if (outputFile.name.endsWith('app-demo1-release.apk')) {
                        fileName="demo1-AndroidTrader-${defaultConfig.versionName}.apk" //打出包的包名
                    }else if(outputFile.name.endsWith('app-demo2-release.apk')){
                        fileName="demo2-AndroidTrader-${defaultConfig.versionName}.apk"
                    } else {
                        fileName='app-release.apk';
                    }
                    output.outputFile = new File(outputFile.parent, fileName)
                }
            }
        }
接下來,我們可以使用gradle進行打包
gradle assembleRelease    // 構建productFlavors下所有Variant Release版本
gradle assembleDebug      // 構建productFlavors下所有Variant Debug版本
gradle assemble[productFlavors.name]          // 構建productFlavors下name的Variant Release和Debug版本
gradle assemble[productFlavors.name]Relase    // 構建productFlavors下name的Variant Releaseg版本
gradle assemble[productFlavors.name]Debug     // 構建productFlavors下name的Variant Debug版本

也可以通過AS進行編譯打包



在我們點選debug除錯的時候,不知道究竟是使用哪個 Flavors來編譯,我們可以選擇” Build Variant”,然後在出現的視窗中選擇其中一個選項作為預設的編譯,執行選項即可。