Skip to content

Commit 9861597

Browse files
feat: Option to Select Language (Kotlin or Java) for Android Plugins (#122)
* (feat) Add Kotlin/Java selectable choice * Updated dependencies * fix(android): Update dependencies to same versions as Cap 8 * 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 * feat(android): Add kotlin version of test files And also support deleting them if the opposite language is selected. * chore: document android-lang as either-or, instead of e.g. To make it clearer that there are only two options. * chore: fix lint issues * fix: Add android-lang as CLI option Otherwise --android-lang is ignored and user needs to prompt it specifically * chore: minor changes on android language validation * chore(android): Kotlin option selected if not java Rather than using kotlin only if "kotlin" is returned --------- Co-authored-by: OS-pedrogustavobilro <pedro.gustavo.bilro@outsystems.com>
1 parent ccdcb82 commit 9861597

11 files changed

Lines changed: 195 additions & 9 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ As of the `0.8.0` release, example apps for testing are included when initializi
3030
--author <author> ......... Author name and email (e.g. "Name <name@example.com>")
3131
--license <id> ............ SPDX License ID (e.g. "MIT")
3232
--description <text> ...... Short description of plugin features
33+
--android-lang <text> ..... Language for Android plugin development (either "kotlin" or "java")
3334
```

assets/plugin-template/README.md.mustache

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,21 @@
44

55
## Install
66

7+
To use npm
8+
79
```bash
810
npm install {{{ PACKAGE_NAME }}}
11+
````
12+
13+
To use yarn
14+
15+
```bash
16+
yarn add {{{ PACKAGE_NAME }}}
17+
```
18+
19+
Sync native files
20+
21+
```bash
922
npx cap sync
1023
```
1124

assets/plugin-template/android/build.gradle.mustache

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,31 @@ ext {
33
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
44
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
55
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
6+
{{ #KOTLIN }}
7+
androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.17.0'
8+
{{ /KOTLIN }}
69
}
710

811
buildscript {
12+
{{ #KOTLIN }}
13+
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20'
14+
{{ /KOTLIN }}
915
repositories {
1016
google()
1117
mavenCentral()
1218
}
1319
dependencies {
1420
classpath 'com.android.tools.build:gradle:8.13.0'
21+
{{ #KOTLIN }}
22+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
23+
{{ /KOTLIN }}
1524
}
1625
}
1726

1827
apply plugin: 'com.android.library'
28+
{{ #KOTLIN }}
29+
apply plugin: 'kotlin-android'
30+
{{ /KOTLIN }}
1931

2032
android {
2133
namespace = "{{ PACKAGE_ID }}"
@@ -42,6 +54,12 @@ android {
4254
}
4355
}
4456

57+
{{ #KOTLIN }}
58+
kotlin {
59+
jvmToolchain(21)
60+
}
61+
{{ /KOTLIN }}
62+
4563
repositories {
4664
google()
4765
mavenCentral()
@@ -52,6 +70,9 @@ dependencies {
5270
implementation fileTree(dir: 'libs', include: ['*.jar'])
5371
implementation project(':capacitor-android')
5472
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
73+
{{ #KOTLIN }}
74+
implementation "androidx.core:core-ktx:$androidxCoreKTXVersion"
75+
{{ /KOTLIN }}
5576
testImplementation "junit:junit:$junitVersion"
5677
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
5778
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.getcapacitor.android
2+
3+
import android.content.Context
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
import androidx.test.platform.app.InstrumentationRegistry
6+
import org.junit.Assert.assertEquals
7+
import org.junit.Test
8+
import org.junit.runner.RunWith
9+
10+
/**
11+
* Instrumented test, which will execute on an Android device.
12+
*
13+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
14+
*/
15+
@RunWith(AndroidJUnit4::class)
16+
class ExampleInstrumentedTest {
17+
18+
@Test
19+
@Throws(Exception::class)
20+
fun useAppContext() {
21+
// Context of the app under test.
22+
val appContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
23+
24+
assertEquals("com.getcapacitor.android", appContext.packageName)
25+
}
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package {{ PACKAGE_ID }}
2+
3+
import android.util.Log
4+
5+
class {{ CLASS }} {
6+
7+
fun echo(value: String?): String? {
8+
Log.i("Echo", value ?: "null")
9+
10+
return value
11+
}
12+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package {{ PACKAGE_ID }}
2+
3+
import com.getcapacitor.JSObject
4+
import com.getcapacitor.Plugin
5+
import com.getcapacitor.PluginCall
6+
import com.getcapacitor.annotation.CapacitorPlugin
7+
import com.getcapacitor.PluginMethod
8+
9+
@CapacitorPlugin(name = "{{ CLASS }}")
10+
class {{ CLASS }}Plugin : Plugin() {
11+
12+
private val implementation = {{ CLASS }}()
13+
14+
@PluginMethod
15+
fun echo(call: PluginCall) {
16+
val value = call.getString("value")
17+
18+
val ret = JSObject().apply {
19+
put("value", implementation.echo(value))
20+
}
21+
call.resolve(ret)
22+
}
23+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.getcapacitor
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Test
5+
6+
/**
7+
* Example local unit test, which will execute on the development machine (host).
8+
*
9+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
10+
*/
11+
class ExampleUnitTest {
12+
13+
@Test
14+
@Throws(Exception::class)
15+
fun addition_isCorrect() {
16+
assertEquals(4, 2 + 2)
17+
}
18+
}

src/help.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const help = `
1010
--author <author> ......... Author name and email (e.g. "Name <name@example.com>")
1111
--license <id> ............ SPDX License ID (e.g. "MIT")
1212
--description <text> ...... Short description of plugin features
13+
--android-lang ............ Language for Android plugin development (either "kotlin" or "java")
1314
1415
-h, --help ................ Print help, then quit
1516
--verbose ................. Print verbose output to stderr

src/options.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface OptionValues {
1717
author: string;
1818
license: string;
1919
description: string;
20+
'android-lang': string;
2021
}
2122

2223
export type Validators = {
@@ -25,7 +26,16 @@ export type Validators = {
2526

2627
const CLI_ARGS = ['dir'] as const;
2728

28-
const CLI_OPTIONS = ['name', 'package-id', 'class-name', 'repo', 'author', 'license', 'description'] as const;
29+
const CLI_OPTIONS = [
30+
'name',
31+
'package-id',
32+
'class-name',
33+
'repo',
34+
'author',
35+
'license',
36+
'description',
37+
'android-lang',
38+
] as const;
2939

3040
export const VALIDATORS: Validators = {
3141
name: (value) =>
@@ -57,6 +67,10 @@ export const VALIDATORS: Validators = {
5767
typeof value !== 'string' || value.trim().length === 0 ? `Must provide a valid license, e.g. "MIT"` : true,
5868
description: (value) =>
5969
typeof value !== 'string' || value.trim().length === 0 ? `Must provide a description` : true,
70+
'android-lang': (value) =>
71+
typeof value === 'string' && value.trim().length > 0 && /^(kotlin|kt|java)$/i.test(value)
72+
? true
73+
: `Must be either "kotlin" or "java"`,
6074
dir: (value) =>
6175
typeof value !== 'string' || value.trim().length === 0
6276
? `Must provide a directory, e.g. "my-plugin"`

src/prompt.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ export const gatherDetails = (initialOptions: Options): Promise<OptionValues> =>
8181
message: `Enter a SPDX license identifier for your plugin.\n`,
8282
validate: VALIDATORS.license,
8383
},
84+
{
85+
type: 'select',
86+
name: 'android-lang',
87+
message: `What language would you like to use for your Android plugin?\n`,
88+
choices: [
89+
{ title: 'Kotlin', value: 'kotlin' },
90+
{ title: 'Java', value: 'java' },
91+
],
92+
},
8493
{
8594
type: 'text',
8695
name: 'description',

0 commit comments

Comments
 (0)