Seamlessly Convert Web Apps to Android App: Automate with Capacitor and GitHub Actions

Narottam04 - May 23 '23 - - Dev Community

What I built

I have developed a GitHub action that allows you to transform a web app, written in any javascript framework, into a production-ready Android app that is prepared for deployment on the Play Store.

It makes use of Ionic's Capacitor, which allows for the integration of native functionality into your web application and simplifies the packaging of your web app as native apps.

Category Submission:

DIY Deployments:
By automating the conversion of websites into Android apps and generating necessary files for testing, the project streamlines the deployment process for open source projects or personal projects, enabling developers to easily deploy their websites as production Android apps to play store.

App Link

Github Repository(Action): https://github.com/Narottam04/action-capacitor-android

Example Web App Converted to Android App:

Web App: https://pokecards.pages.dev/

Android App Release: https://github.com/Narottam04/PokeCards/releases/tag/2023-05-23-17_45_41%2B0000

Screenshots

action marketplace

github action

Demo of web app converted to android app using github actions

The app is created using eleventy js(11ty) and converted to android app using action-capacitor-android. Download the app from github release mentioned above in app link.

Description

action-capacitor-android offers a streamlined solution for converting your web apps into production Android apps. With custom GitHub action, developers can automate the conversion process, generating signed .aab file for deployment to play store and .apk files for testing. This automation simplifies the deployment workflow for open source projects or personal projects that would like to have a native app for their web apps, empowering developers to effortlessly transform their web apps into fully functional Android apps, accelerating their deployment process and developer experience.

Link to Source Code

Github Repository(Action): https://github.com/Narottam04/action-capacitor-android

Github actions marketplace:
https://github.com/marketplace/actions/capacitor-android-action

Permissive License

MIT

Background

I wrote an article last year on how to use Ionic Capacitor to transform any web project into an Android app. The story has received a lot of attention on DEV, with 12,389 views, 320 reactions, and 57 comments thus far.

Here is the link to the article: Convert Your Website into an Android App using Capacitor

In addition, I created an app with Capacitor that has over 2,000+ downloads on the Play Store. Given the app's popularity, I decided it was time to fix some bugs and improve the application UX for the users. However, the process of updating the app has been time-consuming, forcing me to run ten different CLI commands and wait for Android Studio to launch on my slow potato laptop😭😭. This entire process takes an additional 10 to 20 minutes of my work just to get a 5MB build.

While there are third-party services that provide automated builds, they are not free. As a developer working on side projects, I found the cost unjustified. As a result, I decided to create this GitHub action to improve my present workflow and enable faster distribution of updates to my users.

How I built it

Instructions to use this github action is in repository README file

Following the hackathon announcement, I immediately dived into the documentation and developed a basic action that simply echoes a few lines. Following that, I referred to the Capacitor documentation and began creating the action.

Let's go through the code and explore each section:

name: Build Android
run-name: Creating Production Ready Android App 🚀
on:
  push:
    branches:
      - master

Enter fullscreen mode Exit fullscreen mode
  • The name field specifies the name of the GitHub Actions workflow.
  • The run-name field provides a description or title for the workflow.
  • The on section defines the trigger for the workflow. In this case, the workflow will be triggered when there is a push event to the master branch.
jobs:
  build:
    name: Build APK
    runs-on: ubuntu-latest
    # TODO: add the default directory - COMMENT IF IT'S NOT IN SUBFOLDER
    # defaults:
    #   run:
    #     working-directory: ./frontend
    steps:

Enter fullscreen mode Exit fullscreen mode
  • The jobs section specifies the tasks to be executed as part of the workflow. In this case, there is a single job named "Build APK."
  • The runs-on field specifies the operating system environment where the job will run. In this case, it is set to ubuntu-latest, indicating that the job will run on a Linux-based environment.
  • The steps section contains a list of individual steps or tasks that will be executed within the job.

The subsequent steps perform various actions required to build the Android app:

