Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude assets for release build type

I'm importing an android library in an application built with gradle, like that:

dependencies {
    compile 'com.example:great-lib:0.1-SNAPSHOT'
}

This library contains only assets, js, css and images to be used in a webview, with a layout like that:

assets/
|-> great.css
|-> great.min.js
|-> great.min.js.map
|-> js/
|   |-> plop.js
|   |-> foo.js
|   ...
|-> img/
|   ...

The js folder contains source files (to be used with source maps). I would like to include it and the .map file for the debug builds, and have only the minified js in release builds, but I can't find a way to do that.

So far I've tried : 

android {
    // this doesn't exclude anything
    packageOptions {
        exclude 'assets/js'
    }
    buildTypes {
        release {
            // this does exclude the js folder, but in both release and debug
            aaptOptions {
                ignoreAssetsPattern "!js"
            }
        }
    }
}

Any idea if what I want is possible to achieve, and if so how?

(I've also thought of publishing two versions of the library (great-lib and great-lib-debug), and have the dependency in debugCompile and releaseCompile, but I'd prefer avoiding that and publishing a single version)

like image 538
Xavier Avatar asked Mar 06 '15 11:03

Xavier


2 Answers

I had success with this approach (updated 2019-5-13 for TaskProvider support; see edit history for older versions):

android {
⋮
    applicationVariants.all { variant ->
        if (variant.buildType.name == 'release') {
            variant.mergeAssetsProvider.configure {
                doLast {
                    delete(fileTree(dir: outputDir, includes: ['**/js', '**/*.js.map']))
                }
            }
        }
    }
⋮
}

This should address the issues with @Xavier's answer:

  • The deletion is done as part of the variant's mergeAssets task so the deletion is reflected in the task's output and up-to-date checking should be unaffected.
  • The paths are calculated without magic strings. You may need to adjust the include patterns in case my example is too permissive.
  • The variant is being selected by the buildType name, which is less problematic than matching the entire variant name (though it is still stringly typed).

Note that this approach also works for res files rather than assets: just replace mergeAssets with mergeResources.

Other answers mentioning packagingOptions and aaptOptions are barking up the wrong tree, as these are scoped to all variants (they are defined in the android scope, not buildType or productFlavor).

like image 69
Aaron Avatar answered Oct 14 '22 19:10

Aaron


I ended up doing the following:

android.applicationVariants.all { variant ->

  if (variant.name.contains('Release')) {
    // exclude source and sourcemap from release builds
    def noJsSourceTask = task("delete${variant.name}JsSource", type: Delete) {
      delete "${buildDir}/intermediates/assets/${variant.dirName}/js"
      delete "${buildDir}/intermediates/assets/${variant.dirName}/great.min.js.map"
    }
    variant.mergeAssets.finalizedBy noCeJsSourceTask
  }
}

It works ok, but there are a few things I don't really like:

  • I'm touching at the files produced by a task after it is done (the finalizedBy), so it doesn't work well with "up-to-date" checking. But it's only for release builds, I'm doing debug ones more often
  • the path of the files to delete is manually built. I'm not sure if it's generic enough to be reused in other projects as-is
  • I'm selecting the variants based on their name. I would have liked something more structured.
like image 22
Xavier Avatar answered Oct 14 '22 19:10

Xavier