Custom Android Compose Project Template For Android Studio
Learn how to create a new Android project template for Android Studio and Intellij Idea CE.

Here I will show you how to create a new Android Compose project template for Android Studio / IntelliJ Idea CE.

Android Studio Project Templates

Reason

I wanted to create this template because I wanted to add the Compose Compiler to new projects. The default project templates didn't have it built in so it needed to be manually loaded. This took a little extra time when starting new projects. In this guide below I outlined my steps to create a custom Android Compose project template for Android Studio.

Setup

You will need to create a plugin for Android Studio using IntelliJ Idea CE ( Community Edition ), it is free.

After you download and install the IDE, you will need to get the base plugin, IntelliJ Platform Plugin. You can get it from https://github.com/JetBrains/intellij-platform-plugin-template. This plugin is a template that is a good starting point to create your own. Alternatively, you could use the New Project Wizard in IntelliJ Idea CE to create the plugin from scratch.

IntelliJ Idea CE

In IntelliJ Idea CE, go to File >> New >> Project...

Set the Type as Plugin.

IntelliJ Platform Gradle Plugin

For the rest of this post I will show you how I used the template from Github.

You can either clone the repository to your Github or download the zip. I chose to download the zip in case I needed to go back to the original multiple times ( which I did ).

At the Github template site, you can read to directions on how to configure the template. They seem straightforward but I still had issues trying to make it all work. I also referenced the IntelliJ Platform Gradle Plugin Site. This is useful but to me was missing some straightforward directions out of the box for my use case.

I read through many posts online but had issues due to the posts were comprised of using the IntelliJ Platform Gradle Plugin (1.0). The link above shows directions with the new IntelliJ Platform Gradle Plugin (2.0). The old version is not supported on the newer builds of Android Studio I was using so I needed to build the plugin using the newer versions.

Guide

Get Template

As I stated above I chose to download the zip. I then extracted the contents to a folder in the root of my IdeaProjects folder. This may be different for everyone but is defaulted to:

C:\Users\<USERNAME>\IdeaProjects\

Create Project For Plugin

There I opened the project

File >> Open >> Select the directory of the extracted folder. For the rest of this walkthrough, I changed the root folder of the project to test before I opened it in IntelliJ Idea CE.

Edit build.gradle

Now open the build.gradle.kts file

Here I changed the JVM target from 17 to 21.

kotlin {
    jvmToolchain(17)
}
kotlin {
    jvmToolchain(21) // 17
}

Referencing IDE Android Plugin for build.gradle

Now is the part that you need to do a little research on the plugin of Android you have installed on your IDE. You will need to reference the plugins release chart at Android Studio Plugin Development

Open the IDE you are using and open the top toolbar

Navigate to Help >> About

You will need to look at the build version and the IDE version. For Android Studio, reference the releases link above to get the appropriate information for your build.

You may also go to the top of the current plugin page in the IDE you are using and check the build version there. For IntelliJ I need to go there for the version of Android that is used.

IntelliJ IDEA CE

File >> Settings >> Plugins

As shown above, for either IDE, you will need Android plugin ( obviously already installed on Android Studio ) as well as the Plugin Devkit. The android plugin version number here is shown from my IntelliJ IDE.

I will need to specify for IntelliJ Idea CE -> org.jetbrains.android:243.22562.218

Or for my Android Studio -> org.jetbrains.android:242.23339.11

build.gradle

Now with the information you need, you can move on by adding the plugin with version in the build.gradle file. I added this after the repository block.

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()
    }
}

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

Edit gradle.properties

Now you will open the gradle.properties file and make a few changes. Below is the default template.

# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html

pluginGroup = org.jetbrains.plugins.template
pluginName = IntelliJ Platform Plugin Template
pluginRepositoryUrl = https://github.com/JetBrains/intellij-platform-plugin-template
# SemVer format -> https://semver.org
pluginVersion = 2.0.2

# 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

# 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
platformPlugins =
# Example: platformBundledPlugins = com.intellij.java
platformBundledPlugins =

# Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 8.10.2

# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
kotlin.stdlib.default.dependency = false

# Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
org.gradle.configuration-cache = true

# Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html
org.gradle.caching = true

Breakdown

You will need to change:

pluginGroupchange to what you want your structure to be
pluginNamechange to your own plugin name
pluginSinceBuildfirst set of digits from the android plugin version used
pluginUntilBuildfirst set of digits from the android plugin version used end along with .*
platformTypeIC = IntelliJ Idea CE IDE used or AI is Android Studio, leave as IC if doing plugin for both
platformVersionversion of the IDE. Use the version found from step above
platformPluginsorg.jetbrains.android:<version found in step above>
platformBundledPluginscom.intellij.java, org.jetbrains.kotlin
  • also remove both gradle cache entries

