How to Efficiently Use Gradle in Android

Hello everyone,

Let’s talk something about Gradle now.

Gradle is playing major in Native Android development these days. Using Gradle in an efficient way, will give you good impact on your project building process and APK releasing process as well.

 

 

 

How to identify or differentiate the App’s Debug and Release mode 

This is one of the most important questions asked by new developers.

There are two build types defined by system in every android projects.

  1. Debug.
  2. Release.

We should identify them programmatically in order to customize the code according to our need or else we might need to maintain different set of configurations for each build variants.  for example there can be two development urls, one is for debugging purpose and the other one is for actual release purpose. we can configure them in gradle file without doing much work in gradle file.

Check my Stackoverflow answer for a simple solution

 

buildTypes {
    debug {
        manifestPlaceholders = [ mapApiKeyValue:"GHjaSyAjlyp3O831lgaonHMXsd-_DpQ3002x3S4"]
    }

    release {
        manifestPlaceholders = [ mapApiKeyValue:"AIzaSyAuMGDLr2HeuRed4JA0CrdYYdZRjeC3EA"]
    }
}
Â

In Manifest file you use the key like this,

<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="${mapApiKeyValue}" />

 

 

How to create different urls for Debug and Release phases.

You can declare many variables module level gradle file and access them in code file.

buildTypes {
    debug {
        buildConfigField "Boolean", "IS_DEBUG", 'true'
        buildConfigField "String", "URL", 'https://appsgit.com/debugurl'
    }

    release {
        buildConfigField "Boolean", "IS_DEBUG", 'false'
        buildConfigField "String", "URL", 'https://appsgit.com/releaseurl'
    }
}

You can access these variables in the code like below.

if (BuildConfig.URL.equalsIgnoreCase("https://appsgit.com/debugurl")) {
   //debug mode
} else if (BuildConfig.URL.equalsIgnoreCase("https://appsgit.com/releaseurl")){
   //testmode
}

 

 

Add app’s default configuration like below

defaultConfig {
applicationId "com.appsgit.testapp"
minSdkVersion 14
targetSdkVersion 22
versionCode 1 // increment with every release
versionName '1.0.0' // change with every release
}

 

 

Change APK name on creation

By default signed APK name is created like “app-release.apk”. It is really hard to identify the release APK when you work with multiple APK in the same time.  Check the code below, It will help to change the project name on the release time and append the version name to the APK file name.

 

buildTypes {
    debug {
        buildConfigField "Boolean", "IS_DEBUG", 'true'
        buildConfigField "String", "URL", 'https://appsgit.com/debugurl'
    }

    release {
        buildConfigField "Boolean", "IS_DEBUG", 'false'
        buildConfigField "String", "URL", 'https://appsgit.com/releaseurl'
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "ProjectName-" + defaultConfig.versionName + ".apk"))
            }
        }
    }
}

 

 

 

Add Product Flavor (Free version & paid version)

 

Assume that you want to create Free version of the app and paid version of the app,  You can create product flavor of the app in the gradle like below.

 

productFlavors {
    free {
        applicationId "com.appsgit.freeapp"
        buildConfigField 'boolean', 'IS_PAID', 'false'
        buildConfigField 'boolean', 'URL', 'http://freeversion.com'
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "app-free-" + defaultConfig.versionName + ".apk"))
            }
        }
    }

    paid {
        applicationId "com.appsgit.paidapp"
        buildConfigField 'boolean', 'IS_PAID', 'true'
        buildConfigField 'boolean', 'URL', 'https://paidversion.com'
        versionCode 1
        versionName "1.0"
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "app-paid-" + defaultConfig.versionName + ".apk"))
            }
        }
    }
}

 

You  can create source codes for your free and paid version like below, Don’t forget resources in the MAIN is shared to all the created flavors. you no need to copy them to product flavor’s source code.

 

 

I will write a separate post about how to configure and run Product flavor.

 

 

 

 


 

Add Project Level properties.

Edit your top level properties file and adde the following snippet.

buildscript {...}

allprojects {...}

// This block encapsulates custom properties and makes them available to all
// modules in the project.
ext {
    // The following are only a few examples of the types of properties you can define.
    compileSdkVersion = 26
    buildToolsVersion = "26.0.1"
    // You can also create properties to specify versions for dependencies.
    // Having consistent versions between modules can avoid conflicts with behavior.
    supportLibVersion = "26.1.0"
    ...
}
...

 

You use the above property values in module level build.gradle files

 

android {
  // Use the following syntax to access properties you defined at the project level:
  // rootProject.ext.property_name
  compileSdkVersion rootProject.ext.compileSdkVersion
  buildToolsVersion rootProject.ext.buildToolsVersion
  ...
}

 

 

 

 


 

I will append the top level and module level build.gradle files and their properties for your reference here.

 

