android - build.gradle

app

apply plugin: 'com.android.application'
apply plugin: 'findbugs'

//得到日期的方法
static def releaseTime() {
    return new Date().format("yyMMdd-HHmm")
}

//基本配置
android {
    compileSdkVersion 26
    buildToolsVersion '26.0.2'
    defaultConfig {
        applicationId "com.guangyouqian.app"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1000100
        versionName "1.0.1"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        manifestPlaceholders = [channel:"weiliu"]
    }

//签名信息配置
    signingConfigs {
        release {
            storeFile file("keystore.jks")
            storePassword "xxxxxxxxxxxx"//密码
            keyAlias "xxxx"//名称
            keyPassword "xxxxxxxxxxx"//密码
        }
    }

//编译的类型
    buildTypes {
        release {
        // BuildConfig类下增加自定义字段 参数的含义(类型,名称,内容)
            buildConfigField "boolean", "DEV", "false"
            buildConfigField "String", "API_HOST", "\"https://api.gyq.v6h5.com/\""
            //选择签名信息
        signingConfig signingConfigs.release  
        //会对代码进行混淆和压缩
            minifyEnabled true  
        //会对比R文件对无用资源进行删除 (minifyEnabled 设置为true时shrinkResources 的设置才会生效)
            shrinkResources true  
        //是否启用zipAlign压缩
        zipAlignEnabled true 
            //用到的混淆文件
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        http {
            matchingFallbacks = ['debug', 'release']
            buildConfigField "boolean", "DEV", "true"
            debuggable true
            signingConfig signingConfigs.release
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            buildConfigField "boolean", "DEV", "true"
            debuggable true
            signingConfig signingConfigs.release
            minifyEnabled false
            shrinkResources false
        }
    }

    lintOptions {
        abortOnError false
        lintConfig file('lint.xml')
    }

//打包apk重命名
//    android.applicationVariants.all { variant ->
//        variant.outputs.all { output ->
//            def channel = defaultConfig.manifestPlaceholders.get("channel")
//            if (variant.buildType.name == 'release' && outputFileName != null && outputFileName.endsWith('.apk')) {
//                //这里修改apk文件名
//                outputFileName = "gyq-${channel}-v${defaultConfig.versionName}-${releaseTime()}.apk"
//            }
//        }
//    }

    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
}


//依赖配置
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile project(':library')
    testCompile 'junit:junit:4.12'
}

static def getAppName() {
    return "czsp"
}


static def originReleaseApk() {
    return getAppName() + "-release.apk"
}

static def andResGuardApk() {
    return "AndResGuard_app-release/app-release_aligned_signed.apk"
}

def timeReleaseApkName() {
    String appVersion = project.android.defaultConfig.versionName
    return String.format(getAppName() + "-%s-%s", appVersion, releaseTime())
}

