Create native Android App from Web site/PWA
Native mobile Apps give us a lot of magnificent opportunities compared to the pure web site or PWA: with native apps users can allow to share data with messengers and other apps, get access to a contacts list, use a device accelerometer, and permanently share their location. All these and many more features are very limited or missed on the web or PWA because of strict security considerations.
Moreover, native apps could be published to Android's Google Play Store or Apple's App Sore where users can share their reviews and feedback which in the case of qualitative apps is a great benefit to marketing efforts.
After years in web development, I still knew about Mobile application development nothing. But I’ve faced with huge amount of cases when clients wanted to implement some features that are available for native apps but could not be implemented to PWA or web browsers.
Some time ago we started to implement these cases with a Flutter app. We created a “Wrapper application” which allowed us to get native App features using WebView native-to-javascript bridge. This approach gave good results, but there was one small but necessary thing - using Flutter required some minimal knowledge of Dart language and we always spent extra time to write every permission and sensor handling from scratch.
But then we figured out the Open-Source and commercial-friendly framework with a ton of pre-made native modules already exists in this world. And this is CapacitorJS. Yes, also there is an old-school Cordova, but according to our benchmarks, it is slow and consumes more RAM.
In this post I will give you simple guide how to create CapacitorJS app on top of existing Nuxt web app.
Our final aim is - to create an AAB/APK file from our website. Let’s go on!
Step 1. Create your web app (or you can generate AAB/APK files for existing site, but just for example I will create a new project.
npx nuxi@latest init <project-namne>
cd <project-name>
npm install
Step 2. Generate entry index.html file. For this step we should disable SSR mode in nuxt.config to get SPA version of our project. To simplify process of generating file change nuxt generate script in package.json
:
{
"scripts": {
// ... "generate":"NUXT_TO_NATIVE_APP='true' nuxt generate" }}
And add condition to nuxt.config.ts
:
export default defineNuxtConfig({
devtools: { enabled: true },
ssr: process.env.NUXT_TO_NATIVE_APP == 'true' ? false : true,
})
Then execute
npm run generate
Check out .dist directory , it should contain index.html file which is ready for deployment. We will return to it later.
Step 3.Install Capacitor
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Nuxt project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
By this point, you should be able to observe new ios and android folders in your Nuxt 3 project.
Add default directory which included our index.html file (result of the executing "generate" command) at capacitor.config.json:
{
"appId": "com.example.app",
"appName": "TestApp",
"webDir": "dist"
}
Now we are ready launch our native App. Update nuxt files ( if we have some changing ) :
npm run generate
And synchronize native app code with web app code :
npx cap sync
Step 4. Prepare for build.
Install openjdk:
sudo apt install -y openjdk-18-jdksudo apt install -y openjdk-18-jre
Add path to env:
export JAVA_HOME=/path/to/openjdk-18
First of all we have to generate keystore. Navigate to android directory of our web project and execute command:
keytool -genkey -v -keystore <name>.keystore -alias <name> -keyalg RSA -keysize 2048 -validity 10000
In my case it was something like this :
keytool -genkey -v -keystore test.keystore -alias test -keyalg RSA -keysize 2048 -validity 10000
You will get <name>.keystore file in android directory.
During generating of key you should enter key password, please remember it , we'll use it in build configurations.
Now we will add buildOptions to capacitor.config.json
:
{
...
"webDir": "dist",
"android": {
"allowMixedContent": true,
"buildOptions": {
"keystorePath": "<name>.keystore",
"keystoreAlias": "<name>",
"keystorePassword": "<password>",
"releaseType": "APK",
"signingType": "apksigner"
}
}
}
sudo apt update && sudo apt install android-sdk
And add sdk-manager
. Since Ubuntu 22 (Jammy), you can simply install it via :
sudo apt install sdkmanager
Add variables to env:
export ANDROID_HOME=/path/to/sdk
export PATH=$PATH:ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools
Pass to sdk depends on your OS , in my case it is "/usr/lib/android-sdk".
Now we have to accept all licenses.
Add permissions to write into directory of licenses:
sudo chmod -R a+w /usr/lib/android-sdk/licenses/
And add licenses:
sdkmanager --licenses
Add permissions to write into directories for packages:
sudo chmod -R a+w /usr/lib/android-sdk/
Install the packages:
sdkmanager "platforms;android-33"
sdkmanager "build-tools;30.0.3"
Run build:
npx cap build android --keystorepath test.keystore --keystorepass testpassword --keystorealias test --keystorealiaspass testpassword --androidreleasetype APK
That's all . After this step you get APK file.