需求

现在项目已经实现jenkins自动打包,现在需要在jenkns中的shell修改一个参数即可打包生成各种版本的app,例如 生成:

  • 测试环境有调试信息的app
  • 预上线环境有调试信息
  • 预上线环境无调试信息
  • 正式环境有调试信息,
  • 正式环境(发包版本无调试信息)

顺便说下 目前生成的文件是通过 gradle 命令打包生成的.然后通过shell命令从工作空间将apk拷贝出来.供测试人员下载.

解决思路

因为gradle 是groovy 语法 ,那么我定义各种域名后在 buildTypes 里面添加各种类型的版本.读取各种版本的域名.

还有一些其他技巧 比如打包生成的apk 统一放在 output/main 目录下 除了debug 版本

调试信息的含义

调试信息是可以在app里面看到一些网络请求参数,返回值,app的crash.以悬浮窗实现

安利下我之前写的神器,开发工具帮助库
http://blog.csdn.net/liudao7994/article/details/55510782

配置文件

apply plugin: 'com.android.application'

android {
    //DOMAIN
    def API_RELEASE_DOMAIN = "\"正式环境\""
    //正式环境
    def API_RELEASE = "\"https://正式环境\""

    //DOMAIN
    def API_TEST_DOMAIN = "\"测试环境\""
    //测试环境
    def API_TEST = "\"http://测试环境\""

    //DOMAIN
    //预发环境
    def API_PRE_RELEASE = "\"https://预发环境\""
    def API_PRE_RELEASE_DOMAIN = "\"预发环境\""

    //开发环境DOMAIN
    def API_DEV_DOMAIN = "\"开发环境\""
    //开发环境
    def API_DEV_HOST = "\"http://开发环境\""



    compileSdkVersion 25
    buildToolsVersion '26.0.2'

    //23 编译版本需要添加这句话,低于23 不需要
    useLibrary 'org.apache.http.legacy'
    aaptOptions.cruncherEnabled = false
    aaptOptions.useNewCruncher = false
    defaultConfig {
        multiDexEnabled true
        applicationId "com.a1chemic.promotion.android"
        minSdkVersion 12
        targetSdkVersion 23
        versionCode 201
        versionName "2.0.1"
        buildConfigField("String", "API_HOST", "${API_DEV_HOST}")
        buildConfigField("String", "API_DOMAN", "${API_DEV_DOMAIN}")
        ndk {
            abiFilters "armeabi", "x86", "mips"
        }
    }
    dexOptions {
        javaMaxHeapSize "4g"
    }
    aaptOptions {
        cruncherEnabled = false
        useNewCruncher = false
    }
    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }
    signingConfigs {
        release {
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    loadSigningConfigs()

    buildTypes {

        //开发 自己用的
        debug {
            buildConfigField "String", "API_HOST", "${API_DEV_HOST}"//API Host
            buildConfigField "String", "API_DOMAN", "${API_DEV_DOMAIN}"//测试地址
            buildConfigField "boolean", "SING_DEBUG", "true"
            buildConfigField "boolean", "DEBUGINFO", "true"
            resValue "string", "AppName", "应用开发板"
        }
        //测试 显示调试
        debugTest {
            signingConfig signingConfigs.release
            buildConfigField "String", "API_HOST", "${API_TEST}"//API Host
            buildConfigField "String", "API_DOMAN", "${API_TEST_DOMAIN}"//测试地址
            buildConfigField "boolean", "SING_DEBUG", "true"
            buildConfigField "boolean", "DEBUGINFO", "true"
            matchingFallbacks = ['debug']
            resValue "string", "AppName", "应用测试版"
        }
        //预上线 显示调试
        preRelease {
            signingConfig signingConfigs.release
            buildConfigField "String", "API_HOST", "${API_PRE_RELEASE}"//预上线 API Host
            buildConfigField "String", "API_DOMAN", "${API_PRE_RELEASE_DOMAIN}"//预上线
            buildConfigField "boolean", "SING_DEBUG", "false"
            buildConfigField "boolean", "DEBUGINFO", "true"
            matchingFallbacks = ['debug']
            resValue "string", "AppName", "应用预览版"
        }
        //正式 有调试信息
        releasePE {
            minifyEnabled false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "String", "API_HOST", "${API_RELEASE}"//API Host
            buildConfigField "String", "API_DOMAN", "${API_RELEASE_DOMAIN}"//正式地址
            buildConfigField "boolean", "SING_DEBUG", "false"
            buildConfigField "boolean", "DEBUGINFO", "true"
            matchingFallbacks = ['release']
            resValue "string", "AppName", "应用名称"
        }
        //预上线Demo 无调试信息
        preReleaseDemo {
            signingConfig signingConfigs.release
            buildConfigField "String", "API_HOST", "${API_PRE_RELEASE}"//预上线 API Host
            buildConfigField "String", "API_DOMAN", "${API_PRE_RELEASE_DOMAIN}"//预上线
            buildConfigField "boolean", "SING_DEBUG", "false"
            buildConfigField "boolean", "DEBUGINFO", "false"
            matchingFallbacks = ['release']
            resValue "string", "AppName", "应用预览版"
        }
        //正式 无调试信息
        release {
            debuggable false
            minifyEnabled false //启用Proguard --正常应该是true
            shrinkResources false //是否清理无用资源,依赖于minifyEnabled
            zipAlignEnabled true //是否启用zipAlign压缩
            minifyEnabled false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "String", "API_HOST", "${API_RELEASE}"//
            buildConfigField "String", "API_DOMAN", "${API_RELEASE_DOMAIN}"//
            buildConfigField "boolean", "SING_DEBUG", "false"
            buildConfigField "boolean", "DEBUGINFO", "false"
            resValue "string", "AppName", "正式名称"
        }
    }

    sourceSets {
        main {
            jniLibs.srcDir 'libs'
            //说明so的路径为该libs路径,关联所有地图SDK的so文件
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            resources.srcDirs = ['src/main/resources']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
        }
        vivo.res.srcDirs = ['src/main/res-vivo']
    }

    flavorDimensions "default"
    productFlavors {
        main { dimension "default" }
//        vivo { dimension "default" }  //vivo
//        baidu { dimension "default" } //百度
//        tencent { dimension "default" } //应用宝
//        xiaomi { dimension "default" }   //小米
//        qh360 { dimension "default" }  //360
//        huawei { dimension "default" }  //华为
//        wandoujia { dimension "default" } //豌豆荚
//        vivo { dimension "default" }  //vivo
//        oppo { dimension "default" } //oppo
//        meizu { dimension "default" } //魅族
    }
    productFlavors.all {
        flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }
    applicationVariants.all { variant ->
        if (variant.buildType.name != "debug") {//防止AS无法安装debug包(apk)
            variant.getPackageApplication().outputDirectory = new File(project.rootDir.absolutePath + "/app/build/outputs/apk/main")
        }
        variant.outputs.all { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                // 输出apk名称为com_biniusports_app_bnsports_v1.0.0_20171205_baidu.apk
                def fileName = "应用_${variant.buildType.name}_V${defaultConfig.versionName}_${getNowTime()}_${variant.productFlavors[0].name}.apk"
                outputFileName = fileName
            }
        }
    }

}

