Gradle编译打包小结

本文链接:https://blog.csdn.net/byhook/article/details/51746825

 

以前用Eclipse打包,比较笨,右键导出签名 
现在一直是用的Android Studio来开发 
用Gradle编译打包非常方便 
笔者整理的平时编译打包的配置,记录一下,避免遗忘 

大概分为以下几个步骤
1、使用aapt工具将res资源文件生成R.java文件
2、使用aidl工具将aidl文件生成对应java文件
3、使用javac命令编译工程源代码和上面两步生成的文件,生成class文件
4、通过dex工具将class文件和第三方jar包打成dex文件
5、用aapt工具将res下的资源文件编译成二进制文件,然后将其和上一步中的dex文件以及assets中的文件通过apkbuilder工具打包成apk文件
6、通过jarsigner对apk进行签名
7、利用zipalign工具对apk进行字节对齐优化操作
 
 
 
转载:https://www.cnblogs.com/xaf-dfg/p/6374423.html


1.自动签名 
可以直接写在build.gradle里,如:

signingConfigs {
        develop {
            storeFile '/xxxxxx/xxx.jks'
            keyAlias 'xxxxxx'
            keyPassword 'xxxxxx'
            storePassword 'xxxxxx'
        }
    }

笔者习惯写在配置文件里,然后加入ignore方便后续更改 

è¿éåå¾çæè¿°

/**
 * 读取签名
 * @return
 */
def getSignProperty() {
    def Properties buildProperties = new Properties()
    buildProperties.load(new FileInputStream(file('../config/sign.properties')))
    return buildProperties
}

签名配置sign.properties

STORE_PASSWORD=xxxxxx
KEY_PASSWORD=xxxxxx
KEY_ALIAS=xxxxxx
STORE_FILE=xxxxxx.jks

2.同时打出不同环境的包 
正常情况下一个项目可能同时有测试环境和正式环境 
如果每次打包都去改配置是非常繁琐的,而且容易出错 
建议在配置文件里直接添加配置

productFlavors {
        buildDevelop {
            buildConfigField "boolean", "MODEL_DEV", "true"
            versionName = mVersionName
        }
        buildRelease {
            buildConfigField "boolean", "MODEL_DEV", "false"
            versionName = mVersionName
        }
    }

è¿éåå¾çæè¿°

如上所述,打包的时候会同时打出两个不同的包,一个是测试环境一个是正式环境

3.输出日志 
记录打包时候的时间,版本号以及Git提交的版本等等,方便日后审查

/**
 * 输出日志
 */
def buildLog(String output,String vName,String vCode) {
    File outputFile = new File(output)
    if(!outputFile.exists())
        outputFile.mkdirs()
    FileWriter fw = new FileWriter(output + File.separator + "log.txt")
    StringBuilder builder = new StringBuilder();
    builder.append("[构建时间]=" + buildTime("yy-MM-dd HH:mm"))
    builder.append("\r\n")
    builder.append("[版本编号]=" + vCode)
    builder.append("\r\n")
    builder.append("[版本名称]=" + vName)
    builder.append("\r\n")
    builder.append("[提交记录]=" + getGitVersion())
    fw.write(builder.toString())
    fw.flush();
    fw.close();
}

相关的函数

/**
 * 读取Git日志
 * @return
 */
def getGitVersion() {
    return 'git rev-parse --short HEAD'.execute().text.trim()
}

/**
 * 构建时间
 * @return
 */
def buildTime(String time) {
    def date = new Date()
    def formattedDate = date.format(time)
    return formattedDate
}

4.编译构建完成之后最好备份一下mapping文件

build {
    doLast {
        //记录日志
        buildLog(mOutputs,mVersionName,mVersionProps['VERSION_CODE'])
        //复制文件
        copy {
            from "$buildDir/outputs/mapping"
            into mOutputs
        }
    }
}

最后的全局配置文件

apply plugin: 'com.android.application'

/**
 * 读取版本配置
 */
def Properties mVersionProps = getVersionProperty();

/**
 * 读取版本名
 */
def mVersionName = buildRelease() ? mVersionProps['VERSION_NAME'] : "build_" + buildTime('yyMMdd')

/**
 * 输出目录
 */
def mOutputs = "$rootDir/outputs/build_" + buildTime('yyMMdd')

android {

    signingConfigs {
        develop {
            def Properties buildSignProps = getSignProperty()
            storeFile file(buildSignProps['STORE_FILE'])
            keyAlias buildSignProps['KEY_ALIAS']
            keyPassword buildSignProps['KEY_PASSWORD']
            storePassword buildSignProps['STORE_PASSWORD']
        }
    }

    buildTypes {
        debug {
            applicationIdSuffix ".debug"
            buildConfigField "boolean", "MODEL_DEV", "true"
        }
        release {
            minifyEnabled true
            buildConfigField "boolean", "MODEL_DEV", "false"
            signingConfig signingConfigs.develop

            zipAlignEnabled true
            //去掉无用资源
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    //读取版本配置
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultConfig {
        applicationId "cn.byhook.main"
        minSdkVersion 9
        targetSdkVersion 23
        versionCode Integer.valueOf(mVersionProps['VERSION_CODE'])
        versionName = mVersionName
    }

    dexOptions {
        javaMaxHeapSize "4g"
    }

    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    productFlavors {
        /*_$ { variant.productFlavors.get(0).name }
        $ { variant.buildType.name }*/
        buildDebug {
            buildConfigField "boolean", "MODEL_DEV", "true"
            versionName = "Local Version"
        }
        buildDevelop {
            buildConfigField "boolean", "MODEL_DEV", "true"
            versionName = mVersionName
        }
        buildRelease {
            buildConfigField "boolean", "MODEL_DEV", "false"
            versionName = mVersionName
        }
    }


    if (buildRelease()) {
        android.variantFilter { variant ->
            if (variant.buildType.name.equals('release')) {
                variant.getFlavors().each() { flavor ->
                    if (flavor.name.equals('buildDebug')) {
                        variant.setIgnore(true);
                    }
                }
            }
        }
    }

    //输出文件配置
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                if ("release".equals(variant.buildType.name)) {
                    if ("buildDevelop".equals(variant.productFlavors.get(0).name)) {
                        output.outputFile = new File(
                                mOutputs,
                                "Main_${buildTime("yyMMddHHmm")}_dev.apk")
                    } else if ("buildRelease".equals(variant.productFlavors.get(0).name)) {
                        output.outputFile = new File(
                                mOutputs,
                                "Main_${buildTime("yyMMddHHmm")}.apk")
                    }
                } else {
                    output.outputFile = new File(
                            outputFile.parent,
                            "app-debug.apk")
                }
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    testCompile 'org.robolectric:robolectric:3.1'
    compile project(':Exlibrary')
}

/********************************************************************
 * 打包脚本
 ********************************************************************/

/**
 * 构建版本
 * @return
 */
def getVersionProperty() {
    def Properties buildProps = new Properties()
    buildProps.load(new FileInputStream(file('../config/version.properties')))
    return buildProps;
}

/**
 * 读取签名
 * @return
 */
def getSignProperty() {
    def Properties buildProperties = new Properties()
    buildProperties.load(new FileInputStream(file('../config/sign.properties')))
    return buildProperties
}

/**
 * 构建时间
 * @return
 */
def buildTime(String time) {
    def date = new Date()
    def formattedDate = date.format(time)
    return formattedDate
}

/**
 * 是否发布
 * 发布为真
 * 版本号自增
 * @return
 */
def buildRelease() {
    return false
}

/**
 * 读取Git日志
 * @return
 */
def getGitVersion() {
    return 'git rev-parse --short HEAD'.execute().text.trim()
}

/**
 * 输出日志
 */
def buildLog(String output,String vName,String vCode) {
    File outputFile = new File(output)
    if(!outputFile.exists())
        outputFile.mkdirs()
    FileWriter fw = new FileWriter(output + File.separator + "log.txt")
    StringBuilder builder = new StringBuilder();
    builder.append("[构建时间]=" + buildTime("yy-MM-dd HH:mm"))
    builder.append("\r\n")
    builder.append("[版本编号]=" + vCode)
    builder.append("\r\n")
    builder.append("[版本名称]=" + vName)
    builder.append("\r\n")
    builder.append("[提交记录]=" + getGitVersion())
    fw.write(builder.toString())
    fw.flush();
    fw.close();
}

build {
    doLast {
        buildLog(mOutputs,mVersionName,mVersionProps['VERSION_CODE'])
        copy {
            from "$buildDir/outputs/mapping"
            into mOutputs
        }
    }
}

task mak{
    buildLog(mOutputs,mVersionName,mVersionProps['VERSION_CODE'])
}

打包只需终端输入

//--info或者--debug输出详细信息,方便出错时候定位错误
gradle clean
gradle build --info

è¿éåå¾çæè¿°

输出

è¿éåå¾çæè¿°

小结一下,方便以后打包处理更为方便,当然Gradle的强大之处远不止如此

Android Gradle是一种用于构建和管理Android应用程序项目的工具。它的一个重要功能就是打包编译资源。 在Android Gradle中,资源是指应用程序使用的各种非代码文件,如图像、布局文件、字符串、样式等。这些资源文件需要经过打包编译的过程才能被应用程序使用。 打包资源的过程是指将应用程序使用的所有资源文件收集起来,打包成一个或多个二进制资源文件(.arsc),以方便应用程序在运行时访问。这个过程由Gradle打包任务完成。打包后的资源文件会被放置在应用程序的res目录下的各个res-qualified目录中。 编译资源的过程是指将资源文件从其源文件形式编译成二进制格式,以便应用程序可以在运行时使用它们。这个过程由Android资源编译器(AAPT)完成。编译资源的过程包括对资源文件进行验证、解析和优化,最终生成资源文件的二进制表示形式。 要在Android Gradle项目中进行资源的打包编译,我们需要在项目的build.gradle文件中配置相应的构建规则和参数。其中,可以通过设置资源文件的名称、路径、扩展名等属性来指定要打包编译的资源文件。此外,还可以通过配置资源的qualifier(如屏幕密度、语言等)来实现对不同设备和语言环境的资源适配。 通过Android Gradle打包编译资源功能,我们可以方便地管理和使用应用程序的各种资源文件,使应用程序在不同设备和语言环境下都能正确地加载和显示相应的资源。这对于开发多语言和多平台的应用程序来说,是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值