Android Gradle Complete Guide

Source: Internet
Author: User
Tags jcenter

Why do you need to learn gradle?

Gradle is now the mainstream of Android compiler tools, although the Gradle appear before and after the corresponding faster compiler tool appears, but the advantage of Gradle is that it is a pro-son, Gradle is really slow, this and its compilation process, but now the Gradle The compilation speed has been doubled. In addition, relative to other compiler tools, most importantly, he and Android studio is very close, can say that for some simple programs we almost do not need any code on the configuration of the only use of Android Studio can be done to compile and run.

But for some of the more complex, especially multi-team projects, we will need some personalized configuration to improve our development efficiency. For example, we want to customize the name of the compiled APK package, and for some special products we may want to compile the APK with the same project 免费版 付费版 . These advanced features require us to modify the configuration code in a customized manner.

Recently, with the release of Android Studio2.0, Gradle also made a very big upgrade, called Instant Run. It's compiled at a speed of two words on the internet to describe. When we first clicked the Run, the Debug button, it ran the same time as we always did. But in the next time, every time you modify the code after clicking on the Run, the Debug button, the corresponding changes will be quickly deployed to the program you are running, the legend is faster than you can focus on the phone screen, it has made the corresponding changes. But it seems that the compatibility of some projects is not very good, and now do not know how to upgrade.

Why do you want to know about command-line compilation?

In many cases we are using Android Studio to build and debug the project. Android Studio can meet most of the requirements we develop, but in some cases the command line allows us to compile more efficiently and with more clarity, and some advanced configurations need to be familiar with the command line to be able to use, such as when the server is compiled, and when some projects are initialized, they are delivered directly to Android Studio, it'll always be loading, you don't know what it's doing, but with the command line you'll know which link it's stuck in, and you just need to change some code to compile it right away.

What can we do after we know Gradle?

We can do everything and what we want.

    • Custom compiled output file format.
    • Hook Android compilation process.
    • Configuring and improving Gradle compilation speed

Gralde Overview

History

We know that the Android build process is very complex:

We need a tool that will help us compile the Android program faster and more conveniently and concisely. Now combined with Android Studio we generally use the tools are Gradle, before the advent of Gradle, Android also has a corresponding compiler tool called Ant, after the advent of Gradle, there are new compiler tools appear, is Facebook's buck tool. These compile tools are almost always faster than Gradle when they occur, and Gradle's slowness is very much related to its compilation cycle.

Compilation Cycle of Gradle

Before parsing the Gradle compilation process, we need to understand the two objects that are very important in Gradle. Project and task.

Each project is compiled with at least one project, one build.gradle representing one project , each project containing more than one, and the task task contains many action , action a block of code that contains the code that needs to be executed.

During the compilation process, Gradle aggregates all project and executes the action in the task according to the build-related files task . Because there are build.gradle so many in the file task , it takes a logic to execute which one executes it first. This logic is dependent logic, and almost all of the tasks need to depend on other tasks to execute, and the task that is not dependent will be executed first. So to the last of all the tasks will constitute a directed acyclic graph (DAG Directed acyclic graph) data structure.

The compilation process is divided into three stages:

    • Initialization stage: Create a Project object, and if you have more than one build.gradle, you will also create multiple project.
    • Configuration phase: At this stage, all the compilation scripts are executed, and all of project's tasks are created, preparing for the latter phase.
    • Execution phase: At this stage, Gradle determines how these tasks are executed based on the parameters passed in, and the actual execution code for the action is here.

Declined reprint, do not want to reprint, please specify the source http://www.jianshu.com/p/9df3c3b6067a

Just now we mention some of the relevant files when compiling Gradle, let's parse these files in a minute.

Gradle Files

For a Gradle project, the most basic file configuration is as follows:


A project has one setting.gradle , including a top-level build.gradle file, and each module has its own build.gradle file.

    • Setting.gradle: This setting file defines which module should be added to the compilation process, and for a single module The project can not need this file, but for the Multimodule project we need this file, otherwise Gradle I don't know which projects to load. The code for this file is executed during the initialization phase.
    • Top-level Build.gradle: The configuration of the top-level build.gradle files will eventually be applied to all projects. It is typically configured as follows:
