directory

BuildTypes — buildTypes — buildTypes — buildTypes — buildTypes — buildTypes — buildTypes — buildTypes — buildTypes

One, foreword

Following the previous blog post about the implications of configurable parameters in defaultConfig, today we’ll share another familiar buildTypes.

Second, the buildTypes

BuildTypes also exists under Android in every application-level module, as shown below, and is automatically generated after each project is built.

android {
    buildTypes{
    	release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}}Copy the code

BuildTypes configures the buildTypes we need, such as the “test type” and “native type” we often use, using the following configuration

buildTypes{
    // Publication type
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // Test type, to the tester
    debug {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
    // The local type is used with the backend
    local {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}Copy the code

After adding these configurations, we can now see that android Studio has two more build types: “Debug” and “local”, which will be used when we click “Run”. If the “DEBUG” type is selected and we run the code at this time, it is the configuration parameter under DEBUG.Of course, running compiled to APK is no exception, each using its own type of configuration.

The three build types “release”, “debug”, and “local” are actually the three buildTypes, and the parameters that buildType can set are what we’re going to clarify today.

Third, buildType

BuildType official document portal

BuildType exists in form

As we know from the last blog post, each configuration will eventually be mapped to a class, or to a property, or to a method. BuildType is no exception, he will be mapped to com. Android. Build. Gradle. Internal. DSL. BuildType, inheritance structure is as follows

If we look at the inheritance structure of DefaultConfig again, we can see that both inherit to the BaseConfigImpl class, indicating that there will be some overlap between the two. This is why, when we look at gradle files, it feels like a configuration parameter can appear everywhere (more on this later to clear up the confusion).

2. The meaning of attributes in buildType

Let’s start with a convention to avoid using too much verbose code.

buildTypes{
    debug {
	// Our following "how to Use" code is based on this section unless otherwise specified.}}Copy the code

2.1 applicationIdSuffix

  • Type: String
  • Description: Is appended to the applicationId string to form the final package name.
  • It’s worth mentioning that this property is also available in defaultConfig, but is not generally used. Instead, it is used in buildTypes, which allows you to have different package names and install multiple types of applications at the same time. For example, the release, debug, and Local packages mentioned above can all exist at the same time without overwriting them for easy debugging.
  • Usage:
debug {
    applicationIdSuffix '.debug'
}
Copy the code

2.2 consumerProguardFiles

  • Type: List< File >
  • Description: This property only applies to those we createdlibraryThis includes libraries that we import as AArs or create directly. What it does is,Is responsible for obfuscation rules when the library is compiled, we can no longer manage the obfuscation rules of each library under the module of the main App, and can directly use the obfuscation rule files of each library.
  • It’s worth mentioning that the difference between this property and proguardFiles is that consumerProguardFiles are imported as obtruse files by the main App module, while proguardFiles are not.
  • Usage:
debug {
    consumerProguardFiles 'consumer-rules.pro'. Omit other configurations}// Since this attribute is of type List
      
       , if multiple File configurations are required, it is shown below
      
debug {
    consumerProguardFiles 'consumer-rules.pro'.'zincPower-rules.pro'. Omit other configurations}Copy the code

2.3 crunchPngs

  • Types: Boolean
  • Description: Whether to compress PNG images. When set to true, PNG resources that are not optimally compressed are compressed, but it also increases build time.
  • Note: By default, release is enabled and DEBUG is disabled.
  • Usage:
debug {
    crunchPngs false. Omit other configurations}Copy the code

2.4 debuggable

  • Types: Boolean
  • Description: Whether the application can be debugged.
  • It’s worth mentioning that the build type of release defaults to undebugger, which is false. Debug is true by default. Debugging failure means that the “bug” mark in the image below does not enable the application to start, whereas normal operation is ok.

  • Usage:
debug {
    debuggable true
}
Copy the code

2.5 javaCompileOptions

  • Type: JavaCompileOptions
  • Description: Configures some parameters of Java at compile time, such as the ones we useannotationProcessorIs required.
  • Usage:
debug {
    javaCompileOptions {
        annotationProcessorOptions{
    		arguments = []
    		classNames ' '. }}... Omit other configurations}Copy the code

JavaCompileOptions Specifies parameters that can be configured. Please enter the portal

2.6 jniDebuggable

  • Types: Boolean
  • Description: Whether the native code of the application can be debugged
  • Note: The build type of release defaults to undebugable native code, which is false. By default, debug is true to debug native code. Failure to debug native code means that the code will not be “stopped” even if a breakpoint is made in a native method.
  • Usage:
debug {
    jniDebuggable true
}
Copy the code

2.7 manifestPlaceholders

  • Type: Map
    ,>
  • Description: Configuration is available inAndroidManifest.xmlThe parameters used in.
  • Usage:

We want to configure the logo of our application as the logo of the test version, so that testers can distinguish between different types of packages. We can use the following paragraph in Gradle

debug {
    manifestPlaceholders = [APP_LOGO_ICON: "@mipmap/ic_logo"]}Copy the code

Then use it in androidmanifest.xml, using ${the name of the variable you configured}

// To use replacement in the application, add the tools:replace tag and write the name we need to replace, such as android:icon here<application
    android:allowBackup="true"
    android:icon="${APP_LOGO_ICON}"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:replace="android:icon">.Copy the code

2.8 minifyEnabled

  • Types: Boolean
  • Description: Whether to enable obfuscation, code optimization. True starts, false closes.
  • Usage:
debug {
    minifyEnabled true
}
Copy the code

2.9 proguardFiles

  • Type: List< File >
  • Description: Configures obfuscation rules file, onlyminifyEnabledThis parameter is used when it is set to true, and the file must state which files are not optimized or obfuscated.
  • It is worth mentioning that the class name and method name will fail because of the obfuscation of the back-end code, so we need to declare that they are not obfuscated. (This is just an example of a scenario in which this parameter is used. If the application is normal, and the obfuscation is turned on, there is a strange bug, then consider whether the obfuscation caused the bug.)
  • Usage:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
Copy the code

2.10 multiDexEnabled

64K reference restriction issue official document portal

  • Types: Boolean
  • Description: Whether subcontracting is enabled. Because the method index value in Android is a two-byte, four-digit hexadecimal value, namely [0, 0xFFFF], the maximum number of methods is 65536. Once we exceed that, we need to subcontract, so we need to turn this parameter on.
  • Usage:
android{
    buildTypes {
    	debug {
    		multiDexEnabled true. }}}// Add dependencies
dependencies {
    // If you are using AndroidX, use the following import
    / / implementation 'androidx. Multidex: multidex: 2.0.1'
    // If you are not using AndroidX, use the following paragraph
    compile 'com. Android. Support: multidex: 1.0.3'
}
Copy the code

There are two ways to start MultiDex:

// Make your Application inherit from MultiDexApplication.
public class MyApplication extends MultiDexApplication {}// Second: override the Application method attachBaseContext
public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this); }}Copy the code

Finally, don’t forget to use our Application above in androidmanifest.xml.

2.11 multiDexKeepFile

  • Type: the File
  • Description: Package the classes we need into the main package, i.eclasss.dex. We share in 2.10 that we use multi-package processing, and sometimes we need to pack some major classes into the main package, so we can use this property.
  • Usage:
debug {
    multiDexKeepFile file('multidex-config.txt')... }Copy the code

In multidex-config. TXT, each file contains one line

com/example/MyClass.class
com/example/TestClass.class
Copy the code

2.12 multiDexKeepProguard

  • Type: the File
  • Description: Package the classes we need into the main package, the same function as in 2.11, the difference is the writing.
  • Usage:
debug {
    multiDexKeepFile file('multidex-config.pro')... }Copy the code

Multidex-config. pro is written as follows

Com.example package -keep class com.example.** {*; }Copy the code

2.13 the name

  • Type: String
  • Description: The name of the build type.
  • Usage:
// debug is assigned to the name attribute, and name is final and cannot be changed.
debug{
    ...
}
Copy the code

2.14 pseudoLocalesEnabled

  • Types: Boolean
  • Description: This property is used to turn on the pseudo-language to find potential localizable problems in the UI.
  • Usage:

Step 1: We enable this property in the configuration

debug{
    pseudoLocalesEnabled true
}
Copy the code

Step 2: Install our app Step 3: Go to Settings -> System -> Languages and Input methods -> Languages -> Add Languages

On the “Add Language” page, you will see the options shown in the following image. Select the contents in the red box in the image, and the differences are also indicated in the image. Let’s go down to see what the differences are.

The child’s test machine is the Honor 8, which varies slightly from machine to machine

After selection, different languages will have different effects, as shown in the figure (1). (2) In the middle, Pseudo locale (equivalent to En-XA) was selected; (3) On the right, select Bidirection test locale (equivalent to EN-XB);

2.15 renderscriptDebuggable

  • Types: Boolean
  • Description: Whether renderScript code can be debugged
  • Usage:
debug {
    renderscriptDebuggable true
}
Copy the code

2.16 renderscriptOptimLevel

  • Types: int
  • Description: Sets the rendering script level
  • Usage:
debug {
    renderscriptOptimLevel 3
}
Copy the code

2.17 shrinkResources

ShrinkResources Official User manual portal

  • Types: Boolean
  • If this option is enabled, Gradle removes unused resources at compile time.
  • Note: minifyEnabled is also required to enable shrinkResources, otherwise minifyEnabled will not run.
  • Usage:
debug {
    shrinkResources false
}
Copy the code

After this function is enabled, the following logs are displayed

2.18 signingConfig

  • Type: SigningConfig

SigningConfig configurable parameter portal

  • Description: Configure signature configuration. Apk package can be installed only when it needs to be signed. When we run it directly, we use the default signing certificate of the system. When we want to release the package, we need to use the signature of individuals or enterprises.
  • Usage:
buildTypes {
    release {
        signingConfig {
    	    // It is not recommended to write the information about the signed certificate here. Instead, it should be in the properties file to introduce it into use
            config {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']}}... }}Copy the code

2.19 testCoverageEnabled

  • Types: Boolean
  • Description: Test coverage, you can get a report on test coverage
  • Note: Remember to set minifyEnabled to false, otherwise the report will also appear with a confused class name.
  • Usage:

Step 1: Enable testCoverageEnabled in build.gradle

debug {
    testCoverageEnabled true
}
Copy the code

Step 2: Connect to an available device, because the test code we are executing is device-based. If we do not connect, the following error will be reported during the test phaseStep 3: Enter the following command in the Android Studio Terminal to view all runnable tasks.

Kids are MAC environment, so./gradlew starts. For Windows, use Gradlew directly.

./gradlew app:tasks
Copy the code

After you enter a run, you can see the runnable task highlighted in the figure.We run it in camel form (that is, the first letter plus the first letter of each subsequent word in uppercase) as follows

// create + your build type name (debug in this case) + CoverReport
./gradlew app:cDCR
Copy the code

After running, it’s time to view the test report. We enter the Coverage directory, and the specific path is shown in the figure below.Finally, open the index.html file with the browser, and you can see the report, as shown in the figure below. Because there is no test code written for the child’s project, the coverage is 0.

2.20 useProguard

  • Types: Boolean
  • Description: Enabled Always enable ProGuard
  • Usage:
debug {
    useProguard true
}
Copy the code

2.21 versionNameSuffix

  • Type: String
  • Description: Appended after versionName
  • Usage:
debug {
    // If versionName is "1.0.0", the final version is named 1.0.0.test
    versionNameSuffix ".test". }Copy the code

2.22 zipAlignEnabled

  • Types: Boolean
  • Description: Whether to enable zipAlign. The application is byte aligned, which reduces the memory consumed by running the application.
  • Usage:
debug {
    zipAlignEnabled true. }Copy the code

2.23 matchingFallbacks

  • Type: List< String >
  • Description: Used to handle BuildType conflicts between locally dependent libraries.

MatchingFallbacks can also deal with dimensional flavors, but we’ll leave that out for a future article.

  • Usage:

A thing is created to solve at least one problem, so we need to understand how the problem arises.As shown above, our main Module(usually App) has three build types: “Release”, “debug”, and “local”, which we mentioned at the beginning.

At this point we added a module named Library to the project and relied on it in our app. When we build both “Release” and “debug” builds, we don’t have any problems because the Library also provides both builds by default.

However, when we use ‘local’, this becomes a problem because gradle scripts also default to ‘local’ in ‘library’, which is not in ‘Library’. The following error is reported

ERROR: Unable to resolve dependency for ':app@local/compileClasspath': Could not resolve project :lib:library.
Show Details
Affected Modules: app
Copy the code

At this point, you need to help “Local” select an available build type from “Library,” which is set via matchingFallbacks.

Gradle: Build. Gradle: build. Gradle: build. Gradle: build. Gradle: build. Gradle: build.

local{
    matchingFallbacks = ['zinc'.'release']... }Copy the code

For example, if ‘zinc’ fails to match, it will match ‘release’. If ‘release’ does match, it will use it to break any subsequent matches.

3. Meaning of methods in buildTypes

3.1 buildConfigField (type, name, value)

  • Description: We can add values to the BuildConfig class, which will eventually add the following line of code to BuildConfig.
// The value of a value is left as is
<type> <name> = <value>
Copy the code
  • Usage:
debug {
    // This can be obtained by BuildConfig
    buildConfigField('String'.'name'.'"zinc"')
    buildConfigField('int'.'age'.'26')... }Copy the code

This results in the configuration shown below, which we can obtain with the following code

String name = BuildConfig.name;
int age = BuildConfig.age;
Copy the code

The value of theta is thetaWhen we set parameters of type String, we need to enclose “” in quotes (as in the example for the name attribute). Remember that!

3.2 consumerProguardFile (proguardFile)

  • Description: consumerProguardFiles has the same effect as the 2.2 dot property shared above. Only one obfuscation file can be set here.
  • Usage:
debug {
    consumerProguardFile('consumer-rules.pro')}Copy the code

3.3 consumerProguardFiles (proguardFiles)

  • Description: consumerProguardFiles does the same thing as the 2.2 dot property shared above, but is also multiple obfuscation files.
  • Usage:
debug {
    consumerProguardFile('consumer-rules.pro'.'zincPower-rules.pro',...). }Copy the code

3.4 externalNativeBuild (action)

  • Type: ExternalNativeBuildOptions
  • Here we set some parameters for the NDK compilation process. It can be divided into cmake and ndkBuild parameters.
  • Usage:
debug {
    externalNativeBuild {
        ndkBuild {
            // Passes an optional argument to ndk-build.
            arguments "NDK_MODULE_PATH+=.. /.. /third_party/modules"
        }
        // For ndk-build, instead use the ndkBuild block.
        cmake {
             // Passes optional arguments to CMake.
             arguments "-DANDROID_ARM_NEON=TRUE"."-DANDROID_TOOLCHAIN=clang"
        
             // Sets a flag to enable format macro constants for the C compiler.
             cFlags "-D__STDC_FORMAT_MACROS"
        
             // Sets optional flags for the C++ compiler.
             cppFlags "-fexceptions"."-frtti"
        
             // Specifies the library and executable targets from your CMake project
             // that Gradle should build.
             targets "libexample-one"."my-executible-demo"}}}Copy the code

Cmake Specific parameter portal ndkBuild Specific parameter portal

3.5 initWith (that)

  • Description: Copies the given buildType (that is, the value of the argument)
  • Usage:
buildTypes {
    debug{
    }
    local{
    	// The debug configuration is copied
        initWith debug{
          	// Do our own configuration here}}}Copy the code

3.6 proguardFile (proguardFile)

  • Description: Add obfuscation file, and 2.9 small point function is the same, but the passed is a file, here will not repeat the description
  • Usage:
 debug {
    proguardFile 'proguard-rules.pro'
}
Copy the code

3.7 proguardFiles (files)

  • Description: Add obfuscation file, same as 2.9 dot function, not to repeat here
  • Usage:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
Copy the code

3.8 setProguardFiles (proguardFileIterable)

  • Description: Add obfuscation file, same function as 2.9 dot, but written slightly different, not to repeat here
  • Usage:
debug {
    proguardFiles = [getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro']}Copy the code

3.9 resValue (type, name, value)

  • Description: Add a value resource
  • Usage:
debug {
    // Add to res/value, obtained by r.string.age
    resValue('string'.'age'.'12 years old')}Copy the code

Write at the end

Gradle configuration files look messy because we didn’t comb through them. A lot of configuration is not useless, but we did not have an overall understanding of him, is the so-called “ignorance is the most terrible”.

If you like, please give me a like and follow me. If there is anything wrong in the article, please discuss it with me in the comments section and make progress together.

Project address: Portal