1. 程式人生 > >Android Studio 多渠道打包自命名

Android Studio 多渠道打包自命名

//—————————————————————————————-
(a)

apply plugin: 'com.android.application'
apply plugin: 'com.droidtitan.lintcleaner'
def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
def vCode() {
    return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}

android {
    compileSdkVersion 21
buildToolsVersion "22.0.1" signingConfigs { apply plugin: 'signing' release { storeFile file("../androidkey.keystore") storePassword "yourpassword" keyAlias "youralias" keyPassword "yourkey" } } defaultConfig { applicationId "your package name"
minSdkVersion 15 targetSdkVersion 21 versionCode Integer.valueOf(vCode()) versionName "2.1.10" } //多個版本的打包配置 productFlavors { Version1{ applicationId "your package name1" manifestPlaceholders = [GAO_DE_KEY: "your gaode key1", UMENG_KEY: "your umeng key1"
] } Version2 { applicationId "your package name2" manifestPlaceholders = [GAO_DE_KEY: "your gaode key2", UMENG_KEY: "your umeng key2"] } } buildTypes { release { signingConfig signingConfigs.release shrinkResources true minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //將release版本的包名重新命名,加上版本及日期 applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('release.apk')) { def fileName = "${variant.productFlavors[0].name}_V${defaultConfig.versionName}_${releaseTime()}.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } debug { signingConfig signingConfigs.release minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } lintOptions { abortOnError false } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } } repositories { maven { url "https://jitpack.io" } } //用來清除無用資源的外掛,詳見https://github.com/marcoRS/lint-cleaner-plugin lintCleaner { // Exclude specific files exclude = ['umeng*.png', '*.xml'] // Ability to ignore all resource files. False by default. ignoreResFiles = true } //將打包後的檔案複製到build目錄下,這樣就不用深入到apk目錄,同時還看不到unaligned的apk了 task copyTask(type: Copy) { from 'build/outputs/apk/' into 'build/' exclude '*-unaligned.apk' } task bd(dependsOn: ['assembleDebug', 'assembleRelease', 'copyTask']){ copyTask.mustRunAfter assembleRelease } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') // compile 'com.squareup.retrofit:retrofit:1.9.0' // compile 'com.squareup.okhttp:okhttp:2.3.0' // compile 'com.squareup.okhttp:okhttp-urlconnection:2.3.0' // compile 'com.facebook.stetho:stetho:1.1.1' // compile 'com.facebook.stetho:stetho-okhttp:1.1.1' // compile 'io.reactivex:rxandroid:0.24.0' // compile 'com.jakewharton:butterknife:6.1.0' compile 'com.facebook.fresco:fresco:0.5.2+' compile 'me.imid.swipebacklayout.lib:library:1.0.0' compile 'se.emilsjolander:stickylistheaders:2.6.0' compile 'de.greenrobot:eventbus:2.4.0' compile 'com.github.PhilJay:MPAndroidChart:v2.0.9' compile 'com.google.code.gson:gson:2.3.1' compile 'com.android.support:support-v13:22.2.0' compile project(':carShopSyncLib') }

//—————————————————————————————-
(b)
專案切換到Android Studio有一段時間了,來聊聊多渠道打包的做法。

1.在productFlavors新增你需要的所有渠道

android {

    productFlavors {  //在這裡新增你所有需要打包的渠道
        dev {}
        google {}
        myapp {}
        xiaomi {}
        app360 {}
        wandoujia {}
    }
    //新增如下程式碼
    productFlavors.all { flavors->
    flavors.manifestPlaceholders=[CHANNEL_VALUE:name]
    }
}

同時修改androidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="cn.op.zdf"
    android:versionCode="25"
    android:versionName="3.1.2">
    <application 
        android:name=".myApplication">
        <--manifest中新增如下程式碼--->
        <meta-data
                    android:name="UMENG_CHANNEL"
                    android:value="${CHANNEL_VALUE}"/>
    </application>
</manifest>

OK,在命令列執行gradle build,大功告成。你可以去喝杯茶了。

2.如何給apk重新命名
恩,釋出產品的時候我們需要如下的命名規則
release版本的命名規則如下:
產品名稱-版本號-渠道號-sign-42.apk

在build.gradle中新增如下程式碼
//獲取時間戳

def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMddHHmm')
    return formattedDate
}
//從androidManifest.xml中獲取版本號
def getVersionNameFromManifest(){
    def manifestParser = new com.android.builder.core.DefaultManifestParser()
    return manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)
}
android{
    //修改生成的apk名字
    applicationVariants.all{ variant->
        variant.outputs.each { output->
            def oldFile = output.outputFile
            def newName = '';
            if(variant.buildType.name.equals('release')){
//                println(variant.productFlavors[0].name)
                def releaseApkName = 'yjf-android-v' + getVersionNameFromManifest() + '-' + variant.productFlavors[0].name + '-sign-42.apk'
                output.outputFile = new File(oldFile.parent, releaseApkName)
            }
            if(variant.buildType.name.equals('beta')){
                newName = oldFile.name.replace(".apk", "-v" + getVersionNameFromManifest() + "-build" + getDate() + ".apk")
                output.outputFile = new File(oldFile.parent, newName)
            }
            if(variant.buildType.name.equals('debug')){
            }
        }
    }
}