afterEvaluate {

    // daily build,会自动通过findbugs工具检查代码并输出结果
    //noinspection GroovyAssignabilityCheck
    task dailyBuild(dependsOn: 'assemble', type: FindBugs) {
        ignoreFailures = true
        reportLevel = "medium"
        classes = files("$project.buildDir/intermediates/classes")
// Use this only if you want exclude some errors
        excludeFilter = file("findbugs_exclude.xml")

        source = fileTree(dir: '../', include: '*/src/main/**/*.java')
        classpath = files()
        reports {
            xml.enabled = true
            xml.withMessages = true
            html.enabled = !xml.isEnabled()
            //noinspection GroovyAssignabilityCheck
            xml.destination "$project.buildDir/outputs/findbugs/findbugs-output.xml"
            html.destination "$project.buildDir/outputs/findbugs/findbugs-output.html"
        }

    }


    task channelBuild {
        String dir = "../repack/" + project.android.defaultConfig.versionName
        String path = dir + "/" + getAppName() + ".apk";
        println "-apkPath = " + file(path).getAbsolutePath()
        boolean apkRebuild = project.hasProperty("apkRebuild") ? project.property("apkRebuild").toBoolean() : false
        println "-apkRebuild = " + apkRebuild

        boolean shouldRebuild = apkRebuild || !file(path).exists()
        println "shouldRebuild = " + shouldRebuild

        if (shouldRebuild) {
            //构建build那个包
            dependsOn 'assembleRelease' //或者assembleDebug . resguardRelease ....
        }

        doFirst {
            println "doFirst shouldRebuild = " + shouldRebuild
            println "doFirst path = " + path
            if (shouldRebuild) {
                if (file(path).exists()) {
                    if (!file(path).delete()) {
                        println "delete " + path + " failed"
                        throw new RuntimeException("delete " + path + " failed")
                    }
                } else {
                    file(path).getParentFile().mkdirs()
                }
                //将源发布的app,复制一份到指定的位置 ,originReleaseApk()源app ,  renameTo()就是复制方法 file(path) 目标路径
                if (file("$project.buildDir/outputs/apk/release/" + originReleaseApk()).renameTo(file(path))) {
                    println "renameTo " + path + " success"
                } else {
                    println "renameTo " + path + "failed"
                    throw new RuntimeException("renameTo " + path + " failed")
                }
            }
        }

        doLast {
            def localProperties = new File(rootDir, "local.properties")
            Properties properties = new Properties()
            localProperties.withInputStream { instr ->
                properties.load(instr)
            }
            def sdkDir = properties.getProperty('sdk.dir')

            // apktool decode
            String apktool = "apktool-cli.jar"
            String apktoolDecodeDir = dir + "/apktool_decode"
            if (shouldRebuild || !file(apktoolDecodeDir).exists()) {
                if (!file(apktoolDecodeDir).exists()) {
                    if (!file(apktoolDecodeDir).mkdir()) {
                        println "mkdir " + apktoolDecodeDir + " failed"
                        throw new RuntimeException("mkdir " + apktoolDecodeDir + " failed")
                    }
                }
                println "apktool decode to " + apktoolDecodeDir + " starting......"
                exec {
                    executable "java"
                    args "-jar", apktool, "d", "-f", "-r", "-s", "-o", apktoolDecodeDir, path
                }
                println "apktool decode to " + apktoolDecodeDir + " end"
            }

            // for channels
            if (!project.hasProperty("channels")) {
                println "no channels1"
                throw new StopExecutionException()
            }
            String[] channels = project.property("channels").split(",")

            if (channels == null || channels.length == 0) {
                println "no channels2"
                throw new StopExecutionException()
            }
            String buildNo = project.hasProperty("buildNo") ? project.property("buildNo") : "undefined"
            String buildNoDir = dir + "/" + buildNo
            if (!file(buildNoDir).exists()) {
                if (!file(buildNoDir).mkdir()) {
                    println "mkdir " + buildNoDir + " failed"
                    throw new RuntimeException("mkdir " + buildNoDir + " failed")
                }
            }

            String finalName = timeReleaseApkName()
            String apktoolBuildTempPath = dir + "/" + finalName + "_unsigned.apk"
            String signTempPath = dir + "/" + finalName + "_unaligned.apk"
            String[] paths = [apktoolBuildTempPath, signTempPath]
            for (String filePath : paths) {
                if (file(filePath).exists() && !file(filePath).delete()) {
                    println "delete " + filePath + " failed"
                    throw new RuntimeException("delete " + filePath + " failed")
                }
            }

            for (String channel : channels) {
                String finalApkPath = buildNoDir + "/" + finalName + "_" + channel + ".apk"

//                def manifestFile = file(apktoolDecodeDir + "/AndroidManifest.xml")
//                println channel + " write to " + manifestFile + " starting..."
//                def content = manifestFile.getText()
//                def replace = content.replaceAll(/(android:name="UMENG_CHANNEL"\s+android:value=")(\w+)(")/, '$1' + channel + '$3')
//                manifestFile.write replace
                String channelFilePath = apktoolDecodeDir + "/assets/channel.ini"
                println channel + " write to " + channelFilePath + " starting..."
                file(channelFilePath).write channel

                println apktoolBuildTempPath + " apktool build starting..."
                exec {
                    executable "java"
                    args "-jar", apktool, "b", "-f", "-o", apktoolBuildTempPath, apktoolDecodeDir
                }

                println signTempPath + " jarsigner sign starting..."
                exec {
                    executable "jarsigner"
                    args "-keystore", project.android.signingConfigs.release.storeFile,
                            "-storepass", project.android.signingConfigs.release.storePassword,
                            "-keypass", project.android.signingConfigs.release.keyPassword,
                            "-digestalg", "SHA1",
                            "-sigalg", "MD5withRSA",
                            "-signedjar", signTempPath,
                            apktoolBuildTempPath,
                            project.android.signingConfigs.release.keyAlias
                }

                println finalApkPath + " zipalign align starting..."
                exec {
                    executable sdkDir + "/build-tools/26.0.2/zipalign"
                    args "-f", "4", signTempPath, finalApkPath
                }

            }
        }
    }
}



/**
 * 通过过滤黑名单,从而得到白名单列表
 * @param resNameArr 资源名<数组>
 * @param blacklist 黑名单<名字开头>
 * @return 返回白名单列表
 */
static Iterable<String> disposeBlacklist(String[] resNameArr, String blacklist) {
    Iterable<String> arr = new ArrayList<>()
    StringBuffer sb = new StringBuffer()
    for (int j = 0; j < resNameArr.length; j++) {
        for (int i = 0; i < blacklist.length(); i++) {
            sb.setLength(0)
            sb.append(blacklist.substring(0, i + 1))
            sb.insert(i, "[^")
            sb.insert(i + 3, "]")
            arr.add("R." + resNameArr[j] + "." + sb.toString() + "*")
        }
    }
    return arr
}
/*andResGuard资源混淆*/
andResGuard {
//     mappingFile = file("./resource_mapping.txt")
    mappingFile = null
    // 当你使用v2签名的时候,7zip压缩是无法生效的。
    use7zip = true
    useSign = true
    // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字:一般false
    keepRoot = true
    //不进行混淆的白名单
    String[] resName = [
            "anim",
            "animator",
            "color",
            "drawable",
            "layout",
            "menu",
            "mipmap",
            "string",
            "style",
            "item",
            "dimen",
            "string-array",
            "xml",
            "id",
            "raw"
    ]
    whiteList = disposeBlacklist(resName, "gyq_")
    //设置压缩的资源
    compressFilePattern = [
            "*.png",
            "*.jpg",
            "*.jpeg",
            "*.gif",
            "resources.arsc"
    ]
    sevenzip {
        artifact = 'com.tencent.mm:SevenZip:1.2.8'
//        path = "D:/7-Zi/7za.exe"
    }

    /**
     * 可选: 如果不设置则会默认覆盖assemble输出的apk
     **/
//    finalApkBackupPath = "${project.rootDir}/final.apk"

    /**
     * 可选: 指定v1签名时生成jar文件的摘要算法
     * 默认值为“SHA1”
     **/
    digestalg = "SHA1"
}

project

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.8'  //mm:AndResGuard
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven {
            url "http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/"
        }
        google()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

猜你喜欢

转载自blog.csdn.net/binbin594738977/article/details/81544883