Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 AS base

ARG ANDROID_PLATFORM=36
ARG ANDROID_PLATFORM=37
ARG ANDROID_BUILD_TOOLS=36.0.0
ARG CMDLINE_TOOLS_VERSION=11076708
ARG NODE_VERSION=24
ARG JAVA_VERSION=27
ARG JAVA_VERSION=26

ENV JAVA_HOME=/opt/java/openjdk

Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

"features": {
"ghcr.io/nordcominc/devcontainer-features/android-sdk:1": {
"platform": "36",
"platform": "37",
"build_tools": "36.0.0"
},
"ghcr.io/devcontainers/features/node:2.1": {
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
uses: actions/setup-java@v6
with:
distribution: temurin
java-version: '27'
java-version: '26'

- name: Run unit tests
run: npm run test
Expand Down Expand Up @@ -199,15 +199,15 @@ jobs:
- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: '27'
java-version: '26'
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci --no-audit --no-fund
- name: Install Android SDK packages
run: sdkmanager 'platforms;android-36' 'build-tools;36.0.0'
run: sdkmanager 'platforms;android-37' 'build-tools;36.0.0'
- name: Select package
run: npm pkg set name=${{ matrix.package }}
- name: Build APK
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
uses: actions/setup-java@v6
with:
distribution: temurin
java-version: "27"
java-version: "26"
cache: ${{ (!(inputs.is_PR && inputs.PR_NUMBER) && github.ref == 'refs/heads/main' && 'gradle') || '' }}

- name: Setup Node
Expand Down
12 changes: 5 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ If you prefer not to use Docker at all:
|------------|---------|
| **Node.js** | 24 LTS |
| **npm** | Included with Node.js |
| **Java JDK** | 27 (Eclipse Temurin) |
| **Android SDK** | API 36 |
| **Java JDK** | 26 (any vendor) |
| **Android SDK** | API 37 |
| **Gradle** | 9.8.0-rc-3 (included wrapper) |

### Environment Setup
Expand All @@ -102,9 +102,9 @@ export ANDROID_HOME="$HOME/Android/Sdk"
export PATH="$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin"
```

Set `JAVA_HOME` to your Eclipse Temurin JDK 27 installation and add `$JAVA_HOME/bin` to `PATH`. The checked-in daemon criteria require Temurin 27, and the Gradle wrapper downloads the required Gradle version automatically. Android Gradle Plugin 9.4.1 supplies built-in Kotlin support.
Set `JAVA_HOME` to any JDK 26 installation and add `$JAVA_HOME/bin` to `PATH`. The checked-in daemon criteria require Java 26 (any vendor), and the Gradle wrapper downloads the required Gradle version automatically. Android Gradle Plugin 9.4.1 supplies built-in Kotlin support.

Java 27 support currently requires [Gradle 9.8](https://docs.gradle.org/9.8.0-rc-3/release-notes.html), whose latest release is RC3 as of 2026-09-23. Gradle 9.7.1 is the latest stable release but does not support Java 27. The wrapper pins and verifies the RC3 distribution. Java and Kotlin still emit Java 17 bytecode for Android compatibility; the build itself runs on Java 27.
The wrapper pins and verifies the Gradle 9.8.0-rc-3 distribution. Java and Kotlin still emit Java 21 bytecode for Android compatibility; the build itself runs on Java 26.

### Build Steps

Expand Down Expand Up @@ -342,7 +342,7 @@ their file URIs; parsing them as URL text loses literal filename characters.
- `src/native`: typed native APIs imported by `src/native/index.ts`; `bridge(service)` binds promise-based actions to the shared transport.
- `src/platforms/android` and `src/platforms/ios`: platform transports using the shared callback and binary protocol.
- `platforms/ios`: iOS app, with the template's runtime in `runner` and native services in `runner/lib`. Simulator tests and native dependencies remain alongside the app. See the [port checklist](docs/ios-port.md) for remaining work.
- `platforms/android/app/src/main/assets/services.json`: native service registration.
- `platforms/android/app/src/main/java/com/foxdebug/acode/runtime/ServiceRegistry.kt`: native service registration, extended by the `free`/`paid` and `store`/`fdroid` source sets.
- `package.json`: app ID (`name`), version and Android version code.

The native APIs are available through `Bridge.exec`, `Bridge.file`, `Bridge.http`, `Bridge.clipboard` and `Bridge.websocket`. App source uses these APIs or ordinary imports. For existing third-party plugins, `src/native/pluginCompatibility.js` exposes the legacy `cordova` namespace and module names for the public native APIs, forwarding to the same implementations. Existing direct globals and `deviceready`, pause/resume and hardware-button events remain available. Keep compatibility aliases in that file; do not use them inside Acode or add Cordova dependencies. Advertising and billing APIs retain their build-edition restrictions.
Expand Down Expand Up @@ -386,8 +386,6 @@ The familiar APK/AAB paths remain available under `platforms/android/app/build/o

`node dev/storage_manager.mjs y` or `n` toggles all-files access in the tracked Android manifest for the next build. Build scripts read package identity without rewriting it or reinstalling plugins.

See [the migration verification record](docs/native-migration.md) for behavior coverage and remaining device checks.

## 🔧 Troubleshooting

### Missing local dependency
Expand Down
41 changes: 14 additions & 27 deletions dev/scripts/android.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (require.main === module) {
const args = process.argv.slice(2);
const options = parseOptions(args);
if (args.includes("test")) {
runGradle(`test${capitalize(options.variant)}DebugUnitTest`, options);
runGradle(`test${capitalize(variantFlavor(options))}DebugUnitTest`);
} else {
const artifact = build(options);
if (args.includes("run")) launch(options, artifact);
Expand All @@ -30,7 +30,7 @@ function parseOptions(args) {
return {
...getAppConfig(),
mode: args.some((arg) => ["p", "prod"].includes(arg)) ? "p" : "d",
fdroid: args.includes("fdroid"),
channel: args.includes("fdroid") ? "fdroid" : "store",
bundle: args.includes("bundle"),
skipWeb: args.includes("--skip-web"),
target: args.find((arg) => arg.startsWith("--target="))?.slice(9),
Expand All @@ -50,28 +50,19 @@ function build(options) {
"--mode",
options.mode === "p" ? "production" : "development",
],
{ ACODE_PLATFORM: "android", ACODE_FDROID: String(options.fdroid) },
{ ACODE_PLATFORM: "android", ACODE_FDROID: String(options.channel === "fdroid") },
);
}
const type = options.mode === "p" ? "release" : "debug";
const task = `${options.bundle ? "bundle" : "assemble"}${capitalize(options.variant)}${capitalize(type)}`;
runGradle(task, options);
const flavor = variantFlavor(options);
const task = `${options.bundle ? "bundle" : "assemble"}${capitalize(flavor)}${capitalize(type)}`;
runGradle(task);
const outputs = path.join(root, "platforms/android/app/build/outputs");
const extension = options.bundle ? "aab" : "apk";
const file = `app-${options.variant}-${options.channel}-${type}.${extension}`;
let source = options.bundle
? path.join(
outputs,
"bundle",
options.variant + capitalize(type),
`app-${options.variant}-${type}.${extension}`,
)
: path.join(
outputs,
"apk",
options.variant,
type,
`app-${options.variant}-${type}.${extension}`,
);
? path.join(outputs, "bundle", flavor + capitalize(type), file)
: path.join(outputs, "apk", flavor, type, file);
const unsigned = !options.bundle && !fs.existsSync(source);
if (unsigned) source = source.replace(/\.apk$/, "-unsigned.apk");
const destination = path.join(
Expand Down Expand Up @@ -112,15 +103,11 @@ function gradle() {
process.platform === "win32" ? "gradlew.bat" : "gradlew",
);
}
function runGradle(task, options) {
run(gradle(), [
"-p",
"platforms/android",
`:app:${task}`,
`-Pfdroid=${options.fdroid}`,
`-PnodeExecutable=${process.execPath}`,
"--console=plain",
]);
function runGradle(task) {
run(gradle(), ["-p", "platforms/android", `:app:${task}`, "--console=plain"]);
}
function variantFlavor(options) {
return options.variant + capitalize(options.channel);
}
function capitalize(value) {
return value[0].toUpperCase() + value.slice(1);
Expand Down
4 changes: 2 additions & 2 deletions dev/scripts/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ async function launchApp(target, platform, emulator) {
"run",
"--skip-web",
];
if (currentOptions.fdroid) args.push("fdroid");
if (currentOptions.channel === "fdroid") args.push("fdroid");
if (currentOptions.device) args.push("--device");
if (target) args.push(`--target=${target}`);
if (emulator && platform === "android") args.push("--emulator");
Expand All @@ -267,7 +267,7 @@ function startRspackWatch(host, port, proto, onCompiled) {
const env = buildSpawnEnv({
DEV_MODE: "true",
ACODE_PLATFORM: currentOptions.platform,
ACODE_FDROID: String(!!currentOptions.fdroid),
ACODE_FDROID: String(currentOptions.channel === "fdroid"),
DEV_HOST: host,
DEV_PORT: String(port),
DEV_PROTO: proto,
Expand Down
4 changes: 4 additions & 0 deletions platforms/android/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Always use kotlin for writing new code
- Avoid java
- Always add keep rules in proguard file for add @Keep annotation if a file must be preserved
- always write idiomatic android/kotlin code never take shortcuts
98 changes: 0 additions & 98 deletions platforms/android/app/build.gradle

This file was deleted.

Loading
Loading