buildscript {    repositories {        jcenter()    }    dependencies {        ‘com.android.tools.build:gradle:1.2.3‘    }}allprojects{    repositories{        jcenter()    }}
    • Buildscript: Defines the classpath of the Android compilation tool. repositories, jCenter is a well-known Maven repository.
    • Allprojects: The attributes defined in the are applied to all moudle, but in order to ensure the independence of each project, we generally do not operate too many common things in this area.

    • Individual Build.gradle per project: For each moudle configuration, if the options defined here are the same as those defined in the top level build.gradle , the latter will be overwritten. Typical configuration content is as follows:

    • Apply plugin: The first line of code applies the Android program's Gradle plugin, which is required as an Android application, as it plugin provides all the tasks for Android compilation, testing, packaging, and so on.
    • Android: This is the largest code block in the compilation file, all the special configurations about Android are here, which is also provided by the plugin of our previous statement.
      • defaultConfigIs the default configuration of the program, note that if the AndroidMainfest.xml same attribute is defined here, it will be dominated here.
      • The most important thing to note here is the applicationId option: In our definition AndroidManifest.xml , there are two uses for the package name: one is the unique ID of the program, to prevent two identical programs on the same phone, and the other is R the package name for our resource class. In the past, we modified this ID to cause all references to the R resource class to be modified. But now if we modify applicationId only the current program's ID, but not to modify the source file references.
    • Buildtypes: Defines the compilation type, for each type we can have a different compilation configuration, different compilation configuration corresponding to the different compilation commands. The default type is debug, release.
    • Dependencies: is a dependency configuration that belongs to Gradle. It defines the other libraries that the current project needs to rely on.
Gradle Wrapper

Gradle constantly in the development, the new version will inevitably have some backward compatibility issues with previous projects, this time, gradle wrapper came into being.

GRADLW wrapper contains some script files and files for running under different systems. Wrapper is version-sensitive, but does not require you to manually download, when you run the script, if the local does not automatically download the corresponding version of the file.

Scripts executed under different operating systems are executed under the MAC system ./gradlew ... and compiled under Windows gradle.bat .

If you are transitioning directly from an Eclipse project, the program does not automatically create the wrapper script and we need to create it manually. Enter the following command at the command line

gradle wrapper --gradle-version 2.4

It will create the following directory structure:

Wrapper is the beginning of our use of command-line compilation. Let's look at what the wrapper does.

Gradle Basics

Gradle will generate different tasks based on the configuration of the build file, and we can execute each task directly individually. By ./gradlew tasks listing all the tasks. You can use it if you want to also list the other tasks that each task corresponds to ./gradlew tasks -all .

In fact, every time we click on the Build,rebuild,clean menu in Android Studio, we are doing some gradle task.

Android Tasks

With four basic tasks, Android inherits their own implementations separately:

    • Assemble: Generate APK package for all buildtype.
    • Clean: Remove all compiled output files, such as apk
    • Check: Performs a lint detection compilation.
    • Build: Simultaneous execution assemble and check command

These are basic commands that, depending on the configuration in the actual project, will have different dependencies on those tasks. For example, the default assmeble will rely on Assembledebug and assemblerelease, if executed directly assmeble , will eventually compile debug, and release all versions out. If we just need to compile the debug version, we can run it assembleDebug .

In addition to some common new commands, such as the Install command, the compiled APK will be installed on the connected device.

Many of the commands we run are output to the command line, and build a run report is produced under the folder. For example check , commands are generated lint-results.html. in build/outputs .

Configuration

Buildconfig

This class believes that we are not unfamiliar, the most common use is BuildConfig.DEBUG to determine whether the current version is the debug version, if it is to output some only in the debug environment will do the operation. This class is generated by gradle based on the configuration file. Why Gradle can directly generate a Java bytecode class, thanks to our Gradle's writing language is groovy, groovy is a JVM language, the JVM language is characterized by, although the syntax is different, but they will eventually programming JVM bytecode files. The same is the JVM language and Scala,kotlin and so on.

This feature is very powerful, we can set some key-value pairs here, these key-value for different compiled type of APK value is different, such as we can for debug and release two environments defined different servers. Like what:

In addition, we can also set different resource files for different compilation types, such as:

Repositories

Repositories is the code warehouse, this is believed we all know, we usually add some dependency is downloaded from here, Gradle support three types of warehouses: Maven,ivy and some static files or folders. During the execution phase of the compilation, Gradle will take the corresponding dependent files from the repository, and of course, Gradle will have its own cache locally, and will not take these dependencies every time.

Gradle support a variety of Maven repositories, generally we are in common with the jCenter can.
There are some projects that may be in the private warehouse of some companies, when we need to manually join the warehouse connection:

If the repository has a password, you can also pass in the user name and password at the same time

We can also configure the local repository with a relative path, and we can configure the static folders that exist in the project as a local repository:

Dependencies

When we reference the library, each library name contains three elements: 组名:库名称:版本号 , as follows:

If we want to ensure that the library we rely on is always up-to-date, we can add wildcards by adding a wildcard character, such as:

