How to Build a Signed APK from a Capacitor Project Without Android Studio (2026)
If you have a Capacitor project that already contains an android/ folder, you do not need Android Studio to ship it. Build your web assets and run npx cap sync androidlocally — both need only Node.js — then upload the project (ZIP or Git repo) to a cloud compile service. The service runs the Gradle build you can't run, signs the output with your release keystore, and hands back an APK for sideloading plus an AAB for Google Play.
This guide covers the full path for Capacitor specifically: which half of the build you still do locally, which half moves to the cloud, how signing works, and where the honest alternatives (a local Android Studio setup, GitHub Actions, Ionic Appflow) actually beat this approach.
The real problem: every Capacitor app is two projects stapled together
A Capacitor app is a web project (Vite, Angular CLI, whatever) plus a completely ordinary Android Gradle project living in android/. The two halves have wildly different toolchain demands, and that asymmetry is the whole story.
The web half is easy. npm run build compiles your app into dist/, and npx cap sync android copies those assets into android/app/src/main/assets/public and wires each installed plugin into the Gradle files. Any machine with Node.js can do this.
Then you hit the other half, and the machine that just built your web app perfectly greets you with this:
Fixing that means installing the Android SDK, a matching JDK, and accepting a pile of licenses — in practice, installing Android Studio. And the versions are a moving target. As of mid-2026, a Capacitor 7 android/ folder expects Java 21 with compile/target SDK 35, while Capacitor 8 raises the floor again to SDK 36, AGP 8.13 and Gradle wrapper 8.14.x — effectively a current Android Studio install. Meanwhile a project scaffolded in the Capacitor 5 era assumes JDK 17 and an older AGP. Set up your machine for one and the other breaks. This treadmill is exactly why npx cap migrate exists.
Capacitor does ship a CLI escape hatch — npx cap build android with --keystorepath / --androidreleasetype flags — but it still requires the full local SDK underneath, its signing defaults to the older jarsigner tool, and the issue tracker has long-running reports (ionic-team/capacitor #7366, #7054) of the apksigner path producing an unsigned APK while claiming success. It automates the last step of a working local setup; it does not replace the setup.
The vendor CI option is closing: Ionic announced in February 2025 that Appflow — the official cloud build service for Capacitor — is no longer sold to new customers, with existing access ending December 31, 2027. If you searched for this article because Appflow is off the table, that instinct is correct.
What actually happens when you upload a Capacitor project
The honest division of labor: you keep the Node half, we take the Gradle half. You run your web build and cap sync locally, so the synced assets and plugin wiring are already inside android/ when you upload. Here is what the pipeline then does, mechanically:
- Detects the project shape. A
capacitor.config.tsorcapacitor.config.jsonplus anandroid/folder routes you to the Gradle pipeline. No YAML to write. - Era-matches the toolchain.The workspace image is selected to fit your project's Gradle/AGP generation — JDK 17 for a Capacitor 5/6-era project, Java 21 and newer SDKs for Capacitor 7/8. Your three-year-old client project compiles without you downgrading anything.
- Auto-repairs the common walls. A missing
gradlewwrapper (surprisingly often gitignored) is synthesized; AGP and Kotlin get bumped to a floor the image can actually run; and if an older plugin triggers AGP 8's “Namespace not specified” failure because it still declares its package only in the manifest, the namespace is filled in from that manifest. - Builds and signs. The default command is
./gradlew assembleReleasein yourandroid/project. The output is signed with your uploaded release keystore — stored encrypted and reused for that project, so version 2 installs cleanly over version 1 — or with a keystore we generate for you. You get both an APK and an AAB. - Deletes your source. The workspace is ephemeral; the source tree is removed after the build. If the build fails, the credit is refunded automatically.
If your project needs something non-default — a product flavor, a nonstandard module layout — drop a code2native.json in the repo root:
Step-by-step: Capacitor project to signed APK/AAB
Build your web assets
npm ci && npm run build. Make sure the output folder matches webDir in your Capacitor config (usually dist or www).
Run npx cap sync android
This copies the built assets into the native project and updates plugin Gradle wiring. It needs only Node — no SDK, no Studio. If you've never added the platform, run npx cap add android first.
Zip the project root, or connect the Git repo
Include android/ with the synced assets. Exclude node_modules/, android/.gradle/ and android/app/build/ — they only slow the upload.
Create a Source Code Build project
In Code2Native, choose Source Code Build, upload the ZIP or point at the repo, and select Android as the target.
Attach your release keystore (or generate one)
Upload your existing .jkswith its alias and passwords if the app is already on Google Play — updates must be signed with the same key. New app? Let the platform generate a keystore; it's kept encrypted and reused for every later build of this project.
Build, then download APK + AAB
Sideload the APK onto a device to verify, upload the AAB to Google Play. If the build goes red, the log shows the exact Gradle command and error, and the credit comes back automatically.
Cloud compile vs the honest alternatives
Competitor details below are accurate to the best of our knowledge as of mid-2026 — verify current terms before committing.
| Path | What you set up & maintain | Cost | The catch |
|---|---|---|---|
| Local Android Studio | Studio + SDK + JDK matched to your Capacitor major; re-matched on every upgrade | Free (plus disk, plus time) | Best for daily native-plugin development; overkill if you just need release binaries |
| GitHub Actions | Workflow YAML, keystore as base64 secrets, signing steps you write and debug yourself | Free for public repos; minutes metered on private | Genuinely great if you already live in CI — that first working signing step takes an afternoon |
| Ionic Appflow | Vendor dashboard, polished Capacitor-native pipeline, live updates | Not sold to new customers | Winding down — existing customers keep access until Dec 31, 2027; no new signups |
| Code2Native source build | Nothing local beyond Node; upload or connect repo, keystore stored encrypted | First build free; $29/mo for 10 builds | Android-focused; iOS from source is an unsigned .ipa you re-sign yourself (Pro tier) |
One concession worth spelling out: if your team already has a working GitHub Actions pipeline with signing configured, keep it. A cloud compile service earns its fee when the toolchain is the obstacle — an aging project, a machine without the SDK, an agency juggling projects on three different Capacitor majors — not when your CI is already green. The same pipeline handles Flutter projects and plain Gradle apps, which matters if your project mix is wider than Capacitor.
When NOT to use this
- Your app is React Native or Expo. Different pipeline entirely — on our platform, React Native and Expo source builds are waitlist-only right now, not a live build path.
- Your Ionic project has no android/ folder. An Ionic app on legacy Cordova (no Capacitor android platform) is also waitlist territory. If it is Capacitor underneath, you're one
npx cap add androidaway from being buildable. - You're actively writing a custom native plugin. Iterating on Kotlin/Java code needs a local emulator, breakpoints, and instant rebuilds. Install Android Studio for development; use cloud builds for releases.
- You don't have a Capacitor project at all. If what you actually have is a deployed website, wrapping it is a simpler, cheaper path than adopting Capacitor first. And if you're still deciding whether Capacitor is the right architecture, start with our Capacitor vs native comparison.
FAQ
Do I need to run npx cap sync before uploading?
Yes. The cloud pipeline compiles your android/Gradle project as-is, so the web assets must already be synced into it. The good news: sync needs only Node.js, so this step works on any machine — the Android SDK is only required for the Gradle half, which is the half you're handing off.
My project fails locally with “SDK location not found” — will it build in the cloud?
Almost certainly, because that error is about your machine, not your code: Gradle can't find an Android SDK via ANDROID_HOME or local.properties. The cloud workspace has the SDK preinstalled and writes its own local.properties. Real code errors — a plugin that doesn't compile, a bad Gradle script — will still fail, with the full log to show you why, and a failed build refunds its credit.
Why not just use npx cap build android?
If you have a fully working local SDK, you can — it drives Gradle and signs in one command. But it requires that local setup to exist, defaults to legacy jarsigner signing, and has open issues where the apksigner mode reports success while emitting an unsigned APK. It automates the last mile of a configured machine. The cloud path exists for when there is no configured machine.
Do I need an APK or an AAB for Google Play?
Google Play has required the AAB format for new apps since August 2021; the APK is what you sideload onto devices for testing and direct distribution. A Capacitor build here returns both from the same compile, signed with the same key, so you don't have to choose in advance.
Is Ionic Appflow still an option for Capacitor cloud builds?
Only if you're already a customer. Ionic announced in February 2025 that new sales of Appflow are discontinued, and existing customers keep access through December 31, 2027 while the product winds down. As of mid-2026 you cannot sign up, which is why Capacitor teams are re-evaluating their build setup now rather than at the deadline.
What happens to my source code and keystore after the build?
The build runs in an ephemeral workspace and your source tree is deleted when it finishes — we compile it, we don't keep it. Your keystore is different: it's stored encrypted and reused for that project so every subsequent build is signed with the same key, which is what makes clean Play Store updates possible.
Your android/ folder is already build-ready
Run npm run build && npx cap sync android, zip the project, and get a signed APK + AAB back. The first build is free — if the toolchain matrix can't get your project green, you've spent nothing and keep the full build log either way.
Code2Native Engineering
Engineering team
Written by the Code2Native engineering team — the people who build and operate the cloud build pipeline.