哦,怎麼取得版本號?怎麼取得渠道號?怎麼判斷是不是release版本?上面的程式碼裡面都有。
我的專案是從eclipse中遷移過來的,所以我是從manifest檔案中讀取的版本號,就是上面的那個函式 getVersionNameFromManifest()
如果你的版本號定義在build.gradle中,那defaultConfig.versionName就是你的版本號。

//———————————————————————————-
下面是我自己的命名:

apply plugin: 'com.android.application'
//apply plugin: 'com.android.databinding'

def appName() {
    return "APP_NAME"
}

def releaseTime() {
    return new Date().format("yyyyMMddHHmm", TimeZone.getDefault())
}

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "xxxx.xxxx.xxxx.xxxxx"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 9
        versionName "1.0.14"
        // Enabling multidex support.
        // dex突破65535的限制
        multiDexEnabled true
    }

    signingConfigs {
        debug {
            storeFile file('tools/signature.keystore')
            storePassword SIGNING_STOREPASSWORD
            keyAlias SIGNING_KEYALIAS
            keyPassword SIGNING_KEYPASSWORD
        }
        release {
            storeFile file('tools/signature.keystore')
            storePassword SIGNING_STOREPASSWORD
            keyAlias SIGNING_KEYALIAS
            keyPassword SIGNING_KEYPASSWORD
        }
    }

    buildTypes {
        debug {
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //混淆
            minifyEnabled true
            //Zipalign優化
            zipAlignEnabled true
            // 移除無用的resource檔案
            shrinkResources true
            //載入預設混淆配置檔案 progudard-android.txt在sdk目錄裡面,不用管,proguard.cfg是我們自己配的混淆檔案
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //簽名
            signingConfig signingConfigs.debug

            //將release版本的包名重新命名,加上版本及日期,連線真機除錯的時候請註釋掉
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('debug.apk')) {
                        //def fileName = "${variant.productFlavors[0].name}_V${defaultConfig.versionName}_${releaseTime()}.apk"
                        def productFlavorsName = variant.productFlavors[0].name;
                        def fileName = "${appName()}.V${defaultConfig.versionName}.${releaseTime()}.alpha."+productFlavorsName+".apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
        release {
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //混淆
            minifyEnabled true
            //Zipalign優化
            zipAlignEnabled true
            // 移除無用的resource檔案
            shrinkResources true
            //載入預設混淆配置檔案 progudard-android.txt在sdk目錄裡面,不用管,proguard.cfg是我們自己配的混淆檔案
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //簽名
            signingConfig signingConfigs.release
            //
            //將release版本的包名重新命名,加上版本及日期
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('release.apk')) {
                        //def fileName = "${variant.productFlavors[0].name}_V${defaultConfig.versionName}_${releaseTime()}.apk"
                        def productFlavorsName = variant.productFlavors[0].name;
                        def fileName = "${appName()}.V${defaultConfig.versionName}.${releaseTime()}.release."+productFlavorsName+".apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
    }
    sourceSets {
        main {
            //manifest.srcFile 'AndroidManifest.xml'
            //java.srcDirs = ['src']
            //resources.srcDirs = ['resources']
            //res.srcDirs = ['res']
            //assets.srcDirs = ['assets']
            //aidl.srcDirs = ['src']
            //renderscript.srcDirs = ['src']
            jniLibs.srcDirs = ['libs']
        }
        androidTest.setRoot('tests')
    }

    allprojects {
        repositories {
            jcenter()
            mavenCentral();
        }
    }
    lintOptions {
        abortOnError false
        //disable 'InvalidPackage'
    }

    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
    }

//    在生成的apk檔案,修改下命名而已
//    applicationVariants.all { variant ->
//        variant.outputs.each { output ->
//            def outputFile = output.outputFile
//            if (outputFile != null && outputFile.name.endsWith('.apk')) {
//                //def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
//                def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
//                output.outputFile = new File(outputFile.parent, fileName)
//            }
//        }
//    }
     productFlavors {
        yijiajiao {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "XXXX"]
        }
        yingyongbao {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "XXXX"]
        }
        xiaomi {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "XXXX"]
        }
        wandoujia {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "XXXX"]
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile '......'

}

生成的apk名字是:
APP_NAME.V1.0.14.201510300950.alpha.yijiajiao.apk
APP_NAME.V1.0.14.201510300950.alpha.yingyongbao.apk
APP_NAME.V1.0.14.201510300950.alpha.xiaomi.apk
APP_NAME.V1.0.14.201510300950.alpha.wandoujia.apk