⬆️ ⬇️

Several gradle chips for your Android application





One of the latest Android Weekly mailings got an article that mentioned interesting features of the organization of the project assembly. After reading it, I wanted to share something of what I use to customize the build of the Android project.





We get rid of duplication of code in your build.gradle files



It would seem a simple idea, but this approach is used quite rarely.

')

Suppose you have several modules in the application, in each of which you need to register buildToolsVersion. Often this task is solved by placing a specific version in an ext-variable.

In addition, you can optimize the code by setting this value in only one place.



Let me remind you about the possibility of applying code from another gradle file in your build.gradle:



apply plugin: 'com.android.application' apply from: "$buildSystemDir/application.gradle" 


And in the file application.gradle you can already specify the necessary versions:



 android { compileSdkVersion 24 buildToolsVersion "24.0.1" defaultConfig { minSdkVersion 15 targetSdkVersion 24 testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } } 


Here you can bring any settings for the entire project. Then, in each specific module, you can override the values ​​(if necessary).



Not only the android - extension configurations, but also test dependencies, jacoco, findbugs, pmd, etc. settings can be put into a separate gradle file. etc.



Add properties to the project



You may have already noticed the $ buildSystemDir variable. It is specified in the build.gradle file of the root project:



 allprojects { it.extensions.add("buildSystemDir", "$rootProject.projectDir/buildSystem/") } 


After that, in each module you can use this property without any prefixes. Which, again, slightly shortens the code;)



Signature apk



The topic of safe storage of keys and passwords from the certificate is very interesting, and I will be very happy if someone prompts a good solution (with ci, safe), but for now I will give my version.



Information about each certificate is stored in the * .properties file. He may either be present on the project assembly machine or be absent.



sign.gradle:

 Properties signProp = new Properties() try { signProp.load(rootProject.file('signForTest.properties').newDataInputStream()) project.ext { forTest = new Object() { def storeFile = signProp.get("forTest.storeFile") def storePassword = signProp.get("forTest.storePassword") def keyAlias = signProp.get("forTest.keyAlias") def keyPassword = signProp.get("forTest.keyPassword") } } } catch (IOException e) { project.ext { forTest = new Object() { def storeFile = "/" def storePassword = "" def keyAlias = "" def keyPassword = "" } } } android { signingConfigs { forTest { storeFile file(project.ext.forTest.storeFile) storePassword project.ext.forTest.storePassword keyAlias project.ext.forTest.keyAlias keyPassword project.ext.forTest.keyPassword } } } 


That's all. It remains to apply this file in the build.gradle of our application and use the configured signingConfig in our buildType.



buildSrc



What to do when a full-fledged code is needed in the build system, and there is no time to write your own plugin? To do this, you can use the buildSrc directory.



In the root directory of your project (where gradlew lies) we create a new module buildSrc. This module should be a regular java project (or groovy or something else), with the following build.gradle file:



 apply plugin: "groovy" repositories { mavenCentral() } dependencies { compile localGroovy() compile gradleApi() } // START SNIPPET addToRootProject rootProject.dependencies { runtime project(path) } // END SNIPPET addToRootProject 


Now in this project you can create any class Awesome.groovy, and in the build.gradle Android module this class can be imported and used.



When you start building your project, the buildSrc module will be built first. After that, the remaining modules will be configured.



I can not say that I recommend using this solution, because this slightly increases the project build time from scratch. But in extreme cases it can be useful.



Flavor dimensions



This feature for configuring the project is well described in the docks (// tools.android.com/tech-docs/new-build-system/user-guide#TOC-Multi-flavor-variants

). But either not everyone knows about it, or they do not understand in which cases it can be used, so I decided to tell about it.



Suppose you need to create a paid and free application. In this case, your application is available for TVs, tablets and phones. Moreover, your application is published in different markets.



Add the following code to your build.gradle:



 android { flavorDimensions "device", "paid", "market" productFlavors { tv { dimension 'device' } tablet { dimension 'device' } phone { dimension 'device' } free { dimension 'paid' } premium { dimension 'paid' } google { dimension 'market' } amazon { dimension 'market' } } } 


By announcing 7 flavor-s in three different groups, you have received as many as 12 different application options. Add here another buildTypes, and we get a huge amount of apk-nis.



phoneFreeGoogleDebug

phoneFreeGoogleRelease

phoneFreeAmazonDebug

phoneFreeAmazonDebug

phonePremiumGoogleDebug

... etc.


For each flavor you announce, a sourceSet is created. For example, if you selected the phoneFreeAmazonDebug flavor, the following sourceSets will be used:



src / phoneFreeAmazon

src / phoneFree

src / phoneAmazon

src / freeAmazon

src / phone

src / free

src / amazon


Thus, there are ample opportunities for customization of assemblies.



Specify minSdkVersion for buildType



To speed up the build of an application at the development stage, it is often recommended to create a separate flavor “develop” and specify minSdkVersion = 21 for it. However, this is not very convenient, and you often want to specify this parameter in the buildType debug. Initially, the plugin does not allow this to be done, however, if necessary, this problem can be solved by the following haik.



For the required buildType you need to add an ext variable:



 … buildTypes { ... debug { ... ext.minSdkVersion = 21 } } 


Below you need to add the following code:



 preBuild.doFirst { android.applicationVariants.all { if (it.buildType.hasProperty("minSdkVersion")) { int i = it.buildType.ext.minSdkVersion; it.mergedFlavor.setMinSdkVersion(new com.android.builder.core.DefaultApiVersion(i)) } } } 


Now for all your flavor in the debug assembly minSdkVersion will be 21. However, there is a hard tie to the inside of the plug-in, so when updating the plug-in version, something may break. Therefore, I can not recommend using this hack - the choice is yours.



Instead of concluding, I want to note that Gradle is a very powerful tool for building a project. If you pay a lot of attention to the quality of the code of your application, then do not forget to put the code in the build.gradle files in order.

Source: https://habr.com/ru/post/311100/



All Articles