Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 1 | page.title=Configuring Gradle Builds |
| 2 | |
| 3 | @jd:body |
| 4 | |
| 5 | <div id="qv-wrapper"> |
| 6 | <div id="qv"> |
| 7 | <h2>In this document</h2> |
| 8 | <ol> |
| 9 | <li><a href="#buildFileBasics">Build Configuration Basics</a> |
| 10 | <ol> |
| 11 | <li><a href="#buildFileBasics">Declare dependencies</a></li> |
| 12 | <li><a href="#buildFileBasics">Run ProGuard</a></li> |
| 13 | <li><a href="#configureSigning">Configure signing settings</a></li> |
| 14 | </ol> |
| 15 | </li> |
| 16 | |
| 17 | |
| 18 | <li><a href="#workBuildVariants">Work with build variants</a></li> |
| 19 | </ol> |
| 20 | |
| 21 | |
| 22 | <h2>See also</h2> |
| 23 | <ul> |
| 24 | <li><a href="{@docRoot}tools/building/plugin-for-gradle.html"> |
| 25 | Android Plugin for Gradle</a></li> |
| 26 | </ul> |
| 27 | </div> |
| 28 | </div> |
| 29 | |
| 30 | |
| 31 | <p>This section builds on the |
| 32 | <a href="{@docRoot}sdk/installing/studio-build.html">Build System Overview</a> and |
| 33 | <a href="{@docRoot}tools/building/building-studio.html">Build and Running from Android Studio</a> |
| 34 | to show you how to use build variants based on product flavors and build types.</p> |
| 35 | |
| 36 | |
| 37 | <h2 id="buildFileBasics">Build Configuration Basics</h2> |
| 38 | |
| 39 | <p>Android Studio projects contain a top-level build file and a build file for each module. The |
| 40 | build files are called <code>build.gradle</code>, and they are plain text files that use |
| 41 | <a href="http://groovy.codehaus.org">Groovy</a> syntax to configure the build with the elements |
| 42 | provided by the Android plugin for Gradle. In most cases, you only need to edit the build files |
| 43 | at the module level. For example, the build file for the app module in the |
| 44 | <code>BuildSystemExample</code> project looks like this:</p> |
| 45 | |
| 46 | <pre> |
Rich Slogar | 7749ded | 2014-12-16 13:21:56 -0800 | [diff] [blame] | 47 | apply plugin: 'com.android.application' |
Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 48 | |
| 49 | android { |
| 50 | compileSdkVersion 19 |
| 51 | buildToolsVersion "19.0.0" |
| 52 | |
| 53 | defaultConfig { |
| 54 | minSdkVersion 8 |
| 55 | targetSdkVersion 19 |
| 56 | versionCode 1 |
| 57 | versionName "1.0" |
| 58 | } |
| 59 | buildTypes { |
| 60 | release { |
| 61 | minifyEnabled true |
Rich Slogar | f062b94 | 2015-03-03 12:27:16 -0800 | [diff] [blame] | 62 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 63 | } |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | dependencies { |
| 68 | compile project(":lib") |
| 69 | compile 'com.android.support:appcompat-v7:19.0.1' |
| 70 | compile fileTree(dir: 'libs', include: ['*.jar']) |
| 71 | } |
| 72 | </pre> |
| 73 | |
Rich Slogar | 7749ded | 2014-12-16 13:21:56 -0800 | [diff] [blame] | 74 | <p><code>apply plugin: 'com.android.application'</code> applies the Android plugin for Gradle to this build. |
Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 75 | This adds Android-specific build tasks to the top-level build tasks and makes the |
| 76 | <code>android {...}</code> element available to specify Android-specific build options.</p> |
| 77 | |
| 78 | <p><code>android {...}</code> configures all the Android-specific build options:</p> |
| 79 | |
| 80 | <ul> |
| 81 | <li>The <code>compileSdkVersion</code> property specifies the compilation target.</li> |
| 82 | <li><p>The <code>buildToolsVersion</code> property specifies what version of the build tools |
| 83 | to use. To install several versions of the build tools, use the SDK Manager.</p> |
| 84 | <p class="note"><strong>Note:</strong> Always use a build tools version whose major |
| 85 | revision number is higher or equal to that of your compilation target and target SDK.</p> |
| 86 | </li> |
| 87 | <li><p>The <code>defaultConfig</code> element configures core settings and |
| 88 | entries in the manifest file (<code>AndroidManifest.xml</code>) dynamically from the |
| 89 | build system. The values in <code>defaultConfig</code> override those in the manifest |
| 90 | file.</p> |
| 91 | <p>The configuration specified in the <code>defaultConfig</code> element applies |
| 92 | to all build variants, unless the configuration for a build variant overrides some |
| 93 | of these values.</p> |
| 94 | </li> |
| 95 | <li>The <code>buildTypes</code> element controls how to build and package your app. |
| 96 | By default, the build system defines two build types: <em>debug</em> and |
| 97 | <em>release</em>. The debug build type includes debugging symbols and is signed with |
| 98 | the debug key. The release build type is not signed by default. |
| 99 | In this example the build file configures the release version to use |
| 100 | ProGuard.</li> |
| 101 | </ul> |
| 102 | |
| 103 | <p>The <code>dependencies</code> element is outside and after the <code>android</code> element. |
| 104 | This element declares the dependencies for this module. Dependencies are covered in the following |
| 105 | sections.</p> |
| 106 | |
| 107 | <p class="note"><strong>Note:</strong> When you make changes to the build files in your project, |
| 108 | Android Studio requires a project sync to import the build configuration changes. Click |
| 109 | <strong>Sync Now</strong> on the yellow notification bar that appears for Android Studio |
| 110 | to import the changes.</p> |
| 111 | |
| 112 | <img src="{@docRoot}images/tools/as-gradlesync.png" alt="" /> |
| 113 | <p class="img-caption"><strong>Figure 1.</strong> Sync the project in Android Studio.</p> |
| 114 | |
| 115 | <h3 id="declareDeps">Declare dependencies</h3> |
| 116 | |
| 117 | <p>The <code>app</code> module in this example declares three |
| 118 | dependencies:</p> |
| 119 | |
| 120 | <pre> |
| 121 | ... |
| 122 | dependencies { |
| 123 | // Module dependency |
| 124 | compile project(":lib") |
| 125 | |
| 126 | // Remote binary dependency |
| 127 | compile 'com.android.support:appcompat-v7:19.0.1' |
| 128 | |
| 129 | // Local binary dependency |
| 130 | compile fileTree(dir: 'libs', include: ['*.jar']) |
| 131 | } |
| 132 | </pre> |
| 133 | |
| 134 | <p>Each of these dependencies is described below. The build system adds all the |
| 135 | <code>compile</code> dependencies to the compilation classpath and includes them in the final |
| 136 | package.</p> |
| 137 | |
| 138 | <h4>Module dependencies</h4> |
| 139 | |
| 140 | <p>The <code>app</code> module depends on the <code>lib</code> module, because |
| 141 | <code>MainActivity</code> launches <code>LibActivity1</code> as described in |
| 142 | <a href="#openActFromLib">Open an Activity from a Library Module</a>.</p> |
| 143 | |
| 144 | <p><code>compile project(":lib")</code> declares a dependency on the <code>lib</code> |
| 145 | module of <code>BuildSystemExample</code>. When you build the <code>app</code> module, |
| 146 | the build system assembles and includes the <code>lib</code> module.</p> |
| 147 | |
| 148 | <h4>Remote binary dependencies</h4> |
| 149 | |
| 150 | <p>The <code>app</code> and <code>lib</code> modules both use the <code>ActionBarActivity</code> |
| 151 | class from the Android Support Library, so these modules depend on it.</p> |
| 152 | |
| 153 | <p><code>compile 'com.android.support:appcompat-v7:19.0.1'</code> declares a dependency on |
| 154 | version 19.0.1 of the Android Support Library by specifying its Maven coordinates. The Android Support |
| 155 | Library is available in the <em>Android Repository</em> package of the Android SDK. If your |
| 156 | SDK installation does not have this package, download and install it using the SDK Manager.</p> |
| 157 | |
| 158 | Android Studio configures projects to use the Maven Central Repository by default. (This |
| 159 | configuration is included in the top-level build file for the project.)</p> |
| 160 | |
| 161 | <h4>Local binary dependencies</h4> |
| 162 | |
| 163 | <p>Some modules do not use any binary dependencies from the |
| 164 | local file system. If you have modules that require local binary dependencies, copy the JAR |
| 165 | files for these dependencies into <code><moduleName>/libs</code> inside your project.</p> |
| 166 | |
| 167 | <p><code>compile fileTree(dir: 'libs', include: ['*.jar'])</code> tells the build system that any |
| 168 | JAR file inside <code>app/libs</code> is a dependency and should be included in the compilation |
| 169 | classpath and in the final package.</p> |
| 170 | |
| 171 | <p>For more information about dependencies in Gradle, see |
| 172 | <a href="http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html">Dependency |
| 173 | Management Basics</a> in the Gradle User Guide.</p> |
| 174 | |
| 175 | <h3 id="runProguard">Run ProGuard</h3> |
| 176 | |
| 177 | <p>The build system can run |
| 178 | <a href="http://developer.android.com/tools/help/proguard.html">ProGuard</a> to obfuscate your |
| 179 | classes during the build process. In <code>BuildSystemExample</code>, modify the build file for |
| 180 | the app module to run ProGuard for the release build:</p> |
| 181 | |
| 182 | <pre> |
| 183 | ... |
| 184 | android { |
| 185 | ... |
| 186 | buildTypes { |
| 187 | release { |
| 188 | minifyEnabled true |
Rich Slogar | f062b94 | 2015-03-03 12:27:16 -0800 | [diff] [blame] | 189 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 190 | } |
| 191 | } |
| 192 | } |
| 193 | ... |
| 194 | </pre> |
| 195 | |
| 196 | <p><code>getDefaultProguardFile('proguard-android.txt')</code> obtains the default ProGuard |
| 197 | settings from the Android SDK installation. Android Studio adds the module-specific rules file |
Rich Slogar | f062b94 | 2015-03-03 12:27:16 -0800 | [diff] [blame] | 198 | <code>proguard-rules.pro</code> at the root of the module, where you can add custom ProGuard |
Rich Slogar | 4083327 | 2014-11-06 17:15:28 -0800 | [diff] [blame] | 199 | rules.</p> |
| 200 | |
| 201 | <h3 id="configureSigning">Configure signing settings</h3> |
| 202 | |
| 203 | <p>The debug and the release versions of the app differ on whether the application can be |
| 204 | debugged on secure devices and on how the APK is signed. The build system signs the debug |
| 205 | version with a default key and certificate using known credentials to avoid a password prompt at |
| 206 | build time. The build system does not sign the release version unless you explicitly define a |
| 207 | signing configuration for this build. If you do not have a release key, you can generate one as |
| 208 | described in <a href="{@docRoot}tools/publishing/app-signing.html">Signing your Applications</a>.</p> |
| 209 | |
| 210 | |
| 211 | <h2 id="workBuildVariants">Work with build variants</h2> |
| 212 | |
| 213 | <p>This section describes how the build system can help you create different versions of the same |
| 214 | application from a single project. This is useful when you have a demo version and a paid version |
| 215 | of your app, or if you want to distribute multiple APKs for different device configurations on |
| 216 | Google Play.</p> |
| 217 | |
| 218 | <p>The build system uses <em>product flavors</em> to create different product versions of your app. |
| 219 | Each product version of your app can have different features or device requirements. The build |
| 220 | system also uses build types to apply different build and packaging settings to each product version. |
| 221 | Each product flavor and build type combination forms a build variant. The build system generates a |
| 222 | different APK for each build variant of your app. </p> |
| 223 | |
| 224 | <h3>Build variants</h3> |
| 225 | |
| 226 | <p>This example project consists of the two default build types (<em>debug</em> and <em>release</em>) |
| 227 | and two product flavors for app type (demo and full). For more information on advanced uses of |
| 228 | build variants, see |
| 229 | <a href="{@docRoot}sdk/installing/studio-build.html"> Build System Overview</a> .</p> |
| 230 | |
| 231 | |
| 232 | <h4>Product flavors </h4> |
| 233 | |
| 234 | <p>To create different product versions of your app:</p> |
| 235 | |
| 236 | <ol> |
| 237 | <li>Define product flavors in the build file.</li> |
| 238 | <li>Create additional source directories for each flavor.</li> |
| 239 | <li>Add the flavor-specific sources to your project.</li> |
| 240 | </ol> |
| 241 | |
| 242 | <p>The rest of this section walks you through these steps in detail using a |
| 243 | <code>BuildSystemExample</code> project. You create two flavors of the |
| 244 | <code>BuildSystemExample</code> app, a demo flavor and a full flavor. Both flavors share |
| 245 | <code>MainActivity</code>, to which you add a new button to launch a new activity, |
| 246 | <code>SecondActivity</code>. This new activity is different for each flavor, so you simulate a |
| 247 | situation where the new activity would have more features in the full flavor than in the demo |
| 248 | flavor. At the end of the exercise, you end up with two different APKs, one for each flavor.</p> |
| 249 | |
| 250 | <h3>Define product flavors in the build file</h3> |
| 251 | |
| 252 | <p>To define two product flavors, edit the build file for the app module to add the following |
| 253 | configuration:</p> |
| 254 | |
| 255 | <pre> |
| 256 | ... |
| 257 | android { |
| 258 | ... |
| 259 | defaultConfig { ... } |
| 260 | signingConfigs { ... } |
| 261 | buildTypes { ... } |
| 262 | productFlavors { |
| 263 | demo { |
| 264 | applicationId "com.buildsystemexample.app.demo" |
| 265 | versionName "1.0-demo" |
| 266 | } |
| 267 | full { |
| 268 | applicationId "com.buildsystemexample.app.full" |
| 269 | versionName "1.0-full" |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | ... |
| 274 | </pre> |
| 275 | |
| 276 | <p>The product flavor definitions support the same properties as the <code>defaultConfig</code> |
| 277 | element. The base configuration for all flavors is specified in <code>defaultConfig</code>, and each |
| 278 | flavor overrides any default values. The build file above uses the <code>applicationId</code> |
| 279 | property to assign a different package name to each flavor: since each flavor definition creates a |
| 280 | different app, they each need a distinct package name.</p> |
| 281 | |
| 282 | <p class="note"><strong>Note:</strong> To distribute your app using |
| 283 | <a href="{@docRoot}google/play/publishing/multiple-apks.html">Multiple APK Support</a> in |
| 284 | Google Play, assign the same package name to all variants and give each variant a different |
| 285 | <code>versionCode</code>. To distribute different variants of your app as separate apps in Google |
| 286 | Play, assign a different package name to each variant.</p> |
| 287 | |
| 288 | <h4>Add additional source directories for each flavor</h4> |
| 289 | |
| 290 | <p>Now you create source folders and add a <code>SecondActivity</code> to each flavor. To create |
| 291 | the source directory structure for the demo flavor:</p> |
| 292 | |
| 293 | <ol> |
| 294 | <li>On the <em>Project</em> panel, expand <strong>BuildSystemExample</strong>, and then expand |
| 295 | the <strong>app</strong> directory.</li> |
| 296 | <li>Right-click the <strong>src</strong> directory under <em>app</em> and select |
| 297 | <strong>New</strong> > <strong>Directory</strong>.</li> |
| 298 | <li>Enter "demo" as the name of the new directory and click <strong>OK</strong>.</li> |
| 299 | <li><p>Similarly, create the following directories:</p> |
| 300 | <ul> |
| 301 | <li><code>app/src/demo/java</code></li> |
| 302 | <li><code>app/src/demo/res</code></li> |
| 303 | <li><code>app/src/demo/res/layout</code></li> |
| 304 | <li><code>app/src/demo/res/values</code></li> |
| 305 | </ul> |
| 306 | </li> |
| 307 | </ol> |
| 308 | |
| 309 | <p>The resulting directory structure looks like figure 1.</p> |
| 310 | |
| 311 | <img src="{@docRoot}images/tools/as-demoflavordirs.png" alt="" /> |
| 312 | <p class="img-caption"><strong>Figure 1.</strong> New source directories for the demo flavor.</p> |
| 313 | |
| 314 | <h4>Add a new activity to each flavor</h4> |
| 315 | |
| 316 | <p>To add <code>SecondActivity</code> to the <code>demo</code> flavor:</p> |
| 317 | |
| 318 | <ol> |
| 319 | <li>On the <em>Project</em> panel, right click on the <strong>app</strong> module and select |
| 320 | <strong>New</strong> > <strong>Activity</strong>.</li> |
| 321 | <li>Select <strong>Blank Activity</strong> and click <strong>Next</strong>.</li> |
| 322 | <li>Enter "SecondActivity" as the activity name.</li> |
| 323 | <li>Enter "com.buildsystemexample.app" as the package name and click |
| 324 | <strong>Finish</strong>.</li> |
| 325 | <li>Right click on the <strong>java</strong> directory under <em>app/src/demo</em> and select |
| 326 | <strong>New</strong> > <strong>Package</strong>.</li> |
| 327 | <li>Enter "com.buildsystemexample.app" as the package name and click <strong>OK</strong>.</li> |
| 328 | <li>Drag <strong>SecondActivity</strong> and drop it under the new package in |
| 329 | <em>app/src/demo/java</em>.</li> |
| 330 | <li>Accept the default values and click <strong>Refactor</strong>.</li> |
| 331 | </ol> |
| 332 | |
| 333 | <p>To add the layout for <code>SecondActivity</code> and a strings resource to the demo flavor:</p> |
| 334 | |
| 335 | <ol> |
| 336 | <li>Drag <strong>activity_second.xml</strong> from <em>app/src/main/res/layout</em> and drop it |
| 337 | inside <em>app/src/demo/res/layout</em>.</li> |
| 338 | <li>Accept the default values on the window that appears and click <code>OK</code>.</li> |
| 339 | <li>Copy <strong>strings.xml</strong> from <em>app/src/main/res</em> into |
| 340 | <em>app/src/demo/res</em>.</li> |
| 341 | <li><p>Replace the contents of the new copy of <code>strings.xml</code> with the |
| 342 | following:</p> |
| 343 | <p><pre> |
| 344 | <?xml version="1.0" encoding="utf-8"?> |
| 345 | <resources> |
| 346 | <string name="hello_world">Demo version only.</string> |
| 347 | </resources> |
| 348 | </pre></p> |
| 349 | </li> |
| 350 | </ol> |
| 351 | |
| 352 | <p>Now you add source folders and <code>SecondActivity</code> to the full flavor by making a copy |
| 353 | of the <code>demo</code> flavor:</p> |
| 354 | |
| 355 | <ol> |
| 356 | <li>On the <em>Project</em> panel, right click on the <strong>demo</strong> directory under |
| 357 | <em>app/src</em> and select <strong>Copy</strong>.</li> |
| 358 | <li>Right-click on the <strong>src/</strong> directory under <em>app/</em> and select |
| 359 | <strong>Paste</strong>.</li> |
| 360 | <li>On the window that appears, enter "full" as the new name and click <strong>OK</strong>.</li> |
| 361 | <li><p>Replace the contents of <strong>strings.xml</strong> under <em>src/full/res/values</em> |
| 362 | with the following:</p> |
| 363 | <p><pre> |
| 364 | <?xml version="1.0" encoding="utf-8"?> |
| 365 | <resources> |
| 366 | <string name="hello_world">This is the full version!</string> |
| 367 | </resources> |
| 368 | </pre></p> |
| 369 | </li> |
| 370 | </ol> |
| 371 | |
| 372 | <p class="note"><strong>Note:</strong> From this point on, you could develop |
| 373 | <code>SecondActivity</code> independently inside each |
| 374 | flavor. For example, you could add more features to this activity in the <code>full</code> flavor.</p> |
| 375 | |
| 376 | <p>To work on files from a particular flavor, click on <strong>Build Variants</strong> on the left |
| 377 | of the IDE window and select the flavor you want to modify in the <em>Build Variants</em> panel, |
| 378 | as shown in figure 2. Android Studio may show errors in source files from flavors other than the |
| 379 | one selected in the <em>Build Variants</em> panel, but this does not affect the outcome of the |
| 380 | build.</p> |
| 381 | |
| 382 | <img src="{@docRoot}images/tools/as-buildvariants.png" alt="" /> |
| 383 | <p class="img-caption"><strong>Figure 2.</strong> The Build Variants panel.</p> |
| 384 | |
| 385 | <h4>Launch a flavor-specific activity from the main activity</h4> |
| 386 | |
| 387 | <p>Since the flavor-specific activity (<code>SecondActivity</code>) has the same package name and |
| 388 | activity name in both flavors, you can launch it from the main activity, which is common to all |
| 389 | flavors. To modify the main activity:</p> |
| 390 | |
| 391 | <ol> |
| 392 | <li><p>Edit <code>activity_main.xml</code> and add a new button to |
| 393 | <code>MainActivity</code>:</p> |
| 394 | <p><pre> |
| 395 | <LinearLayout ...> |
| 396 | ... |
| 397 | <Button |
| 398 | android:id="@+id/button2" |
| 399 | android:layout_width="wrap_content" |
| 400 | android:layout_height="wrap_content" |
| 401 | android:text="@string/button2" |
| 402 | android:onClick="onButton2Clicked"/> |
| 403 | </LinearLayout> |
| 404 | </pre></p> |
| 405 | </li> |
| 406 | <li>Click on the areas marked in red in the layout file and press <strong>Alt</strong>+ |
| 407 | <strong>Enter</strong>. Follow the suggestions from Android Studio to add a new string |
| 408 | resource with value “Open Second Activity” and an <code>onButton2Clicked</code> method to |
| 409 | <code>MainActivity</code>.</li> |
| 410 | <li><p>Add the following code to the <code>onButton2Clicked</code> method of |
| 411 | <code>MainActivity</code>:</p> |
| 412 | <p><pre> |
| 413 | public void onButton2Clicked(View view) { |
| 414 | Intent intent = new Intent(this, SecondActivity.class); |
| 415 | startActivity(intent); |
| 416 | } |
| 417 | </pre></p> |
| 418 | </li> |
| 419 | <li><p>Edit the app's manifest to include a reference to <code>SecondActivity</code>:</p> |
| 420 | <p><pre> |
| 421 | <manifest ...> |
| 422 | <application ...> |
| 423 | ... |
| 424 | <activity |
| 425 | android:name="com.buildsystemexample.app.SecondActivity" |
| 426 | android:label="@string/title_activity_second" > |
| 427 | </activity> |
| 428 | </application> |
| 429 | </manifest> |
| 430 | </pre></p> |
| 431 | </li> |
| 432 | </ol> |
| 433 | |
| 434 | |
| 435 | <h4>Build types </h4> |
| 436 | <p>Build types represent the build packaging versions generated for each app package. By default, |
| 437 | the debug and release build types are provided. |
| 438 | </p> |
| 439 | |
| 440 | <pre> |
| 441 | ... |
| 442 | android { |
| 443 | ... |
| 444 | defaultConfig { ... } |
| 445 | signingConfigs { ... } |
| 446 | buildTypes { ... } |
| 447 | productFlavors {...} |
| 448 | buildTypes { |
| 449 | release { |
| 450 | minifyEnabled false |
| 451 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
| 452 | } |
| 453 | debug { |
| 454 | debuggable true |
| 455 | } |
| 456 | } |
| 457 | } |
| 458 | ... |
| 459 | </pre> |
| 460 | |
| 461 | <p class="note"><strong>Note:</strong> Although only the <em>release</em> build type appears in |
| 462 | the default <strong>build.gradle</strong> file, both the release and debug build types are |
| 463 | applied to each build. </p> |
| 464 | |
| 465 | <p>In this example, the product flavors and build types create the following build variants: |
| 466 | <ul> |
| 467 | <li>demoDebug</li> |
| 468 | <li>demoRelease</li> |
| 469 | <li>fullDebug</li> |
| 470 | <li>fullRelease</li> |
| 471 | </ul> |
| 472 | |
| 473 | <p>To build this example, invoke the <code>assemble</code> task from Android Studio or from the |
| 474 | command line.</p> |
| 475 | |
| 476 | <p>Separate output folders are created for each build variant. </p> |