Android App Builder

Today's project should be quick (3.5 hours). As I have been working on it for a bit in the past two days. The project is an online Android app builder. It takes a URL, download that web page, and build an apk file using Cordova. I wrote an app called Elastic Doc. It's basically the same idea, albeit taking more work for crawling the whole document web site to make it available for offline view.

But for this demo, our app will only download one web page that is the URL. Let's get started.

I used Docker for building the apk. The Dockerfile looks like this:

FROM beevelop/cordova:latest

RUN cordova telemetry off
ENV CI=1
ENV ANDROID_SDK=/opt/android

RUN cordova prepare android
RUN yes | /opt/android/tools/bin/sdkmanager "platforms;android-27"

RUN mkdir -p /home/app
WORKDIR /home/app
CMD cordova build android --release

Running the build requires more than 1 GB of RAM, so I upped my VM to 2GB.

I also build a simple Python Flask web server to display and serve the generated apk files:

from flask import Flask, request, send_file
import urllib2
from subprocess import call

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def home():
    if request.method == "GET":
        return '''
        <html>
        <head><title>Android App Builder</title></head>
        <body>
        <h1>Build an Android APK by entering an URL below</h1>
        <p>An apk file will be available for download</p>
        <form action="/" method="post">
        URL:<br>
        <input type="text" name="u" value="https://www.google.com">
        <input type="submit" value="Build!">
        </form>

        <br>
        Sample App Here: <a href="/google_search">google</a>
        </body>
        </html>
        '''
    elif request.method == "POST":
        try:
            url = request.form.get("u")
            r = urllib2.urlopen(url)
            text = r.read()
            with open("/tmp/app-template/www/res/index.html", "wt") as f:
                f.write(text)
            call(["cordova", "build", "android"])
            send_file("/tmp/app-template/platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk")
        except Exception, e:
            return str(e)

if __name__ == '__main__':
    app.run(host="0.0.0.0")

Update the Dockerfile to start the web server:

FROM beevelop/cordova:latest

RUN cordova telemetry off
ENV CI=1
ENV ANDROID_SDK=/opt/android

ADD app-template /tmp/app-template
WORKDIR /tmp/app-template
RUN cordova prepare android
RUN yes | /opt/android/tools/bin/sdkmanager "platforms;android-27"

RUN apt-get update && apt-get install -y python python-pip
RUN pip install flask

RUN cordova build android

ADD app.py /tmp/app.py
ADD google.apk /tmp/google.apk

CMD python /tmp/app.py

Run the container with docker run --rm -p 5000:5000 dohsimpson/android-builder.

Visit here: http://android-builder.enting.org. (UPDATED: 2018-06-14)

Screen-Shot-2018-03-24-at-1.39.08-PM

Don't forget to add .apk to the downloaded file.

You can run the apk file in your Chrome browser following this instruction. Or alternatively, run it on your Android phone by connecting via USB and run adb install XXX.apk.

Example: baidu.apk

Screen-Shot-2018-03-24-at-1.46.26-PM

Note that the image is missing because the html file uses relative url for the image instead of absolute url. All the links are clickable.

Not bad!