2013年7月8日月曜日

Python で Androidアプリをセルフ開発 ( sl4a と、AIDE を 使って Pythonスクリプトをスマホ上で独立Androidアプリに変換)

最近、Pythonを使う機会が増えた。スクリプト言語だから、ちょっと思いついたプログラムを簡単に書いておくのに便利。しかも、ちゃんとしたクラス定義のできるオブジェクト指向言語なので、そこそこの規模のアプリケーションを作ることもできる。
更には、こんなことしたいな~と思って検索すれば、大抵はPythonのライブラリが見つかってメデタシメデタシとなる。
しかも、Windows、Macintosh、Linuxなど、さまざまなOSに移植されていて、一度書いたスクリプトが、あっちでもこっちでも便利に使いまわせる。
もちろん、Android上にも移植されていて(Qpython)、たいていのスクリプトはそのまま動く。
自分がパソコン上で書いたプログラムを自分のスマホで走らせて満足しているうちは、これでメデタシ。でも、やっぱり、せっかく作ったプログラム、便利だよと言って友達に使わせてあげたい。とはいえ、友達はプログラムなんて興味ないから「スクリプトを実行する環境をインストールして、コードファイルを適当なディレクトリにコピーして……」なんて説明しても理解してもらえるはずもない。
あるいは、自分用に便利ツールを作ったつもりだったけど、このあたりの情報を見てたら、アプリにして一山当てたくなるかもしれない。(笑)
そんなとき、超えなくてはいけないハードルは大きく二つ。
  1. Androidに対応したGUIを準備する
  2. Pythonスクリプトと実行環境を一つのアプリとしてパックする
これがsl4aとAIDEを使えば意外と簡単に、しかも、全てAndroid上で完結させることができるのだ。ちなみに、手持ちの GALAXY S3 と Kindle Fire HD 8.9 の両方で試してみたが、全く問題なく実行できた。携帯電話や電子書籍リーダー単体でお手軽アプリ開発環境ができてしまうというわけだ。

さて、それでは、はじめにGUI環境のほうを片付けよう。
PC上でPythonスクリプトを書く場合、tkやQT、WxWidgetsなどのGUI環境が使えるが、残念ながらAndroid上にこれらは移植されていない。しかし、Android上のスクリプト実行環境sl4aでは、WebKit(つまりWebブラウザの中身)が使える。ここに、HTMLやCSSを使ってGUIを構成すればいい。HTMLとPythonの間のデータの受け渡しはJavascriptを使う。
まず、手順を追って行こう。
sl4aを準備しよう。sl4aとは、以前このブログで少しふれたことがあるaseの最新版で、Scripting Layer for Android をUNIXコマンド風に省略した名前。forを4、toを2などと書くのはUNIX界の古い習慣だ。Android上で各種スクリプト言語を走らせるためのプラットフォームで、これにより、sl4a上で走る各種スクリプトから、Android本体のカメラや電話、SMSなどの機能にアクセスすることができるようになる。sl4a上ではPythonをはじめ、PerlやLua、beanshellなどのスクリプトが使える。また、Javascript環境のRhinoも使えるようなのでHTML&Javascriptだけでカメラや電話の機能を使うアプリも作れるわけだ。
話を少し戻そう。sl4aをインストールするには“https://code.google.com/p/android-scripting/”からapkを直接ダウンロードしてインストールする。Google Play や、amazon apps 以外からアプリをインストールしたくないという人はここで挫折するしかないわけだが、そんなことは気にしないという自己責任感の強い人たちは先に進もう。
https://code.google.com/p/android-scripting/downloads/list”からsl4a_r?.apkというファイルの最新版をインストールすればいい。執筆時点の最新はsl4a_r6.apk 。
続けて、この上で動作するPython環境もインストールしよう。執筆時点の最新版はこれ、PythonForAndroid_r4.apk
他のスクリプト言語に特に興味が無ければ、この二つをインストールしておけばよい。sl4aを立ち上げてPythonスクリプトを書いていこう。
簡単なサンプルを示す。

--- script.py ---
import sys
import os

from android import Android
droid = Android()

def line_handler(line):
    output = '<b>' + str(eval(line)) + '</b>'
    droid.eventPost('stdout',output)

index_html = os.path.join(os.path.dirname(__file__), 'index.html')
droid.webViewShow('file://' + index_html)

while True:
    event = droid.eventWait().result
    if event['name'] == 'exit':
        sys.exit()
    elif event['name'] == 'line':
        line_handler(event['data'] )
--- script.py ここまで ---

--- index.html ---
<html>
<head>
<script>
var droid = new Android();
function postInput(input){
    if(event.keyCode == 13)
        droid.eventPost('line', input)

    droid.registerCallback('stdout', function(e){
        document.getElementById('output').innerHTML = e.data;
    });
}
</script>
</head>
<body>
<input id="userin" type = "text" spelcheck="false" autofocus="autofocus" onkeyup="postInput(this.value)" />
<div id="output"></div>
<button id="killer" type = "button" onclick = "droid.eventPost('exit','')" >EXIT</button>
</body>
</html>
--- index.html ここまで ---

PythonもJavascriptも、オブジェクトを扱うタイプのスクリプト言語だから似たようなものだ。どちらか片方が読める人はザクッと理解してもらえると思う。
簡単に説明しておく。"script.py" と、"index.html" は、同じディレクトリにあることを想定している。(後々のことを考えると、この2つは同じディレクトリに置いたほうがいい)
  1. まずPythonスクリプトからdroid.webViewShow()でindex.htmlを立ち上げる。これがこのアプリのGUIになるわけだ。
  2. GUIを立ち上げたらPythonスクリプトは droid.eventWait() で、HTML上のイベントを待つ。
  3. HTML上で何かイベントが起こったら、droid.eventPost('名前','値') で、Pythonに何かの「値」と「名前」を引き渡す。
  4. Pythonスクリプトはこれを受けて、「値」に対して「名前」に合った処理をすればいい。
  5. そして、その結果は、Python側からのdroid.eventPost('名前','値')でHTML側のJavascriptに返してやる。
  6. HTML側のJavascriptでは、droid.registerCallback()で、Pythonから結果を受け取りこれまた適切に処理をすればいい。
これを繰り返せば、PythonとHTMLを行ったり来たりしながらアプリが動作するというわけだ。ソースの中でHTMLからPythonへの渡す値の名前を赤で、PythonからHTMLへ渡す値の名前を緑で示した。
ここの「値」はテキストデータなので、XMLやJSONを使えば、少々複雑な構造を持った値でも受け渡しすることは可能だろう。
これでひとまず、PythonとHTMLの連携はできた。

次に、このPythonスクリプトとHTMLをPython環境と一緒にapkにパックする。
そのためには、まずAIDEが必要だ。これも以前に書いたがAIDEは、Android上でセルフ開発する環境。Javaを使えばAIDE単体でAndroidアプリを作ることもできるが、今回はコンパイル環境としてのみ使用する。
AIDE は Google Play にアクセスできるスマホを使っているなら、ここからインストールできる。Kindle Fire など Google Play に入れないなら、1Mobile marketなどから直接ダウンロードすることもできる
コンパイルの手順は、至って簡単。
まず、先ほどのsl4aのサイトから、“script_for_android_template.zip”という名前のファイルをダウンロードする。具体的にはこのページの右下にある「View raw file」というリンクをクリックする。
ダウンロードできたら、これを適当なディレクトリに展開する。
展開したら、その中に "res" というディレクトリを探そう。見つけたら、更にその中に "raw" というディレクトリがあるはずだ。その中に入っている "script.py" を先ほど作った script.py と置き換える。更に、同じディレクトリにindex.htmlをコピーする。
後は、AIDEからプロジェクトを開いて、run させるだけ。

コンパイル後、apkファイルをインストールしてアプリが起動する。
こんな感じのアプリが起動しただろうか。

どうだろう、意外に簡単にAndroid上でWebKitとPythonが連携できた上に、最終的にはいとも簡単にAndroid上でアプリにコンパイルできてしまった。
WebKitが使えるならと、jQuery Mobile なども試してみると、どうやらそれなりに使えそうだ。
GUIはjQuery Mobileに任せ、内部の処理はPythonで組み上げておいて、納得いく仕上がりになったら、AIDEでパッケージングしてリリースというお手軽セルフ開発環境がもう、実際に手の中にあるわけだ。
ちなみに、Kindle Fire HD 8.9 + Bluetoothキーボードという組み合わせは予想以上に快適だ。
ふと思いついたアイデアを会社帰りの電車の中でゲームアプリに仕上げて一攫千金なんてことも全然夢じゃないんじゃないの?(笑)
続く

3 件のコメント:

ten さんのコメント...

出来ました(^-^)/情報ありがとうございます。

著者 さんのコメント...

コメントありがとうございます。
お役に立てたようで、光栄です。

匿名 さんのコメント...

まさかAndroid上でコンパイルできるとは(°Д°)
情報ありがとうございます。