gradle packaging script
1. Different closure meanings
defaultConfig{} Default configuration, yes ProductFlavor Type. Share it with others ProductFlavor use sourceSets{ } Source file directory settings, yes AndroidSourceSet Type. buildTypes{ } BuildType type signingConfigs{ } Signature configuration, SigningConfig type productFlavors{ } Product style configuration, ProductFlavor type testOptions{ } Test configuration, TestOptions type aaptOptions{ } aapt to configure, AaptOptions type lintOptions{ } lint to configure, LintOptions type dexOptions{ } dex to configure, DexOptions type compileOptions{ } Compile configuration, CompileOptions type packagingOptions{ } PackagingOptions type jacoco{ } JacocoExtension Type. Used to set jacoco edition splits{ } Splits type
2 configuration signature
2.1 create a keystore folder under the project root path and put the. store or. jks file into the
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-jbjuwr1y-1631589117624) (C: \ users \ Lenovo \ appdata \ roaming \ typora user images \ image-20210914102048356. PNG)]
2.2 create the key.properties file under the project root path and write the information of the signature file to the
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-s4qgw6ta-1631589117625) (C: \ users \ Lenovo \ appdata \ roaming \ typora user images \ image-20210914102234966. PNG)]
storeFile=../keystore/jiuan.jks storePassword=****** keyAlias=****** keyPassword=******
2.3 in the build.gradle file, import the properties file information
/** * Create a file key.properties under the project root path */ def keystorePropertiesFile = rootProject.file('key.properties') //Create a properties object def keystoreProperties = new Properties() //Load the contents in key.properties keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
2.4 in the build.gradle file, add the signature configuration in the android - "signingConfigs" tag
//Signature configuration signingConfigs { config { storeFile file(keystoreProperties['storeFile']) //Signature file storePassword keystoreProperties['storePassword'] //Signature file password keyAlias keystoreProperties['keyAlias'] //Signature file alias keyPassword keystoreProperties['keyPassword'] //Alias password } }
2.5 in the build.gradle file, use the signature configuration in the android - "buildTypes" tag (the same set of signatures can be used for debug and release versions)
//Build type buildTypes { debug { //Web address switching during script construction buildConfigField('String', 'BASE_URL', '"https://qingchenglive.com"') zipAlignEnabled true //Zialign optimization shrinkResources false // Remove useless resource files minifyEnabled false //Open obfuscation proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config//The signature method is called here } release { //Web address switching during script construction buildConfigField('String', 'BASE_URL', '"https://qingchenglive.com"') zipAlignEnabled true //Zialign optimization shrinkResources false // Remove useless resource files minifyEnabled false //Open obfuscation proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config//The signature method is called here } }
3. Configure multi-channel
3.1 in the build.gradle file, add channels under the android - "productFlavors" tab
/** * Multi channel configuration */ productFlavors { ja_update {} ja_oppo {} ja_vivo {} ja_xiaomi {} ja_huawei {} ja_yingyongbao {} ja_pp {} }
3.2 after Android studio 3.0, flavor dimensions are added to define flavor dimensions
Flavordimens are defined under the android - defaultConfig tag. You can define multiple, separated by commas
defaultConfig { //Flavor dimension - increase the configurability of multi-channel packaging, and the same channel can be subdivided flavorDimensions "frame_flavor" }
Each channel must define its own flavor
/** * Multi channel configuration */ productFlavors { ja_update { dimension "frame_flavor" } ja_oppo { dimension "frame_flavor" } ja_vivo { dimension "frame_flavor" } ja_xiaomi { dimension "frame_flavor" } ja_huawei { dimension "frame_flavor" } ja_yingyongbao { dimension "frame_flavor" } ja_pp { dimension "frame_flavor" } }
3.3 placeholders in the configuration manifest file
Use ${key} to define placeholders in the manifest file - different channels use different application names:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="${app_name}" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Frame">
In the build.gradle file, android - "productFlavors"
/** * Multi channel configuration */ productFlavors { ja_update { dimension "frame_flavor" //The key remains the same as the placeholder in the manifest file and can be replaced manifestPlaceholders = ["app_name": "Picture editing map bottom changing"] } ... }
3.4 traverse multiple channels and add common configuration
android - under the productFlavors tab
productFlavors.all { flavor -> //applicationId must be specified, otherwise it cannot be compiled flavor.applicationId = "com.jiuan.frame" flavor.dimension = "frame_flavor" flavor.signingConfig = signingConfigs.config flavor.manifestPlaceholders.put("channel", name)//Set channel number flavor.manifestPlaceholders.put("application_id", flavor.applicationId)//Replace the placeholder application in the manifest_ id if (flavor.manifestPlaceholders.get("app_name") == null) { //If the upper channel does not specify an app_name, then use the default application name to replace the placeholder app in the manifest_ name flavor.manifestPlaceholders.put("app_name", getDefaultAppName()) } }
getDefaultAppName() gets the default application name and defines the method outside the android tag
def getDefaultAppName() { return "Add a picture frame" }
3.5 obtaining current channels in the application
Add meta data tag in manifest file to configure channel placeholder (under application tag)
<meta-data android:name="channel" android:value="${channel}" />
In the build.gradle file, android - "productFlavors", set the channel placeholder
/** * Multi channel configuration */ productFlavors { ja_update { dimension "frame_flavor" //The key remains the same as the placeholder in the manifest file and can be replaced manifestPlaceholders = ["channel": "Picture editing map bottom changing"] } ... }
Get channel number from application
private String getChannel() { try { PackageManager pm = getPackageManager(); ApplicationInfo appInfo = pm.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); String channel = appInfo.metaData.getString("channel"); // key is the name in the < meta data > tag if (!TextUtils.isEmpty(channel)) { return channel; } } catch (Exception e){ e.printStackTrace(); } return null; }
3.6 user defined output path (when packaging, packages from multiple channels can be generated in the same folder)
android - under the productFlavors tab
applicationVariants.all { variant -> /** * debug Do not specify the output path for the version, otherwise you cannot install and debug * There is a problem after setting the output path -- gradle 6.7 */ if ("release".equals(variant.buildType.name)) { variant.packageApplicationProvider.get().outputDirectory = rootProject.file("/apks/${variant.versionName}") } //Build type def buildType = variant.buildType.name //Named after Android studio 3.0 variant.outputs.all { //File name splicing outputFileName = "imageeditor_${variant.flavorName}_v${defaultConfig.versionName}_${releaseTime()}_${buildType}.apk" } }
releaseTime() formats the current time and defines the method outside the android tag
//Release time def releaseTime() { //When setting the release time, do not set the hours. In this case, the packages generated every hour are different. During installation, studio will report an exception that apk cannot be found // return new Date().format('MMddHH', TimeZone.getTimeZone('GMT+8')) return new Date().format('MMdd', TimeZone.getTimeZone('GMT+8')) }
4 extraction tools
4.1 under the current module directory (the same level as the build.gradle file), create a configuration file config.gradle to integrate the above functions
/** * Create a file key.properties under the project root path */ def keystorePropertiesFile = rootProject.file('key.properties') //Create a properties object def keystoreProperties = new Properties() //Load the contents in key.properties keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { defaultConfig { //Flavor dimension - increase the configurability of multi-channel packaging, and the same channel can be subdivided flavorDimensions "frame_flavor" } //Signature configuration signingConfigs { config { storeFile file(keystoreProperties['storeFile']) //Signature file storePassword keystoreProperties['storePassword'] //Signature file password keyAlias keystoreProperties['keyAlias'] //Signature file alias keyPassword keystoreProperties['keyPassword'] //Alias password } } //Build type buildTypes { debug { //Web address switching during script construction buildConfigField('String', 'BASE_URL', '"https://qingchenglive.com"') zipAlignEnabled true //Zialign optimization shrinkResources false // Remove useless resource files minifyEnabled false //Open obfuscation proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config//The signature method is called here } release { //Web address switching during script construction buildConfigField('String', 'BASE_URL', '"https://qingchenglive.com"') zipAlignEnabled true //Zialign optimization shrinkResources false // Remove useless resource files minifyEnabled false //Open obfuscation proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config//The signature method is called here } } /** * Multi channel configuration */ productFlavors { ja_update { } ja_oppo { //Replace placeholder app in manifest_ name manifestPlaceholders = ["APP_NAME": "Picture editing map bottom changing"] } ja_vivo { manifestPlaceholders = ["APP_NAME":"Picture editing PS"] } ja_xiaomi { manifestPlaceholders = ["APP_NAME":"Picture editing map bottom changing"] } ja_huawei { manifestPlaceholders = ["APP_NAME":"Add a picture frame"] } ja_yingyongbao { manifestPlaceholders = ["APP_NAME":"Interesting picture editing"] } ja_pp { manifestPlaceholders = ["APP_NAME":"Picture editing map bottom changing"] } productFlavors.all { flavor -> //applicationId must be specified, otherwise it cannot be compiled flavor.applicationId = "com.jiuan.frame" flavor.dimension = "frame_flavor" flavor.signingConfig = signingConfigs.config flavor.manifestPlaceholders.put("channel", name)//Set channel number flavor.manifestPlaceholders.put("application_id", flavor.applicationId)//Replace the placeholder application in the manifest_ id if (flavor.manifestPlaceholders.get("app_name") == null) { //If the upper channel does not specify an app_name, then use the default application name to replace the placeholder app in the manifest_ name flavor.manifestPlaceholders.put("app_name", getDefaultAppName()) } } applicationVariants.all { variant -> /** * debug Do not specify the output path for the version, otherwise you cannot install and debug * There is a problem after setting the output path -- gradle 6.7 */ if ("release".equals(variant.buildType.name)) { variant.packageApplicationProvider.get().outputDirectory = rootProject.file("/apks/${variant.versionName}") } //Build type def buildType = variant.buildType.name //Named after Android studio 3.0 variant.outputs.all { //File name splicing outputFileName = "imageeditor_${variant.flavorName}_v${defaultConfig.versionName}_${releaseTime()}_${buildType}.apk" } } } } //Release time def releaseTime() { //When setting the release time, do not set the hours. In this case, the packages generated every hour are different. During installation, studio will report an exception that apk cannot be found // return new Date().format('MMddHH', TimeZone.getTimeZone('GMT+8')) return new Date().format('MMdd', TimeZone.getTimeZone('GMT+8')) } def getDefaultAppName() { return "Add a picture frame" }
4.2 import in build.gradle file
plugins { id 'com.android.application' id 'kotlin-android' } //Introduction configuration apply from :'config.gradle' android { ... }