Seamlessly Convert Web Apps to Android App: Automate with Capacitor and GitHub Actions
Tags: githubhack23, githubactions, javascript, ionic
Published: 2023-05-23 18:53:10

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqc54fu5f2owawbhkup7.png)


![github action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbjrfyddhgimzzlhgs8r.png)

**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.

{% vimeo 829679530 %}

### 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](https://dev.to/narottam04/convert-your-website-into-an-android-app-using-capacitor--5bh2)


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:

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

```

- 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.

```yaml
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:

```

- 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:

```yaml
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 }}
```

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

- [Action Docs](https://docs.github.com/en/actions)
- [Capcitor Docs](https://capacitorjs.com/)
- [Cryptocademy Android App, Created by me using React and Capcitor](https://play.google.com/store/apps/details?id=com.cryptocademy.android)