Skip to content

Writing an Android application

Pierre Quentel edited this page Mar 5, 2017 · 41 revisions

With Brython you can write applications in Python that run in modern browsers, including most of smartphones browsers. But you can also write native Android applications : this page explains how to do it, taking the example of a basic geolocation application.

The first step is to install the latest version of Android Studio.

1. Initializing the application

Follow the instructions to create a new application in Android Studio. In this post, we suppose that you have entered :

application name  : NewBrythonApp
company domain : brython

For the Form factor : select Phone and Tablet, and the minimum SDK required (API 15 is ok).

In "Add an Activity to Mobile" select "Empty activity".

In "Customize the Activity" keep the default names and click "Finish".

Android Studio starts building the project and presents a window like this one :

The application files are stored in a directory shown in the title bar of the Android Studio window. In the rest of this page, you can edit the files either in Android Studio or in any text editor.

2. Customize settings

2.1 activity_main.xml

Edit the file activity_main.xml and replace its content by

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">
     tools:ignore="MergeRootFrame">
     
         <WebView
         android:id="@+id/activity_main_webview"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
</FrameLayout>

2.2 MainActivity.java

The content of this file may vary with the kind of application you want to use. The setting must at least allow the use of Javascript ; in the example below, geolocation is also enabled.

Keep the first line of the script (with the package name) and replace the rest with :

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.GeolocationPermissions;

public class MainActivity extends AppCompatActivity {

    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mWebView = (WebView) findViewById(R.id.activity_main_webview);

        WebSettings webSettings = mWebView.getSettings();

        // Enable Javascript
        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

        // Enable geolocation
        webSettings.setGeolocationEnabled(true);

        mWebView.setWebChromeClient(new WebChromeClient() {
            // always accept geolocation
            public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
                callback.invoke(origin, true, false);
            }
        });
        Context context = getApplicationContext();
        mWebView.getSettings().setGeolocationDatabasePath( context.getFilesDir().getPath() );
        mWebView.loadUrl("file:///android_asset/www/index.html");
    }

}

2.3 AndroidManifest.xml

Replace the content of the <manifest> tag by :

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="Brython Geolocation"
    android:supportsRtl="true"
    android:theme="@style/NoTitleBar">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

You can change the value of the android:label section : it is the name of the application on the Android smartphone when it will be installed.

2.4 styles.xml

The application uses a style, NoTitleBar, that must be defined in a file styles.xml, accessible by unfolding app/res/values. We add the theme by adding a new <style> tag :

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- Theme with no title. -->
    <style name="NoTitleBar" parent="Theme.AppCompat.NoActionBar">
    </style>

</resources>

3. Write a Brython application

Create a subdirectory assets/www in tha Android application directory. This is where we will store the Brython application. It includes at least index.html (the page loaded by the Android app) and brython.js, plus brython_stdlib.js if the application uses modules from the standard distribution and all the additional files (css, images, javascript...) needed by the application.

In this example, we only use brython.js and index.html holds a basic geolocation application :

<!doctype html>
<html>
<head>
<script type="text/javascript" src="brython.js"></script>
<style>
.rTable {
    display: table;
    width: 100%;
}
.rTableRow {
    display: table-row;
}
.rTableHead {
    display: table-cell;
    padding: 3px 10px;
    border: 0px
}

</style>
</head>
<body onload="brython()">

<script type="text/python">
from browser import document, window, html

map = document["map"]
    
def success(position):
    lat = position.coords.latitude
    long = position.coords.longitude
    
    # use Google Maps API to print a map
    url = "http://maps.googleapis.com/maps/api/staticmap"
    params = "markers=%f,%f&zoom=15&size=320x298&sensor=true" % (lat, long)
    mapurl = url + "?" + params
    
    map.clear()
    map <= html.IMG(src=mapurl)


def refresh(*args):
    # cf. https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
    window.navigator.geolocation.getCurrentPosition(success)

document["refresh"].bind("click", refresh)
refresh()
</script>

<div class="rTable">
  <div class="rTableRow">
    <div class="rTableHead">Current location</div>
    <div class="rTableHead" align="right"><button id="refresh">Refresh</button></div>
  </div>
</div>

<div id="map"></div>

</body>
</html>

4. Build the Android application (APK)

To generate the Android executable (a file with the extension .apk), select Build / Build APK in Android Studio. When the file is generated, use "Show in explorer" to open the file system explorer at the location of the APK file, which is called app-debug.apk.

5. Install the application on the smartphone

Connect the Android smartphone to the PC with a cable and choose a location for the APK file, for instance Download, preferably in Card if the smartphone has a memory card, otherwise in Phone. Use the file explorer to drag-and-drop app-debug.apk to this location.

Open the Applications window on the smartphone and select an application to explore the local files ; usually My Files is installed, otherwise download it from Google Play. With this application, navigate to the directory where app-debug.apk has been installed, and click on it.

You will get a message saying that the installation is blocked for security reasons ; select Parameters and check the "Unknown Sources" box. In the next page, select "Install", then "Open" to run the application.

The application is now featured in the Applications window, with the default Android icon, under the name "Brython Geolocation", the one we specified in section android:label of AndroidManifest.xml.