Creating an Android Studio plugin to create new project templates . NoMethodFound addDependency

Answered

I am trying to create a New Project Template in IntelliJ IDEA CE for Android Studio. I have successfully done so but I would like to add more dependencies to the default template the plugin is creating, not the plugin itself. Mainly want to add more compose dependencies at time of creation of new project.

ProjectRecipe

private const val COMPOSE_BOM_VERSION = "2024.12.01"
private const val COMPOSE_KOTLIN_COMPILER_VERSION = "1.5.1"

fun RecipeExecutor.projectRecipe(
    moduleData: ModuleTemplateData,
    activityName: String,
    packageName: PackageName,
    defaultPreview : String,
    greeting : String,
    isLauncher : Boolean,
    canAddComposeDependencies: Boolean
) {

    requireJavaVersion("1.8", true)
    setBuildFeature("compose", true)
    // Note: kotlinCompilerVersion default is declared in TaskManager.COMPOSE_KOTLIN_COMPILER_VERSION
    setComposeOptions(kotlinCompilerExtensionVersion = COMPOSE_KOTLIN_COMPILER_VERSION)
    addMaterial3Dependency()
    addLifecycleDependencies(true)
    addAllKotlinDependencies(moduleData)

    generateManifest(
        moduleData = moduleData,
        activityClass = activityName,
        activityThemeName = moduleData.themesData.main.name,
        packageName = packageName,
        isLauncher = isLauncher,
        hasNoActionBar = true,
        generateActivityTitle = true
    )

    applyPlugin("org.jetbrains.kotlin.plugin.compose", "2.0.0")
    if (canAddComposeDependencies) {
        addDependency(mavenCoordinate = "androidx.lifecycle:lifecycle-runtime-ktx:+")
        addDependency(mavenCoordinate = "androidx.activity:activity-compose:+")
        addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$COMPOSE_BOM_VERSION")
        addPlatformDependency(mavenCoordinate = "androidx.compose:compose-bom:$COMPOSE_BOM_VERSION", configuration = "androidTestImplementation")

        val composeUiFormattedVersion = moduleData.let { ":$it" } ?: ""
        addDependency(mavenCoordinate = "androidx.compose.ui:ui$composeUiFormattedVersion")
        addDependency(mavenCoordinate = "androidx.compose.ui:ui-graphics")
        addDependency(mavenCoordinate = "androidx.compose.ui:ui-tooling", configuration = "debugImplementation")
        addDependency(mavenCoordinate = "androidx.compose.ui:ui-tooling-preview")
        addDependency(mavenCoordinate = "androidx.compose.ui:ui-test-manifest", configuration="debugImplementation")
        addDependency(mavenCoordinate = "androidx.compose.ui:ui-test-junit4", configuration="androidTestImplementation")

        addDependency(mavenCoordinate = "androidx.compose.material3:material3")
    }



    val themeName = "${moduleData.themesData.appName}Theme"

    val emptyActivity = emptyActivity(packageName, activityName, defaultPreview, greeting, themeName)
    val emptyActivityPath = moduleData.srcDir.resolve("$activityName.kt")
    save(emptyActivity, emptyActivityPath)
    open(emptyActivityPath)
}

When  I don't check add compose dependencies, the new project creates and build fine. When I check the add compose dependency in the new project template wizard. It fails with the below issue.

 

