Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Five Minute Android: Simplifying Gradle Build Scripts With Functions

DZone's Guide to

Five Minute Android: Simplifying Gradle Build Scripts With Functions

If you've used build flavors in Gradle, you might have a lot of copy and paste code. Adding functions can make your scripts instantly more readable.

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

If you're like me, or tons of other developers, you'll have started out with a limited number of build flavors in your Gradle build script — probably two, in fact: production and development. However, as you add different variables to expose in your BuildConfig, and extended the number of flavors, your code might start to look like a copy and paste mess. 

Here's an example: 

production {
   buildConfigField 'String', 'REST_API', '"https://api.myserver.com/"'
   buildConfigField 'Boolean', 'DEBUG_MODE', 'false'
   buildConfigField 'Boolean', 'DEMO_MODE', 'false'
   }
development {
   buildConfigField 'String', 'REST_API', '"https://test-api.myserver.com/"'
   buildConfigField 'Boolean', 'DEBUG_MODE', 'true'
   buildConfigField 'Boolean', 'DEMO_MODE', 'false'
   }
demo {
   buildConfigField 'String', 'REST_API', '"https://demo-api.myserver.com/"'
   buildConfigField 'Boolean', 'DEBUG_MODE', 'false'
   buildConfigField 'Boolean', 'DEMO_MODE', 'true'
   }


By using a combination of environment variables and functions, we can simplify these flavors. Most continuous integration systems, like TeamCity and Jenkins, will allow you to set parameters during the build, which in turn can be set as environment variables.

In the example above, the REST API variable is an obvious candidate for this. Here's how it would look, assuming the API_SERVER environment variable is used in the build script: 

productFlavours{
  def getAPIServer = {
	def server = System.getenv("API_SERVER")
	if(server)
        return '"'+server+'"'
   	else
        return '"https://api.myserver.com"'
  }
  //other functions and the rest of the flavors 
  //....
}


As you can see the function reads from the environment variables set, but will also return a default if the variable isn't set. Typically it makes sense to have the production variables as the defaults, as you really don't want to send out a production build pointing at a development setup. 

To use this in the flavor definition itself: 

production {
   buildConfigField 'String', 'REST_API', getAPIServer()
   buildConfigField 'Boolean', 'DEBUG_MODE', 'false'
   buildConfigField 'Boolean', 'DEMO_MODE', 'false'
   }


While it might not reduce the lines of code in your script, it certainly a clearer way of expressing the variations.

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
android ,gradle ,build script ,mobile ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}