Below is what I changed mine to

# IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html

pluginGroup = com.template.r2creations24.testingtemplate
pluginName = Testing Template
pluginRepositoryUrl = https://github.com/JetBrains/intellij-platform-plugin-template
# SemVer format -> https://semver.org
pluginVersion = 2.0.2

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

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

# 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
platformPlugins = org.jetbrains.android:243.22562.218
# Example: platformBundledPlugins = com.intellij.java
platformBundledPlugins = com.intellij.java, org.jetbrains.kotlin

# Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 8.10.2

# Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib
kotlin.stdlib.default.dependency = false

Edit settings.gradle.kts

Now open the settings.gradle.kts file

Change the rootProject.name to what you put in pluginName in step above.

Refactor Template Namespace

Now we will refactor the project path as the pluginGroup that we entered in step above

In the Project window on the left pane, expand until you expose the org.jetbrains.plugins.template and change to what you entered as pluginGroup.

Edit plugin.xml

Now we will edit the plugin.xml file. It is located at:

src >> main >> kotlin >> resources >> META-INF >>

Change the name tag to the pluginName you entered in step above

Then we will need to add a few dependencies here as well as the New Project Wizard reference.

Add the below tags under the com.intellij.modules.platform depends tag

NOTE

If you set the platform as IC for IntelliJ IdeaCE in step above, remove the androidstudio tag stated below. If using Android Studio and you set the platform to AI above, then keep it.

<depends>com.intellij.modules.androidstudio</depends>
    <depends>org.jetbrains.android</depends>
    <depends>org.jetbrains.kotlin</depends>
    <depends>com.intellij.modules.java</depends>
    <depends>com.intellij.modules.androidstudio</depends>

Then add the following extension tag suited to your namespace

    <extensions defaultExtensionNs="com.android.tools.idea.wizard.template">
        <wizardTemplateProvider implementation="com.template.r2creations24.testingtemplate.MyProjectTemplatesProvider"/>
    </extensions>

Wizard Template

Now lets create the MyProjectTemplatesProvider referencing in the previous step.

I added mine to the root of the pluginGroup name as you see in the implementation reference statement in step #8. You can put it where ever you want just make sure to update the reference.

MyProjectTemplatesProvider.kt

Create file MyProjectTemplatesProvider.kt

import com.android.tools.idea.wizard.template.Template
import com.android.tools.idea.wizard.template.WizardTemplateProvider
import com.template.r2creations24.testingtemplate.emptyActivity.*

class MyProjectTemplatesProvider : WizardTemplateProvider() {

    override fun getTemplates(): List<Template> {
        return listOf(projectTemplate)
    }
}

Create Package For Template Classes

Now the initial setup is done.

The next 3 files I have declared here are created from the post I saw here to help me create this plugin.

https://sasikanth.dev/creating-project-templates-in-android-studio

We just need to create the empty activity for us to use as well as the way for the WizardTemplateProvider to get its reference to it.

I created a new package off of the pluginGroup com.template.r2creations24.testingtemplate name emptyActivity to hold the next few classes.

Right-click on the pluginGroup in the Project window pane on the left.

New >> Package >> give it a name ( mine is emptyActivity )

Create Template Files

ProjectTemplate.kt

Create a new file in this package. name ProjectTemplate.kt and add the below code

import com.android.tools.idea.wizard.template.*
import com.android.tools.idea.wizard.template.Constraint.*
import com.android.tools.idea.wizard.template.impl.defaultPackageNameParameter
import java.io.File

val projectTemplate
    get() = template {
        name = "Empty Activity"
        description = "Create a new empty activity with Jetpack Compose"
        minApi = 24
        constraints = listOf(
            TemplateConstraint.AndroidX, TemplateConstraint.Kotlin, TemplateConstraint.Material3,
            TemplateConstraint.Compose)

        category = Category.Compose
        formFactor = FormFactor.Mobile
        screens = listOf(WizardUiContext.ActivityGallery, WizardUiContext.MenuEntry, WizardUiContext.NewProject, WizardUiContext.NewModule, WizardUiContext.NewProjectExtraDetail)

        val activityClass = stringParameter {
            name = "Activity Name"
            default = "MainActivity"
            help = "The name of the activity class to create"
            constraints = listOf(CLASS, UNIQUE, NONEMPTY)
            //loggable = true
        }

        val packageName = defaultPackageNameParameter

        val isLauncher = booleanParameter {
            name = "Launcher Activity"
            default = true
            visible = { true }
            help = "If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher"
        }

        val greeting = stringParameter {
            name = "Greeting function name"
            default = "Greeting"
            help = "Used for deduplication"
            visible = { false }
            constraints = listOf(UNIQUE, KOTLIN_FUNCTION)
            //loggable = true
        }

        val defaultPreview = stringParameter {
            name = "Default Preview function name"
            default = "${greeting.value}Preview"
            help = "Used for deduplication"
            visible = { false }
            constraints = listOf(UNIQUE, KOTLIN_FUNCTION)
            //loggable = true
        }

        val canAddComposeDependencies = booleanParameter {
            name = "Add Compose Dependencies"
            default = false
            visible = { true }
        }

        widgets(
            TextFieldWidget(activityClass),
            PackageNameWidget(packageName),
            CheckBoxWidget(isLauncher),
            CheckBoxWidget(canAddComposeDependencies),
            // Invisible widgets to pass data
            TextFieldWidget(greeting),
            TextFieldWidget(defaultPreview),
            LanguageWidget()
        )

        thumb { File("compose-activity-material3").resolve("template_compose_empty_activity_material3.png") }

        recipe = { data: TemplateData ->
            projectRecipe(
                data as ModuleTemplateData,
                activityClass.value,
                packageName.value,
                defaultPreview.value,
                greeting.value,
                isLauncher.value,
                canAddComposeDependencies = canAddComposeDependencies.value
            )
        }
    }

ProjectRecipe.kt

In the same package/directory add another file named ProjectRecipe.kt. This is the main section of the whole process to add Compose to your custom Android Compose project template. You will need to add the following.

import com.android.tools.idea.wizard.template.ModuleTemplateData
import com.android.tools.idea.wizard.template.PackageName
import com.android.tools.idea.wizard.template.RecipeExecutor
import com.android.tools.idea.wizard.template.impl.activities.common.addAllKotlinDependencies
import com.android.tools.idea.wizard.template.impl.activities.common.addLifecycleDependencies
import com.android.tools.idea.wizard.template.impl.activities.common.addMaterial3Dependency
import com.android.tools.idea.wizard.template.impl.activities.common.generateManifest

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)
}

EmptyActivity.kt

In the same package/directory add another file named EmptyActivity.kt and add the following

import com.android.tools.idea.wizard.template.escapeKotlinIdentifier

fun emptyActivity(
    packageName: String,
    activityClass: String,
    defaultPreview: String,
    greeting: String,
    themeName: String
) = """
package ${escapeKotlinIdentifier(packageName)}

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import ${escapeKotlinIdentifier(packageName)}.ui.theme.${themeName}

class $activityClass : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            $themeName {
                Scaffold( modifier = Modifier.fillMaxSize() ) { innerPadding ->
                    ${greeting}(
                        name = "Android",
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}

@Composable
fun ${greeting}(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello ${"$"}name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun ${defaultPreview}() {
    $themeName {
        ${greeting}("Android")
    }
}
"""

Update libs.versions.toml

Update the Kotlin and the Intellij plugin to the latest version. Currently this is what I edited. Can be found in Project pane to the left

<projectname> >> gradle

intelliJPlatform = "2.2.1"
kotlin = "2.0.0"

Sync Gradle and Build Plugin

We are done. We can sync gradle and then build the plugin. Open the gradle pane in on the right toolbar. Click Sync. When done, then buildPlugin

The plugin will build and be inside your

C:\Users\<username>\IdeaProjects\test\build\libs\

Now you can go to your IDE settings and add the plugin.

File >> Settings >> Plugins ( left pane )

Then Install Plugin From Disk...

Hope this was helpful to anyone that wants to learn how to create an Android Compose project template.

Issues I Had

I spent about a week trying to get this to work in Android Studio. It works in IntelliJ Idea CE no problem. In Android Studio, it installs and works fine unless if I tick the Add Compose Dependencies in the creation wizard.

No matter what I changed, it kept giving me a failure pointing to the android plugin build couldn't find the addDependency("") method.

From my research, it seems that org.jetbrains.android:242.23339.11 has a issue with the DependencyHelper.

I posted help

https://stackoverflow.com/questions/79291235/adddependency-issue-in-intellij-platform-plugin-for-android-studio-to-create-new

I also posted it at:

https://intellij-support.jetbrains.com/hc/en-us/community/posts/23450869457042-Creating-an-Android-Studio-plugin-to-create-new-project-templates-NoMethodFound-addDependency

I am sharing in case if someone comes across same issue. I would prefer to just use 1 IDE but in the meantime this works.