java.lang.NoSuchMethodError: 'void com.android.tools.idea.wizard.template.RecipeExecutor.addDependency$default(com.android.tools.idea.wizard.template.RecipeExecutor, java.lang.String, java.lang.String, java.lang.String, java.io.File, boolean, int, java.lang.Object)' at com.template.r2creations24.demo.emptyActivity.ProjectRecipeKt.projectRecipe(ProjectRecipe.kt:42) at com.template.r2creations24.demo.emptyActivity.ProjectTemplateKt$projectTemplate$1$2.invoke(ProjectTemplate.kt:76) at com.template.r2creations24.demo.emptyActivity.ProjectTemplateKt$projectTemplate$1$2.invoke(ProjectTemplate.kt:75) at com.android.tools.idea.npw.model.NewTemplateRendererKt$doRender$1.run(NewTemplateRenderer.kt:98) at com.intellij.openapi.command.WriteCommandAction$BuilderImpl.lambda$doRunWriteCommandAction$1(WriteCommandAction.java:147) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction$lambda$4(AnyThreadWriteThreadingSupport.kt:318) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:328) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:318) at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:890) at com.intellij.openapi.command.WriteCommandAction$BuilderImpl.lambda$doRunWriteCommandAction$2(WriteCommandAction.java:145) at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:226) at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:188) at com.intellij.openapi.command.WriteCommandAction$BuilderImpl.doRunWriteCommandAction(WriteCommandAction.java:154) at com.intellij.openapi.command.WriteCommandAction$BuilderImpl.lambda$run$0(WriteCommandAction.java:125) at com.intellij.util.concurrency.ContextRunnable.run(ContextRunnable.java:27) at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:229) at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:22) at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:191) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread$lambda$1(AnyThreadWriteThreadingSupport.kt:184) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:84) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread(AnyThreadWriteThreadingSupport.kt:183) at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:836) at com.intellij.openapi.application.impl.ApplicationImpl$2.run(ApplicationImpl.java:424) at com.intellij.openapi.application.impl.LaterInvocator$1.run(LaterInvocator.java:101) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWithImplicitRead(AnyThreadWriteThreadingSupport.kt:122) at com.intellij.openapi.application.impl.ApplicationImpl.runWithImplicitRead(ApplicationImpl.java:1162) at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:78) at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:119) at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:41) at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.desktop/java.awt.EventQueue$4.run(Unknown Source) at java.desktop/java.awt.EventQueue$4.run(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source) at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source) at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:696) at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$16(IdeEventQueue.kt:590) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWithoutImplicitRead(AnyThreadWriteThreadingSupport.kt:117) at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:590) at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:73) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1$1.compute(IdeEventQueue.kt:357) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1$1.compute(IdeEventQueue.kt:356) at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:843) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.invoke(IdeEventQueue.kt:356) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.invoke(IdeEventQueue.kt:351) at com.intellij.ide.IdeEventQueueKt$performActivity$runnableWithWIL$1.invoke$lambda$0(IdeEventQueue.kt:1035) at com.intellij.openapi.application.WriteIntentReadAction.lambda$run$0(WriteIntentReadAction.java:24) at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:84) at com.intellij.openapi.application.impl.ApplicationImpl.runWriteIntentReadAction(ApplicationImpl.java:910) at com.intellij.openapi.application.WriteIntentReadAction.compute(WriteIntentReadAction.java:55) at com.intellij.openapi.application.WriteIntentReadAction.run(WriteIntentReadAction.java:23) at com.intellij.ide.IdeEventQueueKt$performActivity$runnableWithWIL$1.invoke(IdeEventQueue.kt:1035) at com.intellij.ide.IdeEventQueueKt$performActivity$runnableWithWIL$1.invoke(IdeEventQueue.kt:1035) at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1036) at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:106) at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1036) at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$10(IdeEventQueue.kt:351) at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:397) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

Creating the plugin in Intellij IDEA is fine and doesn't throw an error. It builds and installs without issue.

build.gradle.kts

plugins {
    id("java") // Java support
    alias(libs.plugins.kotlin) // Kotlin support
    alias(libs.plugins.intelliJPlatform) // - intelliJPlatform -  IntelliJ Platform Gradle Plugin
    //alias(libs.plugins.gradleIntelliJPlugin)
    alias(libs.plugins.changelog) // Gradle Changelog Plugin
    alias(libs.plugins.qodana) // Gradle Qodana Plugin
    alias(libs.plugins.kover) // Gradle Kover Plugin
}

group = providers.gradleProperty("pluginGroup").get()
version = providers.gradleProperty("pluginVersion").get()

// Set the JVM language level used to build the project.
kotlin {
    jvmToolchain(21) // 17
}

// Configure project's dependencies

repositories {
    mavenCentral()

    // IntelliJ Platform Gradle Plugin Repositories Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-repositories-extension.html
    intellijPlatform {
        defaultRepositories()
        gradlePluginPortal()
        //localPlatformArtifacts()
    }
}

dependencies {
    intellijPlatform {
        plugin("org.jetbrains.android:242.23339.11")
        //local("C:\\Program Files\\Android\\Android Studio\\bin")
        //androidStudio("2024.2.1.12")
        //bundledPlugin("org.jetbrains.android")
    }
}

plugins.xml

<depends>com.intellij.modules.platform</depends>
<!-- We define the dependencies we will use. -->
<depends>org.jetbrains.android</depends>
<depends>org.jetbrains.kotlin</depends>
<depends>com.intellij.modules.java</depends>
<depends>com.intellij.modules.androidstudio</depends>

gradle.properties

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 233
pluginUntilBuild = 242.*

# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
#platformType = IC
#platformVersion = 2023.3.8 ----- AI -> 2024.2.1.12
platformType = IC
platformVersion = 2024.2.3

# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
#java, com.intellij.java, org.jetbrains.android, android, org.jetbrains.kotlin
platformPlugins =
# Example: platformBundledPlugins = com.intellij.java
#com.intellij.java, org.jetbrains.kotlin
platformBundledPlugins = com.intellij.java

Most was generated from the Intellij Plugin Template -  https://github.com/JetBrains/intellij-platform-plugin-template

I followed this guide for Android Studio - https://plugins.jetbrains.com/docs/intellij/android-studio.html

Any guidance? What am I missing?

 

***********UPDATE

I have just tried the plugin in IntelliJ IDEA CE. It run perfectly fine. Exactly as expected. I am still having issues with the plugin in Android Studio. The same issue as stated above. It fails on the "addDependency()" method with NoSuchMethodError.

Anyone have any ideas?

I wonder if it has an issue with the Android plugin used in Android Studio. The one in my Android Studio is

org.jetbrains.android:242.23339.11

while my IntelliJ IDEA CE is using

org.jetbrains.android:243.22562.218

0
3 comments

Hi,

As far as I can see, RecipeExecutor is a part of Android Studio code, so it looks strange it worked for you in IntelliJ IDEA CE, but didn't in Android Studio.

It is unclear in what setups you tested it (). Also, plugin.xml and related files could be helpful to diagnose the issue. As far as I understand, this:

dependencies {
    intellijPlatform {
        plugin("org.jetbrains.android:242.23339.11")
        ...
}

doesn't include any IDE, and it shouldn't work.

0

From the IntelliJ Platform Plugin SDK site, https://plugins.jetbrains.com/docs/intellij/android-studio.html#gradle-build-script

They state to add this 

dependencies {
    intellijPlatform {
        plugin("org.jetbrains.android:243.22562.218")
        }
}

To specify the Android plugin that is being used as the base for the plugin being made.

Basically specify the Android Plugin version that is installed on IntelliJ IDE or the version installed on Android Studio. For me, they are different versions.

In the gradle.properties, I added this to specify I want the plugin for IntelliJ IDE

platformType = IC
platformVersion = 2024.2.3

or if I wanted to build plugin for the standalone Android Studio

platformType = AI
platformVersion = 2024.2.1.12

and then added the following to the gradle.properties as stated in the link above for Android Studio

<depends>com.intellij.modules.androidstudio</depends>

Either way I go with it, RecipeExecutor is in both versions of the Android plugin, even the method of addDependency() I can see are in both. The error only shows after creating the new template in the wizard via the plugin I am making. The stacktrace keeps showing the addDependency() method as the issue stating NoSuchMethodError. - its weird it is just doing it in Android Studio, no problems in IntelliJ IDE.

I mainly posted my configuration arrangement here thinking it would be the most important information. I don't mind posting the rest of the project but there is quite a bit.

The rest of the code I used is posted https://shift2dev.com/2024/12/25/create-custom-new-android-compose-project-template-for-android-studio/. This shows all my code as well as my steps for creation.

If you prefer me to post here, just let me know. I really would like this to work for Android Studio. I prefer to stick with 1 IDE.

Thank you. Any guidance would be appreciated.

0

This is an invalid configuration:

dependencies {
    intellijPlatform {
        plugin("org.jetbrains.android:243.22562.218")
    }
}

It doesn't specify a platform type. I tested it locally and it fails with the error: No IntelliJ Platform dependency found.

The section you linked states:

dependencies {
  intellijPlatform {
    androidStudio("<versionNumber>")
    bundledPlugin("org.jetbrains.android")
  }
}

The plugin() function is for plugins from JetBrains Marketplace.

The bundledPlugin() is for plugins bundled within the IDE.

I suggest creating two separate runIde tasks:

  1. Exactly as described here: https://plugins.jetbrains.com/docs/intellij/android-studio.html#intellij-platform-gradle-plugin-2x. Your setup is different and seems invalid. The runIde task will run Android Studio with a bundled plugin as a dependency (bundledPlugin()).
  2. A custom runIntelliJIdeaWithAndroid that will add a dependency on IntelliJ IDEA CE and Android plugin from the marketplace (plugin()). See https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-testing-extension.html on how to register this task.

EDIT: Sorry, I just noticed the info about Targeting 2023.3+ (the plugin is not bundled anymore). I'll try to take a look at this again later.

0

Please sign in to leave a comment.