Running React, Angular.js, Ember.js, … Locally on Android
In this post, we’ll explore how you can run any JavaScript framework app — like React, Angular.js, or Ember.js — locally on an Android device. Using Ember.js as an example, we’ll discuss how to serve a statically built JS app with a lightweight local web server and run it in a WebView. You can check the full implementation on this GitHub repository.
Repository Overview
The GitHub repository contains the complete implementation of:
- An Ember.js app pre-built into static assets.
- A lightweight Android web server to serve those static files.
- A WebView configuration to load and run the Ember.js app locally on an Android device.
Feel free to clone the repo for hands-on experimentation.
git clone https://github.com/zfir-dev/ember-android.git
How It Works
Here’s the high-level workflow:
- The Ember.js app is built and stored in the Android app’s
assets/ember-dist
folder. - A lightweight web server, implemented in Java, serves these files locally.
- The WebView loads the app through the local server (
http://localhost:8080
).
Key Components
Ember.js App
The Ember.js app is pre-built using:
ember build --environment=production
The output is placed in the assets/ember-dist
folder of the Android project. These files include:
index.html
app.js
styles.css
- Other static assets.
The Ember.js app doesn’t require any external hosting since it is served locally on the device.
Web Server
The web server is implemented using NanoHTTPD, a lightweight HTTP server library. It serves the static assets from the assets
folder.
Here’s an overview of the WebServer
class, located in the WebServer.kt file:
Core Responsibilities:
- File Routing: Routes incoming HTTP requests to corresponding files in the
assets/ember-dist
directory. - Dynamic MIME Type Detection: Ensures proper file rendering by assigning the correct MIME type (e.g.,
text/html
,application/javascript
).
Serve:
@Override
public Response serve(IHTTPSession session) {
String uri = session.getUri().equals("/") ? "ember-dist/index.html" : "ember-dist/" + session.getUri();
try {
InputStream inputStream = context.getAssets().open(uri);
String mimeType = getMimeType(uri);
return newChunkedResponse(Response.Status.OK, mimeType, inputStream);
} catch (IOException e) {
return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "File Not Found");
}
}
This method:
- Handles HTTP requests and determines the file to serve.
- Uses
getMimeType(uri)
to assign appropriate MIME types (HTML, CSS, JS, etc.). - Returns the file content as a
Response
. If the file doesn’t exist, a 404 error response is returned.
MIME Type Detection:
private String getMimeType(String fileName) {
if (fileName.endsWith(".html")) return "text/html";
if (fileName.endsWith(".js")) return "application/javascript";
if (fileName.endsWith(".css")) return "text/css";
if (fileName.endsWith(".png")) return "image/png";
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) return "image/jpeg";
return "application/octet-stream";
}
This ensures the client (WebView) can correctly interpret and render the files.
WebView Configuration
The WebView is configured in the MainActivity.kt file. It connects the Ember.js app served by the local web server to the Android app.
Key Configuration:
- Enable JavaScript: Allows the WebView to execute JavaScript.
- Local Server URL: Loads the app from
http://localhost:8080
. - Optimizations: Settings like
domStorageEnabled
anduseWideViewPort
ensure smooth performance.
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://localhost:8080/");
This simple configuration is sufficient to load and display the Ember.js app locally.
Getting Started
To try it out:
- Clone the repository:
git clone https://github.com/zfir-dev/ember-android.git
- Open the project in Android Studio.
- Build and run the app on an Android emulator or device.
The Ember.js app will load in the WebView, served locally from http://localhost:8080
.
Advantages of This Setup
- Framework-Agnostic: Works with any JavaScript framework (React, Angular.js, Vue.js, etc.).
- Offline Capability: No internet is required to run the app.
- Performance: Static assets load instantly from the device.
Conclusion
This approach demonstrates how you can run a completely offline JS framework-based app on an Android device using a local web server and WebView. In this example, I am using Ember.js but this also works for React, Angular and other JS frameworks. For more details and the full code, check out the repository: github.com/zfir-dev/ember-android. Happy coding!