2013年7月21日日曜日

AIDE + sl4a python & jQuery mobile で、リッチUIな Androidアプリをお手軽セルフ開発!?

Androidのスクリプトプラットフォームsl4a。各種スクリプト言語を使って、お手軽にAndroidの機能を利用できるのでとても便利。しかも、PythonスクリプトならばAIDEを使えば、簡単にapkファイルにパックできるので、超お手軽なセルフ開発環境なのである。sl4a上でWebKitを呼び出せばjQuery mobileなどのJavascriptライブラリが使え、これまた簡単にUIリッチなスクリプトが組めてしまう。このあたりは、先日このブログでも書いた。
ただ、最終的にAIDEでこれをアプリ化するつもりならば、少し注意が必要だ。

まず、第一に理解しておかなくてはいけないのは、AIDEを使ってapkファイルにまとめる際、Pythonスクリプトは各種リソースの一つとして扱われるという事だ。
先日のブログで書いたように、Pythonスクリプトを置くのはプロジェクトディレクトリの下の "res/raw" というディレクトリの中である。
resディレクトリの以下に置かれたファイルはリソースとみなされるが、ここで使用出来るディレクトリの名前は決まっている。したがって、res/rawディレクトリの下に、勝手なディレクトリ構造を持ち込んだとしても無視されてしまう。だから、htmlだけをまとめて……とか、jQuery関連のファイルだけまとめて……というつもりで、res/rawの下にサブフォルダやサブディレクトリを作っても、apkの中にはパックされない。
したがって、script.pyと同じres/rawの下にjavascriptやcss関連のファイル、pngやgifなどの画像ファイルまで全て並べておくことになる。更に、リソースファイルにはファイル名にも制限があり、"-"や"."は使えないので、jQuery関連のファイル名はすべてリネームしておく必要がある。
これはPythonスクリプトについても同じなので注意しておくべきだろう。

次に厄介なのは、WebKitが呼び出されたときのカレントディレクトリである。
どういうわけで、わざわざこんなことになっているのかわからないが、1.HTMLのカレントディレクトリ、2.Pythonのカレントディレクトリ、3.Pythonスクリプトが展開されるディレクトリ、これら全てがみごとにバラバラなのだ。
簡単なスクリプトを書いて確認してみる。

----- script.py -----
import android
import os
import sys
import time

droid = android.Android()

current = os.getcwd()
pydir = os.path.dirname(__file__)

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

dirdata = 'current: %s<br>pydir: %s<br>' % (current,pydir)

while True:
    event = droid.eventWait().result
    if event['name'] == 'exit':
        sys.exit()
    if event['name'] == 'getdata':
        time.sleep(1)
        droid.eventPost('stdout', dirdata)
----- script.py END -----

----- index.html -----
<html>
<head>
<script>
var droid = new Android();

function diroutput(e){
    document.getElementById('output').innerHTML = e.data;
}

function getdir(){
    document.getElementById('output').innerHTML = "Wait ....";
    droid.eventPost('getdata','');
    droid.registerCallback('stdout', diroutput);
}
</script>
</head>
<body>
<button id="getdir" type="button" onclick="getdir()">GET DIR</button><br>
HTML: 
<script>
document.write(location.pathname);
</script>
<div id="output"></div>
<button id="killer" type="button" onclick="droid.eventPost('exit','')">EXIT</button>
</body>
</html>
----- index.html END -----

AIDEでコンパイルした後の実行結果はこんな感じ。
HTMLのカレントディレクトリは、Javascriptでそのまま表示。
Pythonのカレントディレクトリと、Pythonスクリプトが展開されているディレクトリは、「GET DIR」ボタンを押すと表示される。
奇妙なのは、HTMLのカレントディレクトリと、Pythonスクリプトのカレントディレクトリが、AIDEでコンパイルしたにも関わらずsl4aのディレクトリなのだ。スタンドアロンのapkにパックしてもなお、sl4aのディレクトリ構成に依存して動作している。
1.HTMLのカレントディレクトリは "/storage/sdcard0/sl4a/scripts/"
2.Pythonのカレントディレクトリは "/storage/sdcard0/sl4a"
3.Pythonスクリプトが展開されているディレクトリは "/data/data/com.dummy.fooforandroid/files"
と、なっている。
ややこしいことに、script.pyからdroid.webViewShow()を使って開いているのは、 "file:///data/data/com.dummy.fooforandroid/files/index.html" なのだが、HTML自身は "/storage/sdcard0/sl4a/scripts/" にいると思っているのだ。
つまり、index.htmlから相対パスでcssやJavascriptを読み込もうとしても、ありもしない/storage/sdcard0/sl4a/scripts/の中を探すばかりで、何も読み込むことができないのだ。
何故こうなっているのかは、こここのあたりを読めばわかりそうだが、今は深追いはよそう。
とにかく、ここまでの検証でわかったことは、jQuery mobileを使いたいならば、1.関連のファイルは、ファイル名をアルファベット、アンダースコア("_")と、拡張子(".js"や".css"など)だけで構成された
シンプルな名前にして、script.pyと同じディレクトリに置く。 2.これにあわせて、スタイルシート(".css"のついたファイル)の中の、"image/xxxxx.gif" などの記述を "xxxxx.gif" に書き換えておく。 3.HTMLからJavascriptやスタイルシートを呼ぶときのパスは "file:///data/data/com.dummy.fooforandroid/files/xxxxx.js" のように、フルパスで記述する。 以上に注意すればjQuery mobileとPythonを使って本格アプリをセルフ開発することができる。
ただ、パスをフルパスで記述してしまうと、ブラウザ上でUIのテストをして、sl4aでスクリプトのテストをして、その後に毎回HTMLの中身を書き換えないといけない。ブラウザ上で何かテストをするたびにパスを書き換えるのはちょっと面倒だ。もう少し別の手を考えてみたい。
(続く)


1 件のコメント:

정영훈 さんのコメント...

I love python too!
Thanks to this post. :)
(I can't use Japanese well. sorry..)