3

I have this code at the end of my build.gradle file:

         project.afterEvaluate {

            // If you add/change build types, you have to add to/change
            // these task names.
            mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')

        }

See: Copy generated third party licenses to assets for the full code

This used to work fine (regardless of which buildType was set) but if updating my dependencies to the latest version this triggers an exception (when building with buildType='debug'):

Could not get unknown property 'mergeReleaseAssets' for project ':application'

My thought was that maybe split this block in two and put them under the buildTypes configuration. This doesn't work though, as it tries to evaluate the code anyway and crashes.

Any ideas?

Update 1: Root cause? https://code.google.com/p/android/issues/detail?id=219732

Update 2: A horrible workaround:

try {
    mergeDebugAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Release
}
try {
    mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
} catch (Exception e) {
    // Expected when building variant Debug
}
Alix
  • 2,630
  • 30
  • 72
  • are you sure you didn't misstype something? To me the message means he just can't find the task mergeReleaseAssets. Maybe you wrote the original task different. (happened to me some times by now) – Nico Dec 20 '16 at 10:04
  • No, the code is exactly the same as before I updated the dependencies. The problem, as I see it, is that Gradle (or related plugin) has become more strict – Alix Dec 20 '16 at 10:13
  • I'm also only getting used to gradle so I might suggest this http://stackoverflow.com/questions/39590549/after-update-to-android-studio-2-2-gradle-plugin-2-2-0-could-not-get-unknown. Try playing around with `task.finalizedBy` or `task(){ dependsOn 'task2' }`. This might be because of the slightly changed dependency system – Nico Dec 20 '16 at 10:21
  • Interesting. Following your link I found this issue: https://code.google.com/p/android/issues/detail?id=219732 which seems to be the root cause. – Alix Dec 20 '16 at 11:11
  • Did you try to upgrade Gradle manually? I don't know what IDE you are using and if it is possible but if you are using Gradle 2.2 you could try updating to Gradle 3.1 – Nico Dec 20 '16 at 11:36
  • I have upgraded Gradle as well – Alix Dec 20 '16 at 12:45
  • What is the output of `gradle tasks --all` look for `mergeReleaseAssets` – JBirdVegas Dec 20 '16 at 14:11
  • It's not there. As expected. I can find mergeDebugAssets of course – Alix Dec 20 '16 at 14:17

2 Answers2

8

The reason that you get an error referencing a release task in afterEvaluate is probably because Android Studio's Instant Run feature uses a special Android Gradle plugin feature to only build the debug application variant. This means that only the debug tasks are created, hence why the release tasks can't be found when you reference them.

There are several ways to deal with this:

  1. Search for the dependent task by name using a string. If the Android build system changes the task name in the future, your additional build rules won't run, but you might not even notice.

  2. To determine if release tasks exist, check for the existence of a task whose name is unlikely to change in the future. Maybe assembleRelease fits this bill.

  3. To determine if release tasks exist, check if the release application variant is built with something like:

    project.afterEvaluate {
        if (!android.applicationVariants.matching { it.buildType.name == 'release' }.isEmpty()) {
            mergeReleaseAssets.dependsOn project.tasks.getByName('downloadLicenses')
        }
    }
    

The last option looks kind of gross, but hopefully it will fail-fast if the Android build system task names change in the future.

Xargs
  • 769
  • 8
  • 12
5

The reason you get exception in case of debug buildType is because mergeReleaseAssets task is not created. You can do the following instead:

project.tasks.findByName('mergeReleaseAssets')?.dependsOn project.tasks.getByName('downloadLicenses')

or even omit project:

tasks.findByName('mergeReleaseAssets')?.dependsOn tasks.getByName('downloadLicenses')

This uses safe navigation operator on nullable return type, so it's clearer than try/catch workaround.

Ivan Frolov
  • 1,008
  • 8
  • 6