Coffee and Space

Generating assets with a Gradle task

·

Sometimes you need to generate assets during build time. In our case, we had to download our terms of use from a CMS and bake them into the APK, so they’re available without the app ever being online.

Since I had seen folders like app/build/generated/assets and Gradle tasks like :app:mergeDebugAssets fly by my console before, my first hunch was to create a custom task fetchTermsOfUse, make merge${variant}Assets depend on this and throw my generated assets into app/build/generated/assets. In practice, this proved to be flaky at best, and not working at all most of the time. Thankfully, Chris Warrington of the AGP team pointed me in the right direction:

The application- and library-variant objects that the Android Gradle Plugin provides allow extending the list of directories for the different source sets. You might have seen this before when trying to make Gradle consider your src/main/kotlin directories instead of just src/main/java. And just like for Kotlin or Java sources, there’s a source set for assets as well:

task generateTermsOfUseAssets {
  doLast {
    new File(project.buildDir, "termsOfUseAssets").mkdirs()
    new File(project.buildDir, "termsOfUseAssets/tou.txt")
      .write("Hello World :)")
  }
}

android {
  sourceSets.main.assets.srcDirs += 
    new File(project.buildDir, "termsOfUseAssets")

  applicationVariants.all { variant ->
    tasks["merge${variant.name.capitalize()}Assets"]
      .dependsOn(generateTermsOfUseAssets)
  }
}

Neat!