Pythonで作るAndroid WebView アプリ （非kivy)

ずっとLinuxMint18.2(Ubuntu16.04LTS派生)を使っていてWebViewアプリの作成には失敗していたのですが、LinuxMint19.3(Ubuntu18.04LTS派生)に上げた途端に成功したのでメモ。[過去記事][prereq]と手順は似ているので差分のみを書いていきます。

# openjdkの混在を避ける

私がOSをclean installではなくupgradeしたせいなのかopenjdkは複数のversionが混在してしまいました。

```bash
# 現在入っているopenjdkを調べる
dpkg -l | grep openjdk
```

```
ii  openjdk-11-jre:amd64                  11.0.6+10-1ubuntu1~18.04.1                              amd64        OpenJDK Java runtime, using Hotspot JIT
ii  openjdk-11-jre-headless:amd64         11.0.6+10-1ubuntu1~18.04.1                              amd64        OpenJDK Java runtime, using Hotspot JIT (headless)
ii  openjdk-8-jdk:amd64                   8u242-b08-0ubuntu3~18.04                                amd64        OpenJDK Development Kit (JDK)
ii  openjdk-8-jdk-headless:amd64          8u242-b08-0ubuntu3~18.04                                amd64        OpenJDK Development Kit (JDK) (headless)
ii  openjdk-8-jre:amd64                   8u242-b08-0ubuntu3~18.04                                amd64        OpenJDK Java runtime, using Hotspot JIT
ii  openjdk-8-jre-headless:amd64          8u242-b08-0ubuntu3~18.04                                amd64        OpenJDK Java runtime, using Hotspot JIT (headless)
```

これまでの経験でそういった状態だとapkの作成が上手く行かない事は分かっていたので一つのversionだけを残しました。

```bash
sudo apt remove openjdk-11-jre openjdk-11-jre-headless
```

apkをbuildする時に入れろと言われている`openjdk-8`を残しましたが、`openjdk-11`はOSに元から入っている事もあって削除すると後々問題が起こりそうで怖い所です。もし誰か`openjdk-11`だけを入れた状態でapkの作成に上手くいった人が居たら教えてくれると助かります。

# test用のcode

今回はweb frameworkに[Remi][remi]を選びました。これは[Flask][flask]や[Bottle][bottle]とは違ってHTMLの知識が無くて済む物で私にとってうってつけだったからです。codeはexamplesの[hello world](https://github.com/dddomodossola/remi/blob/master/examples/helloworld_app.py)を書き写しました。

```python:main.py
import remi.gui as gui
from remi import start, App

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        wid = gui.VBox(width=300, height=200)
        self.lbl = gui.Label('Hello\n test', width='80%', height='50%', style={"white-space":"pre"})
        bt = gui.Button('Press me!', width=200, height=30)
        bt.onclick.do(self.on_button_pressed)
        wid.append(self.lbl)
        wid.append(bt)
        return wid

    def on_button_pressed(self, emitter):
        self.lbl.set_text('Hello World!')

if __name__ == "__main__":
    start(MyApp, debug=True, address='0.0.0.0', port=12343, start_browser=True)
```

重要なのは最後の`port=12343`で、これでserver側(remi側)がport番号12343で待ち受ける事になります。なのでこの値を`buildozer.spec`に指定するclient側(webview側)の接続先port番号と合わせておく必要があります。

# buildozer.spec

kivyアプリを作る時との違いはこれだけでした。

```
requirements = python3,remi
p4a.bootstrap = webview
p4a.port = 12343
```

# 実機上での様子

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144673/7de5a329-4cbc-b699-695d-3f2764ecda0d.png" width="25%"/>

# 最後に

[python for android][p4a]はkivyに限らず色んなpythonアプリをapk化してくれます。実際私はpygame2を使ったアプリでも成功しました。自分で試してはいませんが

- [Remi][remi]と同じで外部moduleへ依存していない[Bottle][bottle]
- 公式docで触れられている[Flask][flask]

も使えると思います。

[p4a]:https://github.com/kivy/python-for-android
[prereq]:https://qiita.com/gotta_dive_into_python/items/82ee13ebac44719adad6
[remi]:https://github.com/dddomodossola/remi
[bottle]:https://bottlepy.org/
[flask]:https://palletsprojects.com/p/flask/