But we generally do not do so, in addition to every compile to do the network request to see if there is a new version of the compiler is slow, the biggest disadvantage is that we used the version is very difficult to test version, performance is not guaranteed, so we must refer to the library when the dependency version.

Local dependencies

File dependencies

Through the files() method can add file dependencies, if there are many jar files, we can also fileTree() add a folder through the method, in addition, we can also be added by means of wildcard characters, as follows:

Native Libraries

Configure the local .so library. Make the following configuration in the configuration file, then set up the folder in the corresponding location and add the files to the corresponding platform .so .

The file structure is as follows:

Library projects

If we are going to write a library project so that other projects are quoted, our Bubild.gradle plugin cannot be Andrid plugin, which needs to be referenced as follows plugin

apply plugin: ‘com.android.library‘

Refer to it in the setting file include .

If we are not comfortable referencing the project directly and need to refer to it as a file, we can also package the project into a aar file, note that in this case we create a new folder under the project arrs and configure the warehouse in the Build.gradle file:

When you need to refer to an item in it, refer to it in the following way:

Build variants

In development we may have this requirement:

    • We need to configure different server addresses in debug and release two cases;
    • When playing the market channel package, we may need to play the free version, the paid version, or the internal version, the external version of the program.
    • Channel first package usually requires the logo of the channel to be added on the Welcome page. Wait a minute
    • In order for the market version and the debug version to exist simultaneously with a mobile phone, we need to compile the time automatically to the debug version of the package name.

These requirements need to be dynamically compiled to output different styles of apk files based on the current compilation type. It's time for us to do our thing buildType .

Build Type

Android defaults to two compilation types with Debug and release. For example, we now have a new statging compilation type

Source Sets

Whenever a new build type is created, Gradle creates a new source set by default. We can create main folders with the same sibling folder, depending on the type of compilation we can choose to replace some of the source code directly.

In addition to the code can be replaced, our resource files can also be replaced

Other than that, we can rely on different types of projects, for example, if I need to use a different log framework in staging and debug two versions, we configure:

Product Flavors

We are all in front of the same source code to compile the different types of the same program, if we need to compile different programs for the same source code (the package name is also different), such as free version and pay version. We just need to Product flavors .

Note that the Product flavors and build type are not the same, and their properties are different. All product flavor versions and Defaultconfig share all attributes!

Like build type, product flavor can have its own folder as well source set . In addition, the product flavor and build type can be combined, and the file priority in their folders is even higher than the priority of the individual built type and product flavor folders. If you want to have different icons for the release version of the blue type, we can create a folder called blueRelease , note that this order can not be wrong, must be flavor+buildtype form.

In more complex cases, we may need to combine the dimensions of multiple product, such as I want color and price two dimensions to build a program. This is where we need to use flavorDimensions :

Based on our configuration, we look at our task again and discover that these tasks are more:

Resource Merge Priority

The resources defined in build type have the highest priority, and the resources defined in the library have the lowest priority.

Signing configurations

If we are packing the market edition, we need to enter our KeyStore data. If it is a debug version, the system will help us configure this information by default. This information is configured in the Gradle signingConfigs .


After the configuration we need to use it directly in the build type

Optimizespeeding up Multimodule Builds

You can speed up the compilation of Gradle in the following ways:

    • Turn on Parallel compilation: set in the project root directory gradle.properties
org.gradle.parallel=true
    • Turn on the compile daemon: The process is always there after the first boot, and you can reuse the process when you compile two times. The same is gradle.properties set in.
org.gradle.daemon=true
    • Increase available compiled memory:
org.gradle.jvmargs=-Xms256m -Xmx1024m
Reducing APK file

At compile time, we may have a lot of resources and not use, at this time we can shrinkResources optimize our resource files, remove those unnecessary resources.

If we need to look at the command to help us reduce the amount of useless resources, we can also run a shrinkReleaseResources command to view the log.

In some cases, some resources need to be loaded in a dynamic way, and I need to keep our resources like Progard. The way to do this is to res/raw/ create a keep.xml file below and keep the resource by:

Manual shrinking

For some special files or folders, such as International resource files, screen adaptation resources, if we have identified a model, and do not need to be re-adapted, we can directly remove the resources that cannot be adapted. This is useful when customizing the app for the manufacturer's adaptation model. The procedure is as follows:
For example, we may have a lot of international resources, if we use the scenario only english,danish,dutch resources, we can directly specify our resConfig :

We can do that for size files, too.

Profiling

When we execute all the tasks we can --profile generate a copy of the execution report in by adding parameters reports/profile . Examples are as follows:

We can tell from this report which project takes the most time and which is the most time consuming.

Practice

