4

Been working on an Android Webview app and I've only just now started to use a node_modules folder in there, so naturally I did some research on how to exclude it and I ended up at this question here

Tried some of the answers and the one that actually worked the best for me was the one about aaptOptions

So of course naturally I'm playing around with it, trying to figure out what works, and I succeed at excluding a few folders from the debug apk.

            aaptOptions {
                ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
            }

And I can indeed confirm that those folders aren't included in the final APK in Android studio! Success!

So then I realize that I can do something a bit clever: when I'm running my app, testing it on my end, debugging it, I like to have certain credentials in certain places automatically put in - I do this with javascript - but obviously I don't want these credentials included in the APKs I might send out into the world -- even though I've already coded it to not input the credentials automatically unless I'm debugging, the credentials are still actually in the javascript files, and presumably someone could look in there and see them!

So my idea was to create a file, 'example-creds.js', and use aaptOptions to not include that file, ONLY on release builds, so I came up with something that looks approximately like this (extra details stripped out):

android {
    buildTypes {
        release {
            aaptOptions {
                ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:!example-creds.js:'
            }
        }

        debug {
            aaptOptions {
                ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
            }
        }
    }
}

BUT IT DOESN'T WORK! I've tested it and it seems to run whatever the last-defined aaptOptions is, regardless of the build type. If I put release after debug, I get no example-creds in either build. If I put debug after release, I get example-creds in both.

How can I get what I'm looking for?

TKoL
  • 13,158
  • 3
  • 39
  • 73

2 Answers2

1

Generally it should be possible to configure AaptOptions alike any other configuration block. Try to run that script afterEvaluate (which is after those aaptOptions had been evaluated):

task afterEvaluate {
    doLast {
        applicationVariants.all { variant ->
            variant.outputs.all { output ->
                def pattern = "!node_modules:!jsunmin:!.idea:!jade:!css-scss:"
                if(variant.getBuildType().getName() == 'release') {
                    pattern = pattern + "!example-creds.js:"
                }
                aaptOptions.ignoreAssetsPattern = pattern
            }
        }
    }
}
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
1

aaptOptions's ignoreAssetPattern cannot be set in afterEvaluate block. If you try, you will run into this error

com.android.build.gradle.internal.dsl.AgpDslLockedException: It is too late to set ignoreAssetsPattern
It has already been read to configure this project.
Consider either moving this call to be during evaluation,
or using the variant API.

The solution is to use the variant API during configuration (also note that aaptOptions is depricated and is renamed to androidResources AGP 7.1.3 onwards)

android {
    buildTypes {
        release {
            androidResources {
                ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
            }
        }

        debug {
            androidResources {
                ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
            }
        }
    }
    androidComponents {
        onVariants(selector().withName("release")) { variant ->
            def pattern = variant.androidResources.ignoreAssetsPattern
            pattern.add("!example-creds.js")
        }
    }
}
rottweiler
  • 1,201
  • 1
  • 12
  • 23