Top Level build.gradle file

 

/**
 * The buildscript block is where you configure the repositories and
 * dependencies for Gradle itself--meaning, you should not include dependencies
 * for your modules here. For example, this block includes the Android plugin for
 * Gradle as a dependency because it provides the additional instructions Gradle
 * needs to build Android app modules.
 */

buildscript {

    /**
     * The repositories block configures the repositories Gradle uses to
     * search or download the dependencies. Gradle pre-configures support for remote
     * repositories such as JCenter, Maven Central, and Ivy. You can also use local
     * repositories or define your own remote repositories. The code below defines
     * JCenter as the repository Gradle should use to look for its dependencies.
     */

    repositories {
        jcenter()
     //maven()
    }

    /**
     * The dependencies block configures the dependencies Gradle needs to use
     * to build your project. The following line adds Android plugin for Gradle
     * version 2.3.3 as a classpath dependency.
     */

    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
    }
}

/**
 * The allprojects block is where you configure the repositories and
 * dependencies used by all modules in your project, such as third-party plugins
 * or libraries. Dependencies that are not required by all the modules in the
 * project should be configured in module-level build.gradle files. For new
 * projects, Android Studio configures JCenter as the default repository, but it
 * does not configure any dependencies.
 */

allprojects {
   repositories {
       jcenter()
   }
}
 

 

 

 

Module Level Build.Gradle File

/**
 * The first line in the build configuration applies the Android plugin for
 * Gradle to this build and makes the android block available to specify
 * Android-specific build options.
 */

apply plugin: 'com.android.application'

/**
 * All your Android-specifi build configuration goes here.
 */

android {

  /**
   * compileSdkVersion specifies the Android API level Gradle should use to
   * compile your app. This means your app can use the API features included in
   * this API level and lower.
   *
   * buildToolsVersion specifies the version of the SDK build tools, command-line
   * utilities, and compiler that Gradle should use to build your app. You need to
   * download the build tools using the SDK Manager.

   * AndroidManifest.xml file will be overritten by this value on the build time.
   */

  compileSdkVersion 26
  buildToolsVersion "26.0.1"

  /**
   * The defaultConfig block encapsulates default settings and entries for all
   * build variants, and can override some attributes in main/AndroidManifest.xml
   * dynamically from the build system. You can configure product flavors to override
   * these values for different versions of your app.
   */

  defaultConfig {

    /**
     * applicationId uniquely identifies the package for publishing.
     * However, your source code should still reference the package name
     * defined by the package attribute in the main/AndroidManifest.xml file.
     */

    applicationId 'com.example.myapp'

    // Defines the minimum API level required to run the app.
    minSdkVersion 15

    // Specifies the API level used to test the app.
    targetSdkVersion 26

    // Defines the version number of your app.
    versionCode 1

    // Defines a user-friendly version name for your app.
    versionName "1.0"
  }

  /**
   * The buildTypes block is where you can configure multiple build types.
   * By default, the build system defines two build types: debug and release. The
   * debug build type is not explicitly shown in the default build configuration,
   * but it includes debugging tools and is signed with the debug key. The release
   * build type applies Proguard settings and is not signed by default.
   */

  buildTypes {

    /**
     * By default, Android Studio configures the release build type to enable code
     * shrinking, using minifyEnabled, and specifies the Proguard settings file.
     */

    release {
        minifyEnabled true // Enables code shrinking for the release build type.
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

  /**
   * The productFlavors block is where you can configure multiple product
   * flavors. This allows you to create different versions of your app that can
   * override the defaultConfig block with their own settings. Product flavors are
   * optional, and the build system does not create them by default. This example
   * creates a free and paid product flavor. Each product flavor then specifies
   * its own application ID, so that they can exist on the Google Play Store, or
   * an Android device, simultaneously.
   */

  productFlavors {
    free {
      applicationId 'com.example.myapp.free'
    }

    paid {
      applicationId 'com.example.myapp.paid'
    }
  }

  /**
   * The splits block is where you can configure different APK builds that
   * each contain only code and resources for a supported screen density or
   * ABI. You'll also need to configure your build so that each APK has a
   * different versionCode.
   */

  splits {
    // Settings to build multiple APKs based on screen density.
    density {

      // Enable or disable building multiple APKs.
      enable false

      // Exclude these densities when building multiple APKs.
      exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
    }
  }
}

/**
 * The dependencies block in the module-level build configuration file
 * only specifies dependencies required to build the module itself.
 */

dependencies {
    compile project(":lib")
    compile 'com.android.support:appcompat-v7:26.1.0'
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

 

About Zumry

Zumry Mohamed

Self Taught iOS & Android Mobile Application Developer.

Article written by zumrywahid

Self Taught iOS & Android Mobile Application Developer.

Be the first to comment

Leave a Reply

Your email address will not be published. Required fields are marked *