What have you learned after reading this article?
- Familiar with gradle build configuration
- Familiarize yourself with the directory structure of your code build environment; you know more than just SRC /main
- Development, build, and so on can be packaged arbitrarily
- Multi-channel packaging
- APK output file configuration
demand
We usually have debug and release environments for development, but what if you want to separate beta 1, beta 2, and so on?
This relies on the power of Gradle for configuration.
You can also refer to Google’s official documentation for configuration.
Configuring build TypesbuildTypes
* We usually package for different build environments, such as debug, release, beta, etc., which we call buildTypes.
You can create and configure build types inside the Android {} code block in the module-level build.gradle file. When you create a new module, Android Studio automatically creates the debug and publish build types for you. Although the debug build type does not appear in the build profile, Android Studio configures it to Debuggable True. This way, you can debug your application on a secure Android device and configure APK signing using a common debug keystore.
If you want to add or change specific Settings, you can add debug build types to your configuration. The following example specifies applicationIdSuffix for the debug build type and configures a JNidebug build type initialized with the Settings in the debug build type.
ApplicationIdSuffix: Field indicates that you suffix your default program ID (package name) without changing it. For example, if your package name is com.rae.app, and you want to distinguish between test packages and formal packages, set applicationIdSuffix to.debug, and your app’s package name becomes com.rae.app.debug
android { ... defaultConfig {... } buildTypes { release { minifyEnabledtrue
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix ".debug"
}
/** * The 'initWith' property allows you to copy configurations from other build types, * so you don't have to configure one from the beginning. You can then configure * just the settings you want to change. The following line initializes * 'jnidebug' using the debug build type, and changes only the * applicationIdSuffix and versionNameSuffix settings. */
jnidebug {
// This copies the debuggable attribute and debug signing configurations.
initWith debug
applicationIdSuffix ".jnidebug"
jniDebuggable true}}}Copy the code
Build the source set
Noun resolution: The source code is usually stored in the SRC /main folder, but you want to be able to differentiate the source files based on the build type (e.g. debug, release), so that the corresponding folder is a different build source. For example, debug is built from SRC/DEBUG, release is built from SRC /release, and SRC /main is defined as a common resource, which is merged at build time.
See the official documentation for more information.
Android Studio logically groups the source code and resources for each module into a set of sources. The main/ source set of a module contains the code and resources shared by all of its build variants. Other source set directories are optional, and Android Studio does not automatically create these directories for you when you configure new build variants. However, creating a source set like main/ helps keep the files and resources that Gradle should only use when building a particular version of the application in order:
Build sources are named as follows:
ProductFlavor represents the channel package, as shown in the multichannel package below
-
SRC /main/ This source set contains code and resources shared by all build variants.
-
SRC /
/ create this source set to add code and resources specific to a particular buildType. Example: the SRC/jnidebug
-
SRC /
/ create this source set to add code and resources specific to a specific productFlavor. For example baidu channel package: SRC /baidu -
SRC /
/ Create this source set to add code and resources specific to a particular build variant.
For example, to generate a “fully debugged” version of an application, the build system incorporates code, Settings, and resources from the following set of sources. For example, Baidu’s development environment package is SRC /baiduDebug
Build type dependency configuration
Most of the time, we will separate the SDK or API interface into a library, which is usually divided into production environment and test environment, but when we rely on it, we will refer to it like this: Compile project(‘: SDK ‘), such that the dependent environment is release, not when testing the environment during debugging. We’ll have to do it another way:
<buildType>
Compile project()
This will depend on different packages for different build types, such as our test environment dependencies :debugCompile Project (‘: SDK ‘), and jnidebug: jnidebugCompile Project (‘: SDK ‘).
How does my current build type correspond to other modules? For example, if your app depends on the DEBUG environment of the SDK Module, you can do this:
Configuration:
of the target module, such as the debug buildType of
in your SDK
debugCompile project(path: ':sdk', configuration: 'debug')
Composite sample
Build. Gradle configuration:
apply plugin: 'com.android.application'
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
applicationIdSuffix '.debug'
minifyEnabled false
}
// A custom build type. The name should be arbitrary and make sense
raedebug {
initWith debug
applicationIdSuffix '.raedebug'
}
}
}
dependencies {
// Generate environment dependencies
releaseCompile project(path: ':sdk', configuration: 'release')
// Test environment dependencies
debugCompile project(path: ':sdk', configuration: 'debug')
// Customize build type dependencies
raedebugCompile project(path: ':sdk', configuration: 'uutest')
}
Copy the code
Build. Gradle configuration for SDK Module:
apply plugin: 'com.android.library'
android {
buildTypes {
debug {
debuggable true
minifyEnabled false
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
// The configuration of raedebugCompile project must be matched.
uutest {
initWith debug
}
}
}
Copy the code
Multi-channel packagingproductFlavors
Take a look at the build.gradle configuration first
android{
// Channel package definition. The default definition name is the channel name
productFlavors {
dev {} / / test
baidu {} // Baidu Mobile Assistant
yinyongbao {} / / application
m360 {} // 360 mobile Assistant
pp {} / / PP assistant
anzhi{} // Anzhi Market
xiaomi {} // The xiaomi store
letv {} // LeEco Store
huawei {} // Huawei Store
lenovomm {} // Lenovo Music Store
other {} // Other markets
official{} // Official version
}
// Batch channel package value replacement
productFlavors.all { flavor ->
// UMENG_CHANNEL is configured according to your androidmanifest.xml, see below.
flavor.manifestPlaceholders = [UMENG_CHANNEL: name, JPUSH_CHANNEL: name]
}
}
Copy the code
Androidmanifest.xml configuration:
<?xml version="1.0" encoding="utf-8"? >
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rae.demo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<! Use ${variable name} to replace variables, not only with <meta-data /> tags, but with anything you want. -->
<meta-data
android:name="UMENG_APPKEY"
android:value="${UMENG_APPKEY}"/>
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL}"/>
<! --${variable with transform}-->
<activity
android:name=".DemoActivity"
android:label=${variable with transformation}/>
</application>
</manifest>
Copy the code
After Sync Gradle, look at the Gradle Projects pane and you will find out what to do with the various Build types you will find in the Build Variants pane.
APK output configuration
After combining with multi-channel packaging, the operation side hopes that the channel package we give is in this format app-{version number}-{channel name}. Apk, then let’s see how to meet the multi-channel packaging output APK file name modification.
android{
// Output file configuration
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile ! =null && outputFile.name.endsWith('.apk')) {
def dirName = outputFile.parent // Outputs the location of the folder
// Change the file name
def fileName = "app-${output.processResources.variantName}-${defaultConfig.versionName}-${variant.flavorName}.apk"
// If you don't want to bother, just add the version number:
// def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(dirName, fileName)
}
}
}
}
Copy the code
The multi-channel packaging described above uses the default gralde configuration, but the downside is that each channel package is recompiled once, which is slow. For a large number of multi-channel packaging recommended using Meituan Walle, project address: github.com/Meituan-Dia…