steps:
      - name: Checkout source
        uses: actions/checkout@v3
        # TODO: add your branch to checkout
        with:
          ref: master

      - name: Setup java
        uses: actions/setup-java@v3
        with:
          distribution: "zulu"
          java-version: "11"

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 19.x

      - name: install dependencies
        run: npm ci

      - name: Create Build Folder
        run: npm run build

      - name: Add android folder if not present
        run: if [ ! -d "./android" ]; then npx cap add android; fi

      - name: Capacitor update
        run: npx cap update

      - name: Capacitor copy
        run: npx cap copy

      # TODO: Check for folder structure in README for generating splash screen 
      - name: Generate icons and splash screen to android folder 
        run:  if [ -d "./resources" ]; then npm install @capacitor/assets --save-dev && npx capacitor-assets generate --android; fi

      - name: Build app bundle
        run: cd android && ./gradlew bundle && ./gradlew assembleDebug

      - name: Extract Android signing key from env
        run: |
          echo "${{ secrets.RELEASE_KEYSTORE }}" > android/release.jks.base64
          base64 -d android/release.jks.base64 > android/release.decrypted.jks

      - name: Sign dev build
        run: jarsigner -keystore android/release.decrypted.jks -storepass "${{ secrets.RELEASE_KEYSTORE_PASSWORD }}" -signedjar ./android/app/build/outputs/bundle/release/app-release-signed.aab ./android/app/build/outputs/bundle/release/app-release.aab release

      - name: Check folder content of android output
        run: ls ./android/app/build/outputs/bundle/release

      - name: Set Tag
        id: current-datetime
        run: echo "CURRENT_DATETIME=$(date +'%Y-%m-%d-%H_%M_%S%z')" >> "$GITHUB_OUTPUT"

      - name: Build Release
        shell: bash
        run: |
          hub release create ${{ steps.current-datetime.outputs.CURRENT_DATETIME }} \
          -m ${{ steps.current-datetime.outputs.CURRENT_DATETIME }} \
          -a ./android/app/build/outputs/bundle/release/app-release-signed.aab \
          -a ./android/app/build/outputs/apk/debug/app-debug.apk
        env:
          GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
Enter fullscreen mode Exit fullscreen mode
  1. Checkout source: This step checks out the source code repository using the actions/checkout GitHub Actions action.
  2. Setup java: This step sets up the Java environment using the actions/setup-java GitHub Actions action. It installs the Zulu distribution of Java 11.
  3. Setup Node.js: This step sets up the Node.js environment using the actions/setup-node GitHub Actions action. It installs Node.js version 19.x.
  4. Install dependencies: This step installs the project dependencies using npm ci, which ensures a clean installation based on the package-lock.json file.
  5. Create Build Folder: This step runs the command npm run build to create the build folder for the project.
  6. Add android folder if not present: This step checks if the android folder exists in the project. If it doesn't, it adds the Android platform using npx cap add android.
  7. Capacitor update: This step updates the Capacitor configuration and dependencies using npx cap update.
  8. Capacitor copy: This step copies the web app files into the native project using npx cap copy.
  9. Generate icons and splash screen to android folder: This step checks if the resources folder exists in the project. If it does, it installs the @capacitor/assets package as a development dependency and generates the icons and splash screen for the Android platform using npx capacitor-assets generate --android.
  10. Build app bundle: This step navigates to the android directory and runs the Gradle tasks bundle and assembleDebug using ./gradlew. These tasks generate the app bundle and debug APK.
  11. Extract Android signing key from env: This step takes the value of the RELEASE_KEYSTORE secret, which is assumed to be base64-encoded, and decodes it to obtain the signing key file (release.jks). The key file is saved as android/release.decrypted.jks.
  12. Sign dev build: Sign the debug build of the app using the provided keystore and password in github actions secrets.
  13. Check folder content of android output: List the contents of the output directory to verify the presence of the signed app bundle.
  14. Set Tag: Set the current date and time as a tag for the release.
  15. Build Release: Create a GitHub release with the tag name and message, including the signed app bundle and debug APK as release assets.

Additional Resources/Info

. . . . . . . . . . . . . . . .