In the development process, we may encounter a lot of situations that require us to define our own task, before customizing the task, let's take a simple look at groovy's syntax.

Groovy

The Build.gradle configuration files we saw earlier, unlike the configuration files of XML and so on, can be said to be executable code, but their structure seems to be easy to understand, and the configuration file is no different, which is why Google chose groovy. In addition, groovy is a JVM language, that is, groovy code will eventually be compiled into the JVM bytecode, to the virtual machine to execute, we can also directly decompile these bytecode files.

Here's a brief look at groovy syntax.

Variable

In groovy, there are no fixed types, and variables can be def referenced by keywords, such as:

def name = ‘Andy‘

When we refer to a string of strings by single quotation marks, this string is purely a string, but if you use double quotation marks, the interpolation operation is also supported in the string.

def name = ‘Andy‘def greeting = "Hello, $name!"
Method

Like Python, def a method is defined by a keyword. method if you do not specify a return value, the value of the last line of code is returned by default.

def square(def num) { num * num}square 4
Class

Groovy also defines a class through groovy:

class MyGroovyClass {    String greeting    String getGreeting() { return ‘Hello!‘ }}
    • In groovy, all classes and methods are the default, and the pulic fields for all classes are the same private ;
    • Like Java, we new get an instance of the class by keyword, using def a reference to the accepted object:def instance = new MyGroovyClass()
    • and the fields declared in the class will generate the corresponding Setter,getter method by default. So the above code can be called directly instance.setGreeting ‘Hello, Groovy!‘ , note that groovy's method call can be without parentheses, and does not require a semicolon ending. In addition, we can even call directly;
    • We can get the instance.greeting value of the field directly in this way, but it's also going through its get method, and it's not getting that value directly.
Map, collections

In Groovy, the definition of a list is this:

List list = [1, 2, 3, 4, 5]

Traversing a list is like this:

list.each() { element ->println element}

Defining a map is this:

Map pizzaPrices = [margherita:10, pepperoni:12]

To get a map value is this:

pizzaPrices.get(‘pepperoni‘)pizzaPrices[‘pepperoni‘]
Closed Package

There is a concept of closures in groovy. Closures can be understood as anonymous inner classes in Java. Closures support similar lamda forms of syntax invocation. As follows:

def square = { num ->    num * num}square 8

If there is only one parameter, we can even omit this parameter, which is used by default it as a parameter, and the last code is this:

Closure square = {    it * it}square 16

After we understand the syntax of the closures, we will find that in our previous configuration file, the android dependencies code blocks that followed immediately are a closure.

Groovy in Gradle

After knowing the basic syntax of groovy, let's take a look at the code inside Gradle to understand more.

    • Apply
      apply plugin: ‘com.android.application‘
      This code is actually called the method of the project object apply , passing in a plugin map as key. The complete write-up is this:
project.apply([plugin: ‘com.android.application‘])
    • Dependencies
      What we see is this:

The actual call will pass in a DependencyHandler closed packet, the code is as follows:

Task
    • Create a task

Run the task

./gradlew hello

Note: As we said earlier, Gradle's life cycle is divided into three steps, initialization, configuration, and execution. The above code has been executed during the configuration process, so the printed string occurs before the task executes, and the code in the execution phase to execute the task should be set as follows:

    • Add action: Previously we said that the task contains a series of actions, and when the task is executed, all actions are executed sequentially. If we want to add our own action, we can do it by means of a carbon copy doFirst() doLast() .

Print it out like this:

    • Task dependency: As we said earlier, the relationship between tasks is a dependency, and there are two kinds of dependencies on task, must RunAfter and dependsOn . Like what:
task task1 <<{    printfln ‘task1‘}task task2 <<{    printfln ‘task2‘}task2.mustRunAfter task1

And

task task1 <<{    printfln ‘task1‘}task task2 <<{    printfln ‘task2‘}task2.dependsOn task1

The difference is that, when running, the former must be executed in order to gradlew task2 task1 be executed successfully, otherwise each task is executed separately, the latter can gradlew task2 perform two tasks simultaneously.

Practice

We can use two examples to practice task.

KeyStore Protection

Here directly to the store password plaintext written here for the security of the product is not very good, especially if the source source, others can use your ID to publish the app. In this case, we need to build a dynamic load task, when compiling release source code from local files (not git) to obtain keystore information, as follows:

You can also set an insurance policy, in case we do not find the corresponding file requires the user to enter the password from the console

Finally set the final value

Then set the release task to depend on the task we just set

Rename apk by hook Android compilation plugin

The last compiled apk name is similar app-debug-1.0.apk .


From: http://www.jianshu.com/p/9df3c3b6067a

Android Gradle Complete Guide

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.