//获取时间戳
def getNowTime() {
    def date = new Date()
    def now = date.format('yyyyMMdd')
    return now
}


/**
 * 加载签名配置文件
 */
def loadSigningConfigs() {
     Properties props = new Properties()
    def propFile = file('../signing.properties')
    if (propFile.canRead()) {
        props.load(new FileInputStream(propFile))
        //发布版本的签名配置
        android.signingConfigs.release.storeFile = file(props['KEYSTORE_FILE'])
        android.signingConfigs.release.storePassword = props['KEYSTORE_PWD']
        android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
        android.signingConfigs.release.keyPassword = props['KEY_PWD']

       /* //调试版本的签名配置
        android.signingConfigs.debug.storeFile = file(props['DEBUG_KEYSTORE'])
        android.signingConfigs.debug.storePassword = props['DEBUG_KEYSTORE_PWD']
        android.signingConfigs.debug.keyAlias = props['DEBUG_ALIAS']
        android.signingConfigs.debug.keyPassword = props['DEBUG_KEY_PWD']*/
    }
}

dependencies {
    compile 'com.android.support:multidex:1.0.1'
    compile files('libs/android-support-v7-recyclerview.jar')
}

jenkins shell命令

#测试版-测试环境 - 分支 dev:Test
#预览版-预生产环境-分支 dev:Pre
#生产版-生产环境 - 分支 dev:PE
#演示版-预生产环境-分支 master:Demo
#商店版-生产环境 - 分支 master:AppStore
DEFINE=AppStore

if [ "${DEFINE}" == "Test" ]; then
        AssembleBuild="assembledebugTest"
    elif [ "${DEFINE}" == "Pre" ]; then
        AssembleBuild="assemblepreRelease"
    elif [ "${DEFINE}" == "PE" ]; then
        AssembleBuild="assemblereleasePE"
    elif [ "${DEFINE}" == "Demo" ]; then
        AssembleBuild="assemblepreReleaseDemo"
    elif [ "${DEFINE}" == "AppStore" ]; then
        AssembleBuild="assemblerelease"
    fi

gradle clean ${AssembleBuild}

如何使用域名

BuildConfig.API_HOST 就行了

图标的修改

 //预上线Demo 无调试信息
        preReleaseDemo {
            signingConfig signingConfigs.release
            buildConfigField "String", "API_HOST", "${API_PRE_RELEASE}"//预上线 API Host
            buildConfigField "String", "API_DOMAN", "${API_PRE_RELEASE_DOMAIN}"//预上线
            buildConfigField "boolean", "SING_DEBUG", "false"
            buildConfigField "boolean", "DEBUGINFO", "false"
            matchingFallbacks = ['release']
            resValue "string", "AppName", "应用预览版"
            manifestPlaceholders =[app_icon:"@drawable/app_icon_test"]
        }
 manifestPlaceholders =[app_icon:"@drawable/app_icon_test"]
 //app_icon_test 这个就是需要的图标

在AndroidManifest.xml中替换\
android:icon=”${app_icon}”
就做这两步就OK了

TODU

后面有时间还要做的是使用命令行进行360加固,这样打包出来之后就可以直接发布市场了.

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