Software development for mobile devices has long been associated with a strict division into camps: Java and Kotlin for Android, Swift and Objective-C for iOS. However, with the rise of the web and JavaScript, this monolith was broken. Today, web developers can create full-fledged native applications using a familiar technology stack, without diving deep into the specifics of mobile platforms. This opens up enormous opportunities for rapid prototyping and cross-platform development.

Creating an Android app with JavaScript has become available thanks to the emergence of powerful frameworks and bridges that connect browser code with native device APIs. Instead of learning the complex class hierarchies of the Android SDK, you can write logic in JS and layout in HTML and CSS. In this article, we'll look at the main approaches, tools, and pitfalls you'll encounter when moving from web to mobile development.

You don't have to be an expert in mobile architecture to get started. Enough knowledge ECMAScript 6+, an understanding of how the DOM works and the basic principles of asynchronous programming. The tools we'll look at take care of all the hard work of compiling and interacting with the operating system, leaving you creative freedom in writing code.

Choice of technology: from WebView to completely native code

The first decision you have to make is choosing an application architecture. There are two main directions: using web view (WebView) and compiling into native components. In the first case, your application is essentially a website wrapped in an Android application wrapper. This is the simplest way, but it can suffer from performance issues with complex animations.

The second approach, which is implemented by giants like React Native or Weex, is that JavaScript code controls native Android widgets. Buttons, lists and input fields are rendered by the system itself, and not by the browser engine. This gives almost native performance and the feel of a โ€œnativeโ€ interface, but requires a deeper understanding of the specifics of each framework.

  • ๐Ÿš€ Cordova / PhoneGap: A classic solution where the entire application runs inside a WebView. Ideal for simple data applications and prototypes.
  • โš›๏ธ React Native: Allows you to write in JS, but renders native components. Requires knowledge of React, but provides excellent performance.
  • ๐Ÿ”ฅ Ionic + Capacitor: A modern evolution of Cordova with support for current web standards and the ability to use Angular, Vue or React.

โš ๏ธ Attention: If your application requires complex graphics processing, heavy real-time computing, or the use of specific sensors with minimal latency, pure JavaScript in WebView may not provide the required speed. In such cases, part of the code will have to be written in Java/Kotlin or use native modules.

For beginners who want to quickly get results, the combination Ionic and Capacitor looks the most attractive. It allows you to take advantage of modern web capabilities such as Service Workers and PWAs and easily port them to mobile platforms. At the same time, you get access to native functions through a single JavaScript API, which greatly simplifies development.

๐Ÿ“Š What development experience do you have?
Only HTML/CSS/JS
I know React or Vue
Wrote in Java/Kotlin
Complete beginner

Setting up the environment and installing tools

Before writing the first line of code, you need to prepare the working environment. Unlike pure web development, where a text editor and a browser are enough, building Android applications requires installing additional software. This is a critical stage, errors at which can block the entire process of further work.

You will definitely need Node.js to manage packages and execute build scripts. In addition, to compile the project into an APK file you will need Android Studio or at least a set of command line Android SDK and JDK (Java Development Kit). Without environment variables pointing to the path to the SDK, the builder will not be able to find the necessary platform libraries.

โ˜‘๏ธ Preparing the workplace

Done: 0 / 5

After installing the basic software, you should select and initialize a specific framework. For example, for Ionic, a process looks like executing a command in the terminal. You choose a project template, front-end technology (React, Vue, Angular) and get a ready-made folder structure. It is important to make sure that the paths to the tools are written correctly, otherwise commands like ionic build or npm run android will produce errors about missing dependencies.

๐Ÿ’ก

Use version managers nvm (for Node.js) and sdkmanager (for Android) to easily switch between software versions. This will save you when old projects no longer build on new versions of the tools.

Checking the functionality of the environment is carried out by connecting a real device or launching an emulator. Team adb devices should display a list of connected devices. If the list is empty, check whether USB debugging is enabled in the developer options on your smartphone. Without this step, you will not be able to test the application in real time.

Project architecture and file structure

Understanding the project structure is the key to successful development. In a typical Android JavaScript project, you'll see a split between a web part and a native part. The web part contains your HTML, CSS and JS code that will be executed inside the application. The native part contains Android configuration files, manifests and resources (icons, splash screen).

The central element of the configuration is the file config.xml (in Cordova/Capacitor) or package.json with build settings. The access rights that the application requests from the system are written here. For example, access to the camera, geolocation or contacts must be explicitly declared, otherwise the Android OS will block the corresponding functions at the kernel level.

Folder/File Purpose Importance for a JS developer
src/ or www/ Application source code (HTML, JS, CSS) High: you write 90% of the code here
android/ Native Android project (Gradle, Java/Kotlin) Medium: touch only when adding native plugins
resources/ Application icons and screensavers Medium: requires preparation of graphics of different sizes
plugins/ Installed API access plugins High: managing device functionality

Particular attention should be paid to the file AndroidManifest.xml, which is generated automatically, but may require manual editing for specific settings. For example, if you want the application to work in landscape mode or not close when you rotate the screen, changes are made here. However, modern frameworks allow you to set many of these parameters via JSON configuration, avoiding direct XML editing.

โš ๏ธ Attention: Never edit files in the folder platforms/android or plugins directly if you are using CLI tools. The next time you build or add a plugin, all your changes will be overwritten by the generator. Place all settings in the root configs of the project.

Access to device functions through plugins

The main advantage of creating an application, and not just a website, is access to the hardware. JavaScript in the browser has limited access to the system, but in the Android app wrapper you can use the camera, Bluetooth, file system and accelerometer. This is implemented through a system of plugins that act as a bridge between JS and the native code of the platform.

Installation of a plugin usually occurs through one command in the terminal. Once installed, your code has new objects or methods that can be called asynchronously. For example, to work with a camera, you import a module and call the method Camera.getPhoto(). The framework itself processes the permission request from the user and returns the result in Promise format.

import { Camera, CameraResultType } from '@capacitor/camera';

const takePicture = async () => {

const image = await Camera.getPhoto({

quality: 90,

allowEditing: true,

resultType: CameraResultType.Uri

});

// image.webPath contains the path to the file

};

There are plugins for almost any scenario: from scanning QR codes to working with fingerprints. However, it is worth remembering that each additional plugin increases the size of the final APK file. An excessive number of unused libraries can slow down the application startup. Therefore, connect only those modules that are really necessary for the functionality of your product.

What to do if there is no ready-made plugin?

If the required functionality is not in the plugin store, you will have to write your own native module in Java or Kotlin. This requires knowledge of the Android SDK, but allows you to implement any, even the most exotic, logic, and then call it from JavaScript.

Working with the file system requires special care. In modern versions of Android (starting from 10 and higher), the rules for accessing files (Scoped Storage) have become more stringent. Old methods of direct path access may no longer work. Use specialized plugins such as Filesystem from Capacitor, which abstract these complexities and provide a secure API for reading and writing data.

Optimizing performance and interface

Portring the web interface to a mobile device often reveals performance issues. What works quickly in Chrome on a powerful PC may be slow on a budget smartphone. The main reason is the rendering of heavy DOM trees and complex CSS animations that are executed on the main thread. To create a native feel, you need to optimize each stage of rendering.

Use hardware acceleration for animations. CSS properties such as transform and opacityare processed by the GPU and do not cause layout reflow. Avoid animating properties width, height, top or leftas this forces the processor to recalculate the page geometry on each frame, which leads to interface friezes.

  • ๐Ÿ“‰ List virtualization: If you are displaying a long list of data (news feed, chat), do not render all the elements at once. Use virtual scroll components that create in the DOM only those elements that are currently visible to the user.
  • ๐Ÿ–ผ๏ธ Image optimization: Do not load original photos from the camera. Compress images before display and use modern formats like WebP, which are supported on Android.
  • โšก Lazy Loading: Break the application into modules and load page code only when the user navigates to them. This will speed up the initial start of the application.

The size of fonts and controls is also critical. On a desktop, the mouse finger is precise, and the user's finger on the phone screen has a contact area of โ€‹โ€‹about 7-10 mm. Buttons should be large enough (minimum 48x48 deep), and interactive elements should be clearly visible. Ignoring Material Design guidelines can make the application inconvenient, even if it is technically sound.

๐Ÿ’ก

The performance of a JS app on Android directly depends on the complexity of the DOM tree. The fewer nodes you create, the smoother the interface will be, especially on older devices.

Building, signing and publishing the application

The final stage is turning the source code into an installation file. To distribute via Google Play, you will need to generate a signed release APK or, more relevant now, an Android App Bundle (.aab). The build process is started by a CLI command that calls Gradle, the Android build system. At this point, the code is minified, resources are compressed, and the application is signed with a cryptographic key.

Signing an application is a matter of security and identification of the developer. You must create Keystore (key storage) and securely store the password for it. Losing this key means that you will never be able to update your app in the store, as Google Play requires all updates to be signed with the same key as the original version.

โš ๏ธ Attention: Never commit keystore files (.jks or .keystore) or push them to public Git repositories. If attackers obtain your key, they will be able to sign malicious updates on your behalf, and users will receive them as a legitimate update to your application.

After successful assembly, the file appears in the folder build/outputs. Before uploading to the Google Play Developer Console, you need to test your app on different devices and Android versions. Please note the target API version requirements (targetSdkVersion): Google regularly raises the minimum threshold, and apps targeting older versions of Android may be rejected by moderation.

๐Ÿ’ก

Use the Bundletool to test your .aab file locally before uploading it to the store. It allows you to emulate the installation process and check whether separate resources work correctly for different screen densities and languages.

The publication process includes filling out an application card, uploading screenshots, describing and undergoing moderation. Google Play moderators carefully check applications for compliance with policies, including work with personal data. Make sure your privacy policy is available here and clearly describes what data the app collects and why.

Is it possible to update the app's JS code without re-releasing it in the store?

Yes, this is possible thanks to Code Push technologies (for example, AppCenter Code Push or our own solutions). You can upload new bundles of JavaScript code to the server, and the application will download and apply the updates when launched. However, this only works for changes to JS, CSS and HTML. Changes to native plugins or manifest settings require a full release through Google Play.

Do I need to pay for an Android developer account?

Yes, publishing apps on Google Play requires a one-time registration fee of $25. After payment you get access to the developer console indefinitely. This distinguishes the Android platform from iOS, where the subscription is paid annually.

What is the minimum version of Android supported?

This depends on your project settings and the plugins used. By default, many frameworks target Android 5.1 (API 22) or higher. However, Google Play requires that new apps target current versions of Android (usually a version released within the last year), although you can select the minimum version (minSdkVersion) below to cover older devices.

Is it difficult to add ads to a JS app?

No, it's quite easy. There are ready-made plugins for popular advertising networks (AdMob, Unity Ads). You install the plugin, specify your ad IDs in the code or config, and advertising banners or videos are integrated into the interface. The main thing is to follow the rules for advertising so as not to get banned from the advertising network.