Skip to content

Remote live edit and HTTP deployment of Python applications on Android

License

Notifications You must be signed in to change notification settings

miohtama/webkivy

Repository files navigation

Webkivy: Remote live edit of Python applications on Android

Webkivy is a tool for running Python applications on an Android mobile over web. It is intended for quick prototyping, sharing your Python scripts with friends and learning Python development.

Live edit of source code is supported. Changed source code files are automatically copied to a mobile from any HTTP source. You do not need to copy new application files to your phone by hand - it's enough to hit Run button again and again. This web like development model makes it possible to prototype fast. Furthermore no development tools need to be installed lowering the barrier of entry for mobile application development.

The project is based on Kivy mobile application development framework. Using Python programming language makes dynamic compiling and execution possible, something that's difficult with Android's default statically typed Java toolchain.

screenshots/main.png

  • Run a Python application from a given URL link. Sharing your application with your friends is as easy as linking to its source code in web.
  • "Just bunch of files" (JBOF) deployment model: use wi-fi, shared hosting, Apache, Amazon S3, gist.github.com, pasteboard or anything that serves HTTP to deploy your application.
  • Live editing and reload of source code.
  • Access to native Android Java APIs: sensors, Bluetooth, NFC, OpenGL, sound, others.
  • Developer friendly Python exception handling with exception dialogs: no need to dig Android logs to see Python tracebacks.
  • No additional tools required: write your code on a web editor or your favorite text editor.

This tutorial link is preloaded to the application when you run it first time.

Webkivy asks you for an URL from where to load your Python script.

  • The URL can be a link to a single .py file
  • The URL can be a link to a folder with an index.html file. This way multiple .py files and other application resources like images and sounds can be loaded.
  • The URL must contain a fragment part telling the entry point. The entry point defines which Python module and function to call after the loading is complete.
  • The URL may contain links to subfolders. These subfolders are also crawled and considered a Python submodule paths. Subfolders must come with their __init__.py file. Subfolder links must end with an ending slash (/) that is a default behavior of Python's simple HTTP server.

An example URL of running a Python application off from gist.github.com. This will load kivyhello.py from gist.github.com and run function main():

https://gist.githubusercontent.com/miohtama/80391980c2e73b285cfe/raw/dd89a55497ba33a6014453d9bb7432ab424c01cf/kivyhello.py#main

An example URL of running a Python application from static web hosting with index.html support. This will crawl all files in the target, start simplekivy.py from run() functoin:

http://bit.ly/webkivytest#simplekivy:run

The entry point function return a Kivy screen object. Usually entry point is a module level function run(). After entry point is called the Android application switches over to screen by given the entry point.

Write Python code online and execute in a phone through Webkivy.

  • Assume you have created a Python file myscript.py based on the example.

  • Make sure your phone and your computer are in same wi-fi network

  • Figure out the internal IP address of your computer. Use the network manager of your operating system or following Python command:

    python -c "import socket ; print socket.gethostbyname(socket.gethostname())"
    
  • Go to a folder where you have myscripy.py and start a Python built-in web server:

    python -m SimpleHTTPServer
    
  • Enter URL to your computer. Replace 999.999.999.999 with your IP address

    http://999.999.999.999:8000/#myscript.py:run

  • Hit Run

The Python entry point function is given in the URL fragment. It must return a Kivy screen object. Usually entry point is a module level function run(). After entry point is called the Kivy UI switches over to screen by given the entry point.

Example run entry point from http://localhost:8000#simplykivy:run:

from kivy.uix.screenmanager import Screen

class HelloWorldScreen(Screen):

    def quit(self):
        # Bind this to your app UI if you want to return Webkivy main screen
        app = kivy.app.App.get_running_app()
        landing_screen = app.reset_landing_screen()
        self.manager.switch_to(landing_screen)

    def run():
        return HelloWorldScreen()

By default all exceptions in Kivy main event loop are shown in a dialog:

screenshots/exception.png

If you have code that may raise exception outside Kivy main loop you can decorate it with webkivy.exception.catch_gracefully to get an error dialog. Otherwise you need to dig exception traceback from adb logs:

from webkivy.exceptions catch_gracefully

import android


class MyScreen:

    def on_enter(self):
      android.activity.bind(on_new_intent=self.on_new_intent)

    @catch_gracefully()
    def on_new_intent(self, intent):

        action = intent.getAction()
        # Exception raised where here...

Webkivy doesn't know about proper Python packaging (eggs, wheels, setup.py, etc.). However you can just symlink or copy related Python modules to your application as a subfolder. Subfolders are also crawled.

Alternatively you can rebuild Webkivy APK with libraries you need in buildozer.spec

All loaded Python files are put to the top level namespace. Absolute and relative imports should work between them. Thus, relative imports do not work on the top level of the application. If you want to use relative imports on your top level, just nest your deployed Python files in a dummy directory with __init__.py.

The Python interpreter is Python 2.7. This will be upgraded as soon as Buildozer toolchain supports Python 3.

Default libraries include

  • Kivy
  • pyOpenSSL
  • requests
  • lxml
  • pyjnius
  • pygame
  • futures

For the default available Android permissions see buildozer.spec. Please let me know if you wish any updates on these.

Android logs to a subsystem which is often referred as "adb logs". You will need to be able to read these lgos when a native Java API crash occurs. This is common when using Android APIs through pyjnius. Python cannot trap these errors and cannot display inline tracebacks for them.

The easiest way to view these logs is to

screenshots/logs.png

To build Webkivy APK you need to use Buildozer virtual machine image (Linux).

Make sure your phone is in developer mode. Connect your phone. Expose your phone to the VM by clicking the USB icon in the lower right corner of Virtualbox. Make sure you have high quality USB cable.

Build debug APK:

buildozer android debug

Make sure VM sees your connected Android phone:

/home/kivy/.buildozer/android/platform/android-sdk-20/platform-tools/adb devices

Deploying on a local Android phone using Buildozer (VM):

buildozer android debug deploy run

For the first deployment it will ask permission on phone screen. Accept it and rerun the command.

When your application crashes you can view adb logs:

/home/kivy/.buildozer/android/platform/android-sdk-20/platform-tools/adb logcat

So start a Google Play release on Buildozer:

# Make unsigned release
buildozer android release

# Copy APK over to host OS osing Virtualbox shared folder
cp bin/Webkivy-*-release-unsigned.apk /mnt/code

Then on the host:

# Create release key
keytool -genkey -v -keystore ./Dropbox/android-keys/androidkey.keystore -alias androidkey -keyalg RSA -keysize 2048 -validity 10000

# Sign release
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/Dropbox/android-keys/androidkey.keystore ~/code/Webkivy-0.3-release-unsigned.apk androidkey

# ZIP alignment
~/Library/Android/sdk/build-tools/23.0.2/zipalign -v 4 ~/code/Webkivy-0.3-release-unsigned.apk ~/code/Webkivy-0.3.apk

Upload to Google Play developer console.

If

  • Your local computer doesn't have publicly exposed IP address
  • Your WLAN devices cannot to connect each other due to enterprise wireless firewalling

You can use ngrok to build a publicly exposed HTTP tunnel from Internet to your computer. Example how to expose Python http server running in port 8000:

ngrok http 8000 -subdomain=myhorseapp

And then you can access your site at myhorseapp.ngrok.io.

For S3 deployment one needs to generate index.html directory listing files as Amazon doesn't do it for you.

Webkivy supplies a simple Bash script which can do index generation for you. Here is an example how to get directories prepared to for S3 upload and then upload them using Amazon aws tool.

Drop generate-index.bash``somewhere. First generate ``index.html files:

# Run downloaded bash script
~/code/generate-index.bash

Generated /Users/mikko/code/example.com/android/index.html
Generated /Users/mikko/code/example.com/android/desfire/index.html

Then sync them to Amazon S3:

aws s3 sync . s3://example.com

You get functioning import and autocompletion in your editor when you install pyjnius native modules.

Example:

git clone git@github.com:kivy/pyjnius.git
find /Applications|grep -i "jni.h"
# Oracly y u so fun
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h .
/Applications/Kivy2.app/Contents/Resources/


/Applications/Kivy2.app/Contents/Resources/venv/bin/python setup.py develop

JNI headers installation on OSX.

Please note that the project is not a proper Python package, but a Kivy application.

Setup package in development mode:

kivy -m pip install -e ".[dev, test]"

Running Kivy application locally:

kivy -m webkivy.main

Go to test_data folder and there start a web server kivy -m http.server 8866. Then you can use URL http://localhost:8866/#simplekivy:main for local Kivy app testing.

Run tests:

kivy -m pytest tests

Run a single test:

kivy -m pytest -k test_load_simple_module tests

To discuss contact via IRC channel:

  • Server: irc.freenode.net
  • Port: 6667, 6697 (SSL only)
  • Channel: #kivy

For bugs and issues open an issue at Github.

Mikko Ohtamaa (blog, Facebook, Twitter)

About

Remote live edit and HTTP deployment of Python applications on Android

Resources

License

Stars

Watchers

Forks

Packages

No packages published