Tuesday 15 August 2017

HB Blog 142: Android Configure Using Build Variants - Part 2.

Hello friends, Thanks for reading my previous post on HB Blog 141: Android Configure Build Variants - Part 1.
This post will show you how you can configure build variants to create different versions of your app from a single project, and how to properly manage your dependencies and signing configurations.
Build variants are the result of Gradle using a specific set of rules to combine settings, code, and resources configured in your build types and product flavors. Although you do not configure build variants directly, you do configure the build types and product flavors that form them. Each build variant represents a different version of your app that you can build. For example, you might want to build one version of your app that's free, with a limited set of content, and another paid version that includes more. You can also build different versions of your app that target different devices, based on API level or other device variations.

Refer the below link for complete sample code:-

Download Sample Code

Have a look on few code snippets,

//build.gradle
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.harshalbenake.buildvariant"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }

    /**
     * The following sample specifies an applicationIdSuffix for the debug build type,
     * and configures a "jnidebug" build type that is initialized using settings from
     * the debug build type.
     */
    buildTypes {
        release {
            minifyEnabled false
            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
        }
    }

    // Specifies the flavor dimensions you want to use. The order in which you
    // list each dimension determines its priority, from highest to lowest,
    // when Gradle merges variant sources and configurations. You must assign
    // each product flavor you configure to one of the flavor dimensions.
    flavorDimensions "api", "mode"

    /**
     * The following code sample creates "demo" and "full" product flavors
     * which provide their own applicationIdSuffix and versionNameSuffix.
     * The following code sample uses the flavorDimensions property
     * to create a "mode" flavor dimension to group the "full" and "demo" product flavors,
     * and an "api" flavor dimension to group product flavor configurations based on API level
     */
    productFlavors {
        demo {
            applicationIdSuffix ".demo"
            versionNameSuffix "-demo"
            // Assigns this product flavor to the "mode" flavor dimension.
            dimension "mode"
            resValue "string", "app_name", "HB Demo"
        }
        full {
            applicationIdSuffix ".full"
            versionNameSuffix "-full"
            dimension "mode"
            resValue "string", "app_name", "HB Full"
        }

        // Configurations in the "api" product flavors override those in "mode"
        // flavors and the defaultConfig block. Gradle determines the priority
        // between flavor dimensions based on the order in which they appear next
        // to the flavorDimensions property above--the first dimension has a higher
        // priority than the second, and so on.
        minApi24 {
            dimension "api"
            minSdkVersion '24'
            // To ensure the target device receives the version of the app with
            // the highest compatible API level, assign version codes in increasing
            // value with API level. To learn more about assigning version codes to
            // support app updates and uploading to Google Play, read Multiple APK Support
            versionCode 30000 + android.defaultConfig.versionCode
            versionNameSuffix "-minApi24"
        }

        minApi23 {
            dimension "api"
            minSdkVersion '23'
            versionCode 20000  + android.defaultConfig.versionCode
            versionNameSuffix "-minApi23"
        }

        minApi21 {
            dimension "api"
            minSdkVersion '21'
            versionCode 10000 + android.defaultConfig.versionCode
            versionNameSuffix "-minApi21"
        }
}

    /**
     * Using the build configuration from the previous section as an example,
     * suppose you plan to support only API levels 23 and higher for the demo version of the app.
     * You can use the variantFilter block to filter out all build variant configurations that
     * combine the "minApi21" and "demo" product flavors.
     */
    variantFilter { variant ->
        def names = variant.flavors*.name
        // To check for a certain build type, use variant.buildType.name == "<buildType>"
        if (names.contains("minApi23") && names.contains("full")) {
            // Gradle ignores any variants that satisfy the conditions above.
            setIgnore(true)
        }
    }
}

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

Tuesday 1 August 2017

HB Blog 141: Android Configure Using Build Variants - Part 1.

The Android build system compiles app resources and source code, and packages them into an Android Application Package (APK), that you can test, deploy, sign, and distribute.  Android Studio uses Gradle, an advanced build toolkit, to automate and manage the build process, while allowing you to define flexible custom build configurations.
 The build process for a typical Android app module follows these general steps:
  1.     The compilers convert your source code into DEX (Dalvik Executable) files, which include the bytecode that runs on Android devices, and everything else into compiled resources.
  2.     The APK Packager combines the DEX files and compiled resources into a single APK. Before your app can be installed and deployed onto an Android device, however, the APK must be signed.
  3.     Before generating your final APK, the packager uses the zipalign tool to optimize your app to use less memory when running on a device.
At the end of the build process, you have either a debug APK or release APK of your app that you can use to deploy, test, or release to external users.

Gradle and the Android plugin help you configure the following aspects of your build:

 Build Types :-
    Build types define certain properties that Gradle uses when building and packaging your app, and are typically configured for different stages of your development lifecycle. For example, the debug build type enables debug options and signs the APK with the debug key, while the release build type may shrink, obfuscate, and sign your APK with a release key for distribution. You must define at least one build type in order to build your app—Android Studio creates the debug and release build types by default.

 Product Flavors :-
    Product flavors represent different versions of your app that you may release to users, such as free and paid versions of your app. You can customize product flavors to use different code and resources, while sharing and reusing the parts that are common to all versions of your app. Product flavors are optional and you must create them manually.

 Build Variants :-
    A build variant is a cross product of a build type and product flavor, and is the configuration Gradle uses to build your app. Using build variants, you can build the debug version of your product flavors during development, or signed release versions of your product flavors for distribution. Although you do not configure build variants directly, you do configure the build types and product flavors that form them. Creating additional build types or product flavors also creates additional build variants.

 Manifest Entries :-
    You can specify values for some properties of the manifest file in the build variant configuration. These build values override the existing values in the manifest file. This is useful if you want to generate multiple APKs for your modules where each of the apk files has a different application name, minimum SDK version, or target SDK version.

 Dependencies :-
    The build system manages project dependencies from your local filesystem and from remote repositories. This prevents you from having to manually search, download, and copy binary packages of your dependencies into your project directory.

 Signing :-
    The build system enables you to specify signing settings in the build configuration, and it can automatically sign your APKs during the build process. The build system signs the debug version with a default key and certificate using known credentials to avoid a password prompt at build time. The build system does not sign the release version unless you explicitly define a signing configuration for this build.
For more details, visit my post, HB Blog 120: How To Sign Your APKs Using Android Studio.

 ProGuard :-
    The build system enables you to specify a different ProGuard rules file for each build variant. The build system can run ProGuard to shrink and obfuscate your classes during the build process.
For more details, visit my post, HB Blog 139: ProGuard - Shrinks, Optimizes, And Obfuscates Your Code.

 Multiple APK Support :-
    The build system enables you to automatically build different APKs that each contain only the code and resources needed for a specific screen density or Application Binary Interface (ABI).

Custom Build Configurations :-

Creating custom build configurations requires you to make changes to one or more build configuration files, or build.gradle files. These plain text files use Domain Specific Language (DSL) to describe and manipulate the build logic using Groovy, which is a dynamic language for the Java Virtual Machine (JVM).

When starting a new project, Android Studio automatically creates some of these files for you, as shown in below image, and populates them based on sensible defaults.
 ......Continue, to read more on Build Variant gradle in my next post, Android Configure Using Build Variants - Part 2.