From 3c1a625f858c78d60f62b4837754871643fb4cae Mon Sep 17 00:00:00 2001 From: Fabio Martino Date: Wed, 25 Dec 2024 19:34:35 +0100 Subject: [PATCH 01/10] (feat) Add Kotlin/Java selectable choice --- README.md | 1 + assets/plugin-template/README.md.mustache | 13 +++++ .../android/build.gradle.mustache | 15 ++++++ .../src/main/kotlin/__JAVA_PATH__.kt.mustache | 12 +++++ .../kotlin/__JAVA_PATH__Plugin.kt.mustache | 23 +++++++++ src/help.ts | 1 + src/options.ts | 3 ++ src/prompt.ts | 9 ++++ src/template.ts | 51 ++++++++++++++++--- 9 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__.kt.mustache create mode 100644 assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__Plugin.kt.mustache diff --git a/README.md b/README.md index f055a05..1c966c8 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,5 @@ As of the `0.8.0` release, example apps for testing are included when initializi --author ......... Author name and email (e.g. "Name ") --license ............ SPDX License ID (e.g. "MIT") --description ...... Short description of plugin features +--android-lang ..... Language for Android plugin development (e.g. "kotlin" or "java") ``` diff --git a/assets/plugin-template/README.md.mustache b/assets/plugin-template/README.md.mustache index 837a83f..eab36d9 100644 --- a/assets/plugin-template/README.md.mustache +++ b/assets/plugin-template/README.md.mustache @@ -4,8 +4,21 @@ ## Install +To use npm + ```bash npm install {{{ PACKAGE_NAME }}} +```` + +To use yarn + +```bash +yarn add {{{ PACKAGE_NAME }}} +``` + +Sync native files + +```bash npx cap sync ``` diff --git a/assets/plugin-template/android/build.gradle.mustache b/assets/plugin-template/android/build.gradle.mustache index 350a9bb..f84c20f 100644 --- a/assets/plugin-template/android/build.gradle.mustache +++ b/assets/plugin-template/android/build.gradle.mustache @@ -3,19 +3,31 @@ ext { androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0' androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1' androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1' +{{ #KOTLIN }} + androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.15.0' +{{ /KOTLIN }} } buildscript { +{{ #KOTLIN }} + ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25' +{{ /KOTLIN }} repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:8.7.2' +{{ #KOTLIN }} + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" +{{ /KOTLIN }} } } apply plugin: 'com.android.library' +{{ #KOTLIN }} +apply plugin: 'kotlin-android' +{{ /KOTLIN }} android { namespace "{{ PACKAGE_ID }}" @@ -52,6 +64,9 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':capacitor-android') implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" +{{ #KOTLIN }} + implementation "androidx.core:core-ktx:$androidxCoreKTXVersion" +{{ /KOTLIN }} testImplementation "junit:junit:$junitVersion" androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" diff --git a/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__.kt.mustache b/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__.kt.mustache new file mode 100644 index 0000000..341ff69 --- /dev/null +++ b/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__.kt.mustache @@ -0,0 +1,12 @@ +package {{ PACKAGE_ID }} + +import android.util.Log + +class {{ CLASS }} { + + fun echo(value: String?): String? { + Log.i("Echo", value ?: "null") + + return value + } +} diff --git a/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__Plugin.kt.mustache b/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__Plugin.kt.mustache new file mode 100644 index 0000000..52ee14c --- /dev/null +++ b/assets/plugin-template/android/src/main/kotlin/__JAVA_PATH__Plugin.kt.mustache @@ -0,0 +1,23 @@ +package {{ PACKAGE_ID }} + +import com.getcapacitor.JSObject +import com.getcapacitor.Plugin +import com.getcapacitor.PluginCall +import com.getcapacitor.annotation.CapacitorPlugin +import com.getcapacitor.PluginMethod + +@CapacitorPlugin(name = "{{ CLASS }}") +class {{ CLASS }}Plugin : Plugin() { + + private val implementation = {{ CLASS }}() + + @PluginMethod + fun echo(call: PluginCall) { + val value = call.getString("value") + + val ret = JSObject().apply { + put("value", implementation.echo(value)) + } + call.resolve(ret) + } +} diff --git a/src/help.ts b/src/help.ts index db53697..dc0c53a 100644 --- a/src/help.ts +++ b/src/help.ts @@ -10,6 +10,7 @@ const help = ` --author ......... Author name and email (e.g. "Name ") --license ............ SPDX License ID (e.g. "MIT") --description ...... Short description of plugin features + --android-lang ............ Language for Android plugin development (e.g. "kotlin" or "java") -h, --help ................ Print help, then quit --verbose ................. Print verbose output to stderr diff --git a/src/options.ts b/src/options.ts index cc852bc..c56baec 100644 --- a/src/options.ts +++ b/src/options.ts @@ -17,6 +17,7 @@ export interface OptionValues { author: string; license: string; description: string; + 'android-lang': string; } export type Validators = { @@ -57,6 +58,8 @@ export const VALIDATORS: Validators = { typeof value !== 'string' || value.trim().length === 0 ? `Must provide a valid license, e.g. "MIT"` : true, description: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a description` : true, + 'android-lang': (value) => + typeof value !== 'string' || value.trim().length === 0 ? `Must provide a language, e.g. "kotlin"` : true, dir: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a directory, e.g. "my-plugin"` diff --git a/src/prompt.ts b/src/prompt.ts index 8b49e86..57d205e 100644 --- a/src/prompt.ts +++ b/src/prompt.ts @@ -81,6 +81,15 @@ export const gatherDetails = (initialOptions: Options): Promise => message: `Enter a SPDX license identifier for your plugin.\n`, validate: VALIDATORS.license, }, + { + type: 'select', + name: 'android-lang', + message: `What language would you like to use for your Android plugin?\n`, + choices: [ + { title: 'Kotlin', value: 'kotlin' }, + { title: 'Java', value: 'java' } + ] + }, { type: 'text', name: 'description', diff --git a/src/template.ts b/src/template.ts index e675cb7..bfb6930 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,4 +1,4 @@ -import { readFile, rmdir, mkdir, writeFile, unlink } from 'fs/promises'; +import { readFile, rmdir, mkdir, writeFile, unlink, readdir, rm } from 'fs/promises'; import Mustache from 'mustache'; import { dirname, join, resolve, sep } from 'path'; import tar from 'tar'; @@ -25,6 +25,7 @@ export const extractTemplate = async ( ): Promise => { const templateFiles: string[] = []; const templateFolders: string[] = []; + const androidLang = details['android-lang'].toLowerCase(); await mkdir(dir, { recursive: true }); await tar.extract({ file: type === 'PLUGIN_TEMPLATE' ? TEMPLATE_PATH : WWW_TEMPLATE_PATH, @@ -41,14 +42,44 @@ export const extractTemplate = async ( }); await Promise.all(templateFiles.map((p) => resolve(dir, p)).map((p) => applyTemplate(p, details))); - await Promise.all(templateFolders.map((p) => resolve(dir, p)).map((p) => rmdir(p))); + await deleteUnnecessaryFolders(dir, androidLang); + await Promise.all(templateFolders.map((p) => resolve(dir, p)).map((p) => rm(p, { recursive: true }))); +}; + +const deleteUnnecessaryFolders = async (dir: string, androidLang: string): Promise => { + const androidFolder = join(dir, 'android', 'src', 'main'); + const javaFolder = join(androidFolder, 'java'); + const kotlinFolder = join(androidFolder, 'kotlin'); + + if (androidLang === 'kotlin' && await folderExists(javaFolder)) { + await rm(javaFolder, { recursive: true }); + } + + if (androidLang === 'java' && await folderExists(kotlinFolder)) { + await rm(kotlinFolder, { recursive: true }); + } +}; + +const folderExists = async (folderPath: string): Promise => { + try { + const files = await readdir(folderPath); + return files != null; + } catch (err) { + return false; + } }; export const applyTemplate = async ( p: string, - { name, 'package-id': packageId, 'class-name': className, repo, author, license, description }: OptionValues, + { name, 'package-id': packageId, 'class-name': className, repo, author, license, description, 'android-lang': androidLang }: OptionValues, ): Promise => { const template = await readFile(p, { encoding: 'utf8' }); + + const conditionalView = { + KOTLIN: androidLang.toLowerCase() === 'kotlin', // Set KOTLIN flag + // Add more flags... + } + const view = { CAPACITOR_VERSION: CAPACITOR_VERSION, PACKAGE_NAME: name, @@ -60,17 +91,21 @@ export const applyTemplate = async ( AUTHOR: author, LICENSE: license, DESCRIPTION: description, + ANDROID_LANG: androidLang, }; - const contents = Mustache.render(template, view); - const filePath = Object.entries(view).reduce( - (acc, [key, value]) => (value ? acc.replaceAll(`__${key}__`, value) : acc), - p.substring(0, p.length - MUSTACHE_EXTENSION.length), + const combinedView = { ...view, ...conditionalView }; + const intermediateContents = Mustache.render(template, combinedView); + const finalContents = Mustache.render(intermediateContents, view); + let filePath = p.substring(0, p.length - MUSTACHE_EXTENSION.length); + filePath = Object.entries(view).reduce( + (acc, [key, value]) => (value ? acc.replaceAll(`__${key}__`, value.toString()) : acc), + filePath, ); await mkdir(dirname(filePath), { recursive: true }); // take off the .mustache extension and write the file, then remove the template - await writeFile(filePath, contents, { encoding: 'utf8' }); + await writeFile(filePath, finalContents, { encoding: 'utf8' }); await unlink(p); }; From 86995f4c119ba047d21c943d886feac8326fcb0f Mon Sep 17 00:00:00 2001 From: Fabio Martino Date: Wed, 14 May 2025 23:43:46 +0200 Subject: [PATCH 02/10] Updated dependencies --- assets/plugin-template/package.json.mustache | 10 +++++----- src/template.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/plugin-template/package.json.mustache b/assets/plugin-template/package.json.mustache index 36ac2c5..dc7d5df 100644 --- a/assets/plugin-template/package.json.mustache +++ b/assets/plugin-template/package.json.mustache @@ -55,13 +55,13 @@ "@ionic/eslint-config": "^0.4.0", "@ionic/prettier-config": "^4.0.0", "@ionic/swiftlint-config": "^2.0.0", - "eslint": "^8.57.0", - "prettier": "^3.4.2", - "prettier-plugin-java": "^2.6.6", + "eslint": "^9.26.0", + "prettier": "^3.5.3", + "prettier-plugin-java": "^2.6.7", "rimraf": "^6.0.1", - "rollup": "^4.30.1", + "rollup": "^4.40.2", "swiftlint": "^2.0.0", - "typescript": "~4.1.5" + "typescript": "~5.4.5" }, "peerDependencies": { "@capacitor/core": ">={{{ CAPACITOR_VERSION }}}" diff --git a/src/template.ts b/src/template.ts index 981357d..1e98490 100644 --- a/src/template.ts +++ b/src/template.ts @@ -7,7 +7,7 @@ import type { OptionValues } from './options'; const MUSTACHE_EXTENSION = '.mustache'; -export const CAPACITOR_VERSION = '7.0.0'; +export const CAPACITOR_VERSION = '7.2.0'; const TEMPLATE_PATH = resolve(__dirname, '..', 'assets', 'plugin-template.tar.gz'); From 0ba96b21b7e9b7b982a5a21ec70fa3d298dd0f3c Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 12:05:52 +0000 Subject: [PATCH 03/10] fix(android): Update dependencies to same versions as Cap 8 --- assets/plugin-template/android/build.gradle.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/plugin-template/android/build.gradle.mustache b/assets/plugin-template/android/build.gradle.mustache index d84d743..16290b5 100644 --- a/assets/plugin-template/android/build.gradle.mustache +++ b/assets/plugin-template/android/build.gradle.mustache @@ -4,13 +4,13 @@ ext { androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0' androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0' {{ #KOTLIN }} - androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.15.0' + androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.17.0' {{ /KOTLIN }} } buildscript { {{ #KOTLIN }} - ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25' + ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20' {{ /KOTLIN }} repositories { google() From 7149ea3f05dfe345f3f6f04347f6a2f862c41a5c Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 12:09:41 +0000 Subject: [PATCH 04/10] chore(android): Set JVM 21 for Kotlin Since it's the recommended for Capacitor 8 References: https://capacitorjs.com/docs/updating/plugins/8-0#update-to-java-21-recommended --- assets/plugin-template/android/build.gradle.mustache | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assets/plugin-template/android/build.gradle.mustache b/assets/plugin-template/android/build.gradle.mustache index 16290b5..a2abf04 100644 --- a/assets/plugin-template/android/build.gradle.mustache +++ b/assets/plugin-template/android/build.gradle.mustache @@ -54,6 +54,12 @@ android { } } +{{ #KOTLIN }} +kotlin { + jvmToolchain(21) +} +{{ /KOTLIN }} + repositories { google() mavenCentral() From c85054c022f503d78f3dc02b59d7a5020e8d45ba Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 12:54:50 +0000 Subject: [PATCH 05/10] feat(android): Add kotlin version of test files And also support deleting them if the opposite language is selected. --- .../android/ExampleInstrumentedTest.kt | 26 +++++++++++++++++++ .../com/getcapacitor/ExampleUnitTest.kt | 18 +++++++++++++ src/template.ts | 21 +++++++++------ 3 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 assets/plugin-template/android/src/androidTest/kotlin/com/getcapacitor/android/ExampleInstrumentedTest.kt create mode 100644 assets/plugin-template/android/src/test/kotlin/com/getcapacitor/ExampleUnitTest.kt diff --git a/assets/plugin-template/android/src/androidTest/kotlin/com/getcapacitor/android/ExampleInstrumentedTest.kt b/assets/plugin-template/android/src/androidTest/kotlin/com/getcapacitor/android/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..8e8e3f0 --- /dev/null +++ b/assets/plugin-template/android/src/androidTest/kotlin/com/getcapacitor/android/ExampleInstrumentedTest.kt @@ -0,0 +1,26 @@ +package com.getcapacitor.android + +import android.content.Context +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + + @Test + @Throws(Exception::class) + fun useAppContext() { + // Context of the app under test. + val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext + + assertEquals("com.getcapacitor.android", appContext.packageName) + } +} diff --git a/assets/plugin-template/android/src/test/kotlin/com/getcapacitor/ExampleUnitTest.kt b/assets/plugin-template/android/src/test/kotlin/com/getcapacitor/ExampleUnitTest.kt new file mode 100644 index 0000000..ba1894e --- /dev/null +++ b/assets/plugin-template/android/src/test/kotlin/com/getcapacitor/ExampleUnitTest.kt @@ -0,0 +1,18 @@ +package com.getcapacitor + +import org.junit.Assert.assertEquals +import org.junit.Test + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +class ExampleUnitTest { + + @Test + @Throws(Exception::class) + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} diff --git a/src/template.ts b/src/template.ts index fdb19ec..9db186c 100644 --- a/src/template.ts +++ b/src/template.ts @@ -47,16 +47,21 @@ export const extractTemplate = async ( }; const deleteUnnecessaryFolders = async (dir: string, androidLang: string): Promise => { - const androidFolder = join(dir, 'android', 'src', 'main'); - const javaFolder = join(androidFolder, 'java'); - const kotlinFolder = join(androidFolder, 'kotlin'); + const androidSrcDir = join(dir, 'android', 'src'); + const sourceSets = ['main', 'test', 'androidTest']; - if (androidLang === 'kotlin' && await folderExists(javaFolder)) { - await rm(javaFolder, { recursive: true }); - } + for (const sourceSet of sourceSets) { + const sourceFolder = join(androidSrcDir, sourceSet); + const javaFolder = join(sourceFolder, 'java'); + const kotlinFolder = join(sourceFolder, 'kotlin'); + + if (androidLang === 'kotlin' && await folderExists(javaFolder)) { + await rm(javaFolder, { recursive: true }); + } - if (androidLang === 'java' && await folderExists(kotlinFolder)) { - await rm(kotlinFolder, { recursive: true }); + if (androidLang === 'java' && await folderExists(kotlinFolder)) { + await rm(kotlinFolder, { recursive: true }); + } } }; From 18c649127d2ecee75f9f48e35422d9e92226b924 Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 12:59:00 +0000 Subject: [PATCH 06/10] chore: document android-lang as either-or, instead of e.g. To make it clearer that there are only two options. --- README.md | 2 +- src/help.ts | 2 +- src/options.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1c966c8..dd029a1 100644 --- a/README.md +++ b/README.md @@ -30,5 +30,5 @@ As of the `0.8.0` release, example apps for testing are included when initializi --author ......... Author name and email (e.g. "Name ") --license ............ SPDX License ID (e.g. "MIT") --description ...... Short description of plugin features ---android-lang ..... Language for Android plugin development (e.g. "kotlin" or "java") +--android-lang ..... Language for Android plugin development (either "kotlin" or "java") ``` diff --git a/src/help.ts b/src/help.ts index dc0c53a..df38983 100644 --- a/src/help.ts +++ b/src/help.ts @@ -10,7 +10,7 @@ const help = ` --author ......... Author name and email (e.g. "Name ") --license ............ SPDX License ID (e.g. "MIT") --description ...... Short description of plugin features - --android-lang ............ Language for Android plugin development (e.g. "kotlin" or "java") + --android-lang ............ Language for Android plugin development (either "kotlin" or "java") -h, --help ................ Print help, then quit --verbose ................. Print verbose output to stderr diff --git a/src/options.ts b/src/options.ts index c56baec..804d8a6 100644 --- a/src/options.ts +++ b/src/options.ts @@ -59,7 +59,7 @@ export const VALIDATORS: Validators = { description: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a description` : true, 'android-lang': (value) => - typeof value !== 'string' || value.trim().length === 0 ? `Must provide a language, e.g. "kotlin"` : true, + typeof value !== 'string' || value.trim().length === 0 ? `Must provide a language, either "kotlin" or "java"` : true, dir: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a directory, e.g. "my-plugin"` From 749cc16dc98bb1a5423f914089515106ecfe4d23 Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 13:09:43 +0000 Subject: [PATCH 07/10] chore: fix lint issues --- src/options.ts | 4 +++- src/prompt.ts | 4 ++-- src/template.ts | 21 +++++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/options.ts b/src/options.ts index 804d8a6..6927408 100644 --- a/src/options.ts +++ b/src/options.ts @@ -59,7 +59,9 @@ export const VALIDATORS: Validators = { description: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a description` : true, 'android-lang': (value) => - typeof value !== 'string' || value.trim().length === 0 ? `Must provide a language, either "kotlin" or "java"` : true, + typeof value !== 'string' || value.trim().length === 0 + ? `Must provide a language, either "kotlin" or "java"` + : true, dir: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a directory, e.g. "my-plugin"` diff --git a/src/prompt.ts b/src/prompt.ts index 57d205e..76d601f 100644 --- a/src/prompt.ts +++ b/src/prompt.ts @@ -87,8 +87,8 @@ export const gatherDetails = (initialOptions: Options): Promise => message: `What language would you like to use for your Android plugin?\n`, choices: [ { title: 'Kotlin', value: 'kotlin' }, - { title: 'Java', value: 'java' } - ] + { title: 'Java', value: 'java' }, + ], }, { type: 'text', diff --git a/src/template.ts b/src/template.ts index 9db186c..ad07d62 100644 --- a/src/template.ts +++ b/src/template.ts @@ -1,4 +1,4 @@ -import { readFile, rmdir, mkdir, writeFile, unlink, readdir, rm } from 'fs/promises'; +import { readFile, mkdir, writeFile, unlink, readdir, rm } from 'fs/promises'; import Mustache from 'mustache'; import { dirname, join, resolve, sep } from 'path'; import { extract } from 'tar'; @@ -55,11 +55,11 @@ const deleteUnnecessaryFolders = async (dir: string, androidLang: string): Promi const javaFolder = join(sourceFolder, 'java'); const kotlinFolder = join(sourceFolder, 'kotlin'); - if (androidLang === 'kotlin' && await folderExists(javaFolder)) { + if (androidLang === 'kotlin' && (await folderExists(javaFolder))) { await rm(javaFolder, { recursive: true }); } - if (androidLang === 'java' && await folderExists(kotlinFolder)) { + if (androidLang === 'java' && (await folderExists(kotlinFolder))) { await rm(kotlinFolder, { recursive: true }); } } @@ -76,14 +76,23 @@ const folderExists = async (folderPath: string): Promise => { export const applyTemplate = async ( p: string, - { name, 'package-id': packageId, 'class-name': className, repo, author, license, description, 'android-lang': androidLang }: OptionValues, + { + name, + 'package-id': packageId, + 'class-name': className, + repo, + author, + license, + description, + 'android-lang': androidLang, + }: OptionValues, ): Promise => { const template = await readFile(p, { encoding: 'utf8' }); const conditionalView = { - KOTLIN: androidLang.toLowerCase() === 'kotlin', // Set KOTLIN flag + KOTLIN: androidLang.toLowerCase() === 'kotlin', // Set KOTLIN flag // Add more flags... - } + }; const view = { CAPACITOR_VERSION: CAPACITOR_VERSION, From 6987ba30ba5b223e248f655a5112e6b346c73698 Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 16:05:19 +0000 Subject: [PATCH 08/10] fix: Add android-lang as CLI option Otherwise --android-lang is ignored and user needs to prompt it specifically --- src/options.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/options.ts b/src/options.ts index 6927408..df1b41f 100644 --- a/src/options.ts +++ b/src/options.ts @@ -26,7 +26,16 @@ export type Validators = { const CLI_ARGS = ['dir'] as const; -const CLI_OPTIONS = ['name', 'package-id', 'class-name', 'repo', 'author', 'license', 'description'] as const; +const CLI_OPTIONS = [ + 'name', + 'package-id', + 'class-name', + 'repo', + 'author', + 'license', + 'description', + 'android-lang', +] as const; export const VALIDATORS: Validators = { name: (value) => From a5afa8be0d5c82a1dad64424229abdb81b554fb5 Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 16:08:54 +0000 Subject: [PATCH 09/10] chore: minor changes on android language validation --- src/options.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/options.ts b/src/options.ts index df1b41f..e15a25d 100644 --- a/src/options.ts +++ b/src/options.ts @@ -68,9 +68,9 @@ export const VALIDATORS: Validators = { description: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a description` : true, 'android-lang': (value) => - typeof value !== 'string' || value.trim().length === 0 - ? `Must provide a language, either "kotlin" or "java"` - : true, + typeof value === 'string' && value.trim().length > 0 && /^(kotlin|kt|java)$/i.test(value) + ? true + : `Must be either "kotlin" or "java"`, dir: (value) => typeof value !== 'string' || value.trim().length === 0 ? `Must provide a directory, e.g. "my-plugin"` From 116651d3f82f69682a6c76d25b7ee2449ef73a49 Mon Sep 17 00:00:00 2001 From: OS-pedrogustavobilro Date: Fri, 27 Feb 2026 16:17:02 +0000 Subject: [PATCH 10/10] chore(android): Kotlin option selected if not java Rather than using kotlin only if "kotlin" is returned --- src/template.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/template.ts b/src/template.ts index ad07d62..6446f8e 100644 --- a/src/template.ts +++ b/src/template.ts @@ -90,8 +90,7 @@ export const applyTemplate = async ( const template = await readFile(p, { encoding: 'utf8' }); const conditionalView = { - KOTLIN: androidLang.toLowerCase() === 'kotlin', // Set KOTLIN flag - // Add more flags... + KOTLIN: androidLang.toLowerCase() !== 'java', }; const view = {