Custom plugin and access to android.applicationVariants

2,043 views
Skip to first unread message

Thomas Bruyelle

unread,
Jul 27, 2013, 3:53:16 PM7/27/13
to adt...@googlegroups.com
I'm trying to write a plugin for the AndroidAnnotations project. For those who don't know that project, it generates superclass from annotated classes, like activities for instance, with apt.

Currently to make things work with the android gradle plugin, I need to add the following code in my build.gradle :

android.applicationVariants.each { variant ->

            // Add special compile for Android Annotations
            def aptOutput = project.file("${project.buildDir}/source/apt_generated/${variant.dirName}")
        
            variant.javaCompile.doFirst {
                println "*** compile doFirst ${variant.name}"
                aptOutput.mkdirs()
                variant.javaCompile.options.compilerArgs += [
                        '-processorpath', configurations.apt.getAsPath(),
                        '-AandroidManifestFile=' + variant.processResources.manifestFile,
                        '-AresourcePackageName=net.tsoft.resetunreadsms',
                        '-s', aptOutput
                ]
            }
        }

I want to write a gradle plugin to perform the same thing, so I wrote this :

class AndroidAnnotationGradlePlugin implements Plugin<Project> {
    void apply(Project project) {
        project.android.applicationVariants.each { variant ->

            // Add special compile for Android Annotations
            def aptOutput = project.file("${project.buildDir}/source/apt_generated/${variant.dirName}")
          
            variant.javaCompile.doFirst {
                println "*** compile doFirst ${variant.name}"
                aptOutput.mkdirs()
                variant.javaCompile.options.compilerArgs += [
                        '-processorpath', configurations.apt.getAsPath(),
                        '-AandroidManifestFile=' + variant.processResources.manifestFile,
                        '-AresourcePackageName=net.tsoft.resetunreadsms',
                        '-s', aptOutput
                ]
            }         
        }
    }
}

But I get the following error when executing gradle assembleDebug :

A problem occurred evaluating root project 'MyProject'.
> Android tasks have already been created.
  This happens when calling android.applicationVariants,
  android.libraryVariants or android.testVariants.
  Once these methods are called, it is not possible to
  continue configuring the model.


It seems not possible to access applicationVariants from another plugin, is there another way to do it ?

Thanks in advance

Peter Fortuin

unread,
Jul 29, 2013, 4:36:18 AM7/29/13
to adt...@googlegroups.com
I also saw this problem when I developed my plugin. I resolved it (and I don't think this is the right way) by moving the 'apply plugin' statement down in my build.gradle below the android {} block. This is probably a good workaround, that will help you to continue developing your plugin. Xavier can probably tell you why this is happening. I'm very interested in a good solution as well. 


2013/7/27 Thomas Bruyelle <thomas....@gmail.com>

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Thomas Bruyelle

unread,
Jul 29, 2013, 5:28:14 AM7/29/13
to adt...@googlegroups.com
Thanks a lot Peter, it works !
Don't know very well Gradle but it seems weird to impose to put the `apply plugin` after the android block. So interested also in a better solution.

Xavier Ducrohet

unread,
Jul 29, 2013, 10:04:09 PM7/29/13
to adt...@googlegroups.com
While you can defer the apply plugin, it's kind of ugly.

Right now calling android.applicationVariant force creating the tasks. It really shouldn't and we should fix this.

What this will do though, it prevent using android.applicationVariant.each in most cases since when you are calling this in your custom plugin (or after the android {} block) the variants and their tasks won't have been generated.

The trick will be to use .all instead of .each.

.all applies the closure to all existing items in the collections right away, and then automatically applies it whenever a new item is added.


On Mon, Jul 29, 2013 at 2:28 AM, Thomas Bruyelle <thomas....@gmail.com> wrote:
Thanks a lot Peter, it works !
Don't know very well Gradle but it seems weird to impose to put the `apply plugin` after the android block. So interested also in a better solution.

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

Peter Fortuin

unread,
Jul 30, 2013, 2:19:37 AM7/30/13
to adt...@googlegroups.com
You are right that my solution is very ugly. 
I'm using the .all instead of the .each, but I have the same problem. But as I understand you correctly you are going to make a fix for this?




2013/7/30 Xavier Ducrohet <x...@android.com>

Xavier Ducrohet

unread,
Jul 30, 2013, 1:57:23 PM7/30/13
to adt...@googlegroups.com
yes .all will only work right when I stop forcing the creation of the tasks when accessing the android.applicationVariants container.

Thomas Bruyelle

unread,
Aug 2, 2013, 5:46:06 AM8/2/13
to adt...@googlegroups.com
It seems the last version deployed today (0.5.5) fixed this issue. 

We can now declare the `apply plugin` just after the `apply plugin: 'android'`, and we now have to use `android.applicationVariants.all`

Peter Fortuin

unread,
Aug 2, 2013, 7:15:34 AM8/2/13
to adt...@googlegroups.com
I also tested the 0.5.5 of the android plugin and it seems to work fine. 
Thanks for the fix!



2013/8/2 Thomas Bruyelle <thomas....@gmail.com>
It seems the last version deployed today (0.5.5) fixed this issue. 

We can now declare the `apply plugin` just after the `apply plugin: 'android'`, and we now have to use `android.applicationVariants.all`

--

Josh Burton

unread,
Jul 29, 2014, 6:47:39 PM7/29/14
to adt...@googlegroups.com
Hi Xavier,

I see this issue has been fixed, but it's reoccurring for me, which I think is due to trying to modify the packagingOptions as well as applicationVariants.

I'm guessing calling the packagingOptions also forces creating the tasks? 

I'm trying to call applicationVariants.all after packagingOptions but am getting the same error:


Android tasks have already been created.
  This happens when calling android.applicationVariants,
  android.libraryVariants or android.testVariants.
  Once these methods are called, it is not possible to
  continue configuring the model.


Can you suggest any work arounds for this?
Reply all
Reply to author
Forward
0 new messages