美文网首页
Android项目构建Gradle专栏——build基础

Android项目构建Gradle专栏——build基础

作者: 壹零二肆 | 来源:发表于2021-04-02 16:41 被阅读0次

    目录:

      1. 构建体系
      1. Build流程
      1. 工具
      1. build文件分析
      1. gradle Task
      1. 依赖

    公众号: https://mp.weixin.qq.com/s/WkwgKyAachnfCxKw3b1BMg
    gradle专栏地址: https://gongshijier.github.io/2021/04/02/Android%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BAGradle%E4%B8%93%E6%A0%8F%E2%80%94%E2%80%94build%E5%9F%BA%E7%A1%80/


    1. 构建体系

    Android 构建系统会编译应用资源和源代码,然后将它们打包成可供您测试、部署、签署和分发的 APK。
    也就是说 构建: 从代码和应用资源到APK的过程
    Android 采用的构建系统是 Gradle 工具, Android 项目架构中的一些和构建相关的文件就是供Gradle构建核心文件

    • build.gradle
    • settings.gradle
    • app/build.gradle
    • app/build.gradle

    通过这些文件执行一系列的 Gradle Task 就完成从源代码和资源文件 ----> APK
    参考下面的 project 目录, 项目中会有多个 module 每个module 内也都有 build.gradle 来负责构建事宜

    2. Build流程

    • 从需要构建的模块开始, 确定依赖项
    • 编译
    • 打包
      编译器: 源代码 --> dex 文件
      打包: 将dex和编译后的资源 组合为 apk 文件 并且使用相应的密钥库来进行签名
      生成最终 APK 前, zipalign 会对APK进行一定优化, 减少内存占用

    3. 工具

    gradle 构建都是通过 gradle 构建工具包实现的
    可以到 sdk目录: Library/Android/sdk/版本/build-tools 下找到对应的工具


    构建过程就是通过gradle脚本使用这些工具, 完成前面说的 编译和打包和优化 图片引用

    图片里面很清楚的说明了构建过程的各个核心流程


    • aapt (Android asset package tool) :负责将xml文件和其他一些资源文件res ... 编译打包应用资源形成供代码访问的一个索引表
    • aidl: 处理使用AIDL规范写的aidl文件, 编译为 java 源代码
    • javac: java --> class 文件
    • d8: class 文件 --> dex 文件
    • zipalign: 字节码对齐工具, 进行优化, 类似垃圾回收标记整理的过程
    • jarsigner: 使用密钥证书 为 apk 签名

    对以上构建工具建议查阅官方资料: https://developer.android.com/studio/command-line?hl=zh-cn

    里面都有详细权威介绍

    4. build文件分析

    settings.gradle

    settings.gradle 文件位于项目的根目录下,用于指示 Gradle 在构建应用时应将哪些模块包含在内。
    比如开源项目bytex settings.gradle 指明了哪些模块参与构建

    //opensource
    include ':shrink-r-plugin'
    include ':access-inline-plugin'
    include ':getter-setter-inline-plugin'
    include ':refer-check-plugin'
    include ':closeable-check-plugin'
    include ':serialization-check-plugin'
    include ':const-inline-plugin'
    include ':field-assign-opt-plugin'
    include ':method-call-opt-plugin'
    include ':SourceFileKiller'
    include ':butterknife-check-plugin'
    
    include ':coverage-plugin'
    project(':coverage-plugin').projectDir = new File('coverage/coverage-plugin')
    include ':coverage-lib'
    project(':coverage-lib').projectDir = new File('coverage/coverage-lib')
    
    

    project/build.gradle

    /**
     * The buildscript block is where you configure the repositories and
     * dependencies for Gradle itself—meaning, you should not include dependencies
     * for your modules here. For example, this block includes the Android plugin for
     * Gradle as a dependency because it provides the additional instructions Gradle
     * needs to build Android app modules.
     */
    
    buildscript {
    
        /**
         * The repositories block configures the repositories Gradle uses to
         * search or download the dependencies. Gradle pre-configures support for remote
         * repositories such as JCenter, Maven Central, and Ivy. You can also use local
         * repositories or define your own remote repositories. The code below defines
         * JCenter as the repository Gradle should use to look for its dependencies.
         *
         * New projects created using Android Studio 3.0 and higher also include
         * Google's Maven repository.
         */
    
        repositories {
            google()
            jcenter()
        }
    
        /**
         * The dependencies block configures the dependencies Gradle needs to use
         * to build your project. The following line adds Android plugin for Gradle
         * version 4.1.0 as a classpath dependency.
         */
    
        dependencies {
            classpath 'com.android.tools.build:gradle:4.1.0'
        }
    }
    
    /**
     * The allprojects block is where you configure the repositories and
     * dependencies used by all modules in your project, such as third-party plugins
     * or libraries. However, you should configure module-specific dependencies in
     * each module-level build.gradle file. For new projects, Android Studio
     * includes JCenter and Google's Maven repository by default, but it does not
     * configure any dependencies (unless you select a template that requires some).
     */
    
    allprojects {
       repositories {
           google()
           jcenter()
       }
    }
    
    • repositories: 指明依赖项目从哪里来, 从哪个仓库导入进来
    • dependencies: 指明具体的 groupID 和 ArtifactID 用来找到具体依赖库
    • buildScript: 这里的依赖是 Gradle 构建时候需要用的, 比如依赖一些库,需要使用他们定义的Gradle插件
      重点注意 buildScript是 Gradle 需要的库, 比如一些 gradle plugin

    比如:

    buildscript {
    
        repositories {
            maven { url 'https://jitpack.io' }
            maven {
                url uri('../gradle_plugins')
            }
            google()
            jcenter()
            maven {
                url "https://plugins.gradle.org/m2/"
            }
        }
        dependencies {
            classpath "com.android.tools.build:gradle:$gradle_version"
    
            //依赖了 com.github.dcendents:android-maven-gradle-plugin 是因为gradle构建阶段需要使用到其内的插件
            classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
        }
    }
    
    // 因为在 buildScript 中 , classpath 依赖了库, 所以可以在项目中可以使用 该 plugin
    apply plugin: 'com.github.dcendents.android-maven'
    
    buildscript {...}
    
    allprojects {...}
    
    // This block encapsulates custom properties and makes them available to all
    // modules in the project.
    ext {
        // The following are only a few examples of the types of properties you can define.
        compileSdkVersion = 28
        // You can also create properties to specify versions for dependencies.
        // Having consistent versions between modules can avoid conflicts with behavior.
        supportLibVersion = "28.0.0"
        ...
    }
    ...
    

    全局 build.gradle 中的 ext 里面定义的一些 变量是全局可用的, 可以在其他模块中访问如:

    android {
      // Use the following syntax to access properties you defined at the project level:
      // rootProject.ext.property_name
      compileSdkVersion rootProject.ext.compileSdkVersion
      ...
    }
    ...
    dependencies {
        implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
        ...
    }
    

    module/build.gradle

    模块下的 build.gradle 配置则是 对该模块生效的一些特性

    /**
     * The first line in the build configuration applies the Android plugin for
     * Gradle to this build and makes the android block available to specify
     * Android-specific build options.
     */
    
    apply plugin: 'com.android.application'
    
    /**
     * The android block is where you configure all your Android-specific
     * build options.
     */
    
    android {
    
      /**
       * compileSdkVersion specifies the Android API level Gradle should use to
       * compile your app. This means your app can use the API features included in
       * this API level and lower.
       */
    
      compileSdkVersion 28
    
      /**
       * buildToolsVersion specifies the version of the SDK build tools, command-line
       * utilities, and compiler that Gradle should use to build your app. You need to
       * download the build tools using the SDK Manager.
       *
       * This property is optional because the plugin uses a recommended version of
       * the build tools by default.
       */
    
      buildToolsVersion "29.0.2"
    
      /**
       * The defaultConfig block encapsulates default settings and entries for all
       * build variants, and can override some attributes in main/AndroidManifest.xml
       * dynamically from the build system. You can configure product flavors to override
       * these values for different versions of your app.
       */
    
      defaultConfig {
    
        /**
         * applicationId uniquely identifies the package for publishing.
         * However, your source code should still reference the package name
         * defined by the package attribute in the main/AndroidManifest.xml file.
         */
    
        applicationId 'com.example.myapp'
    
        // Defines the minimum API level required to run the app.
        minSdkVersion 15
    
        // Specifies the API level used to test the app.
        targetSdkVersion 28
    
        // Defines the version number of your app.
        versionCode 1
    
        // Defines a user-friendly version name for your app.
        versionName "1.0"
      }
    
      /**
       * The buildTypes block is where you can configure multiple build types.
       * By default, the build system defines two build types: debug and release. The
       * debug build type is not explicitly shown in the default build configuration,
       * but it includes debugging tools and is signed with the debug key. The release
       * build type applies Proguard settings and is not signed by default.
       */
    
      buildTypes {
    
        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default Proguard rules file.
         */
    
        release {
            minifyEnabled true // Enables code shrinking for the release build type.
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
      }
    
      /**
       * The productFlavors block is where you can configure multiple product flavors.
       * This allows you to create different versions of your app that can
       * override the defaultConfig block with their own settings. Product flavors
       * are optional, and the build system does not create them by default.
       *
       * This example creates a free and paid product flavor. Each product flavor
       * then specifies its own application ID, so that they can exist on the Google
       * Play Store, or an Android device, simultaneously.
       *
       * If you declare product flavors, you must also declare flavor dimensions
       * and assign each flavor to a flavor dimension.
       */
    
      flavorDimensions "tier"
      productFlavors {
        free {
          dimension "tier"
          applicationId 'com.example.myapp.free'
        }
    
        paid {
          dimension "tier"
          applicationId 'com.example.myapp.paid'
        }
      }
    
      /**
       * The splits block is where you can configure different APK builds that
       * each contain only code and resources for a supported screen density or
       * ABI. You'll also need to configure your build so that each APK has a
       * different versionCode.
       */
    
      splits {
        // Settings to build multiple APKs based on screen density.
        density {
    
          // Enable or disable building multiple APKs.
          enable false
    
          // Exclude these densities when building multiple APKs.
          exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
        }
      }
    }
    
    /**
     * The dependencies block in the module-level build configuration file
     * specifies dependencies required to build only the module itself.
     * To learn more, go to Add build dependencies.
     */
    
    dependencies {
        implementation project(":lib")
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    }
    
    • compileSdkVersion 28 用来编译的 Android API 版本
    • buildToolsVersion "29.0.2" 用来 build 构建的 build-tools 版本

    local.properties

    系统本地环境属性

    gradle.properties

    配置一些全局的配置, 和 ext 闭包一样 可以在其他gradle文件中获得其中配置

    5. gradle Task

    gradle 执行的是一个个 task
    gradle 开发的自定义plugin 也就是重写 apply 方法部分

    每一次 Android 项目构建执行会执行一系列的gradle task 来完成整个构建过程比如:

    可以参考该文章: https://mp.weixin.qq.com/s/6Cb6MqV9GQG60hBltss61A

    Starting Gradle Daemon...
    Gradle Daemon started in 902 ms
    > Task :app:preBuild UP-TO-DATE
    > Task :app:preDebugBuild UP-TO-DATE
    > Task :app:compileDebugAidl NO-SOURCE
    > Task :app:compileDebugRenderscript NO-SOURCE
    > Task :app:generateDebugBuildConfig UP-TO-DATE
    > Task :app:checkDebugAarMetadata UP-TO-DATE
    > Task :app:generateDebugResValues UP-TO-DATE
    > Task :app:generateDebugResources UP-TO-DATE
    > Task :app:mergeDebugResources UP-TO-DATE
    > Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
    > Task :app:extractDeepLinksDebug UP-TO-DATE
    > Task :app:processDebugMainManifest
    > Task :app:processDebugManifest
    > Task :app:javaPreCompileDebug UP-TO-DATE
    > Task :app:mergeDebugNativeDebugMetadata NO-SOURCE
    > Task :app:mergeDebugShaders UP-TO-DATE
    > Task :app:compileDebugShaders NO-SOURCE
    > Task :app:generateDebugAssets UP-TO-DATE
    > Task :app:mergeDebugAssets UP-TO-DATE
    > Task :app:compressDebugAssets UP-TO-DATE
    > Task :app:processDebugJavaRes NO-SOURCE
    > Task :app:mergeDebugJniLibFolders UP-TO-DATE
    > Task :app:mergeDebugNativeLibs UP-TO-DATE
    > Task :app:stripDebugDebugSymbols NO-SOURCE
    > Task :app:validateSigningDebug UP-TO-DATE
    > Task :app:mergeLibDexDebug
    > Task :app:processDebugManifestForPackage
    > Task :app:processDebugResources
    > Task :app:compileDebugKotlin UP-TO-DATE
    > Task :app:compileDebugJavaWithJavac UP-TO-DATE
    > Task :app:compileDebugSources UP-TO-DATE
    > Task :app:mergeDebugJavaResource UP-TO-DATE
    > Task :app:dexBuilderDebug
    > Task :app:mergeExtDexDebug
    > Task :app:mergeProjectDexDebug
    > Task :app:packageDebug
    > Task :app:assembleDebug
    
    BUILD SUCCESSFUL in 22s
    27 actionable tasks: 10 executed, 17 up-to-date
    
    
    //aidl 转换aidl文件为java文件
    > Task :app:compileDebugAidl
    
    //生成BuildConfig文件
    > Task :app:generateDebugBuildConfig
    
    //获取gradle中配置的资源文件
    > Task :app:generateDebugResValues
    
    // merge资源文件
    > Task :app:mergeDebugResources
    
    // merge assets文件
    > Task :app:mergeDebugAssets
    > Task :app:compressDebugAssets
    
    // merge所有的manifest文件
    > Task :app:processDebugManifest
    
    //AAPT 生成R文件
    > Task :app:processDebugResources
    
    //编译kotlin文件
    > Task :app:compileDebugKotlin
    
    //javac 编译java文件
    > Task :app:compileDebugJavaWithJavac
    
    //转换class文件为dex文件
    > Task :app:dexBuilderDebug
    
    //打包成apk并签名
    > Task :app:packageDebug
    

    可以自己run apk 的时候看一下build 窗口中的一系列 gradle task执行过程

    gradle task 是 gradle 流水线执行的节点

    开发中 会针对一些 特定位置运行gradle task

    比如很多 task 是有依赖关系的, 比如 你可以让 taskA , 依赖 taskB
    也可以在buid结束时候添加一些 task
    可以参考: https://blog.csdn.net/ccpat/article/details/89342198简单介绍了一些task

    6. 依赖

    开发中经常接触到就是处理库之间的依赖关系

    常见的依赖方式:

    apply plugin: 'com.android.application'
    
    android { ... }
    
    dependencies {
        // Dependency on a local library module
        implementation project(":mylibrary")
    
        // Dependency on local binaries
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    
        // Dependency on a remote binary
        implementation 'com.example.android:app-magic:12.3'
    }
    

    里面代表了三种依赖源
    本地模块、 jar包、 远程maven仓库


    除了依赖源头, 依赖的方式也很多:

    • implementation
    • api
    • compileOnly
    • runtimeOnly
    • annotationProcessor

    Android项目构建gradle专栏系列持续更新中......

    参考:
    https://developer.android.google.cn/studio/build/index.html
    https://mp.weixin.qq.com/s/6Cb6MqV9GQG60hBltss61A
    https://cloud.tencent.com/developer/article/1392511
    https://www.jianshu.com/p/e73510605c56
    https://developer.android.com/studio/build?hl=zh-cn

    相关文章

      网友评论

          本文标题:Android项目构建Gradle专栏——build基础

          本文链接:https://www.haomeiwen.com/subject/nqpfkltx.html