Python Kivyの使い方④　～Androidでの実行～

# あらまし

今まで作成した記事は以下になります。

+ [Kv Languageの基本](http://qiita.com/dario_okazaki/items/7892b24fcfa787faface)
+ [電卓を作成する](http://qiita.com/dario_okazaki/items/910abf09344a60dd7823)
+ [WebAPIとの連携（リクエストの送受信から結果表示まで）](http://qiita.com/dario_okazaki/items/32446faff803a067d700)

今回は、KivyがQt系のライブラリと比較した際に利点とされる、モバイル（iOS,Android）   系の出力のうちAndroidの出力について説明します。先に結論から言うと個人的には微妙です。帯に短しタスキに長しというか、こちらがたつと後ろが立たずというか・・・。

# 作成するもの
前回の [WebAPIとの連携（リクエストの送受信から結果表示まで）](http://qiita.com/dario_okazaki/items/32446faff803a067d700)をAndroid端末で実行してみます。

# 使用するコード
前回のコードと内容はほぼ一緒です。変更があった部分に関しては、適宜紹介します。

# KivyをAndroid端末で実行する方法

方法としては３つ方法がありますが目的によって実行方法が違います。

①自分の保有するAndroid端末で動かす
②APKを作成し、Google Playなどの配布して不特定多数の人に利用してもらう
③python-for-androidを利用してandroid端末上でPythonを実行する


①の場合は、[Kivy Launcher](https://play.google.com/store/apps/details?id=org.kivy.pygame&hl=ja)という、Androidアプリを使用して実現します。今回はこの方法を採用して説明します。

②の場合はUbuntuにBuildozerというパッケージをインストールして実現します。
windowsの場合は、VMが配布されていますのでそちらを使用してください。
https://kivy.org/#download のVirtual Machineの項目からダウンロードできます。

実際に使用する場合は、[KivyアプリケーションをGoole Play Storeで公開する為に #2 APKを作成](http://qiita.com/gotta_dive_into_python/items/f3a6a2c83ed96366bc2f)という投稿で実際に実行された方がいるので参考にしてみてください。

③の場合は①、②とは方法性が違ってAndroid端末上で実際にPythonスクリプトを実行するという方法になります。Qpythonで検索すると色々出てきます。

この辺りの内容ですが、[2016年現在の「Python を android で使う」](http://hhsprings.pinoko.jp/site-hhs/2016/08/2016%E5%B9%B4%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%80%8Cpython-%E3%82%92-android-%E3%81%A7%E4%BD%BF%E3%81%86%E3%80%8D/)という記事で詳しく説明されていますので、興味のある方は読んでください。

参考

+ [Programming Guide(翻訳済み) » Create a package for Android(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/packaging-android.html)
+ [QPython - Python on Android](http://qpython.com/)

# 実行するPython環境について

検証環境ですが、Kivyは1.9.1になります。一方Pythonの方は**Python2.7**になります。Kivyの公式サイトを見ると、AndroidはPython３に暫定的に対応したとありますが、2017年2月現在は実質的にPython2系対応でPython3系には非対応と考えたほうが良いです。理由は後述します
なおiOSはPython2.7対応でPython３系の対応は現在対応中だそうです。

# 実際に検証に使用したAndroid端末について

試した機種は以下の2種類になります。

+ Nexus (OS Android6.01)
+ ZenFone 3 Laser(OS Android6.01)
+ Iconia One 7 (OS Android5.01)

Android自体はメーカー、機種ごとに固有の機能があるので機種、OSによっては動かないかもしれないです。


# AndroidでKivyを実際に動かす
いか、実際の操作になります。

## Kivy Launcherについて
[Kivy Launcher](https://play.google.com/store/apps/details?id=org.kivy.pygame&hl=ja)はGoogle Playに配布されているアプリで、使用することでAndroid上でKivyを使用したPythonスクリプトを手軽に使用できます。
以下簡単な使用方法です。

なお、使用方法を説明するにあたり、Kivy公式サイトで配布しているdemoプログラムである、「touchtracer」を用いて説明します。

参考

+ [Gallery of Examples(翻訳済み) » Touch Tracer Line Drawing Demonstration(翻訳済み)](https://pyky.github.io/kivy-doc-ja/examples/gen__demo__touchtracer__main__py.html)
+  [ソースコード(github)](https://github.com/kivy/kivy/tree/master/examples/demo/touchtracer)

### Kivy Lancherの使い方
事前に、AndroidにPlayストアからKivyLancherをインストールしてください

#### ①Android端末をPCとUSB接続します。
![0.png](https://qiita-image-store.s3.amazonaws.com/0/11002/c808fe1c-b14b-069a-9b0e-06f141d8e289.png)

ファイル転送を選択してください。
####  ②Kivyフォルダを作成してファイルを配置する

![PC.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/fb8a9949-e498-7ca8-af9d-a67787297f98.jpeg)

「Kivy」というディレクトリを作成します。
ディレクトリ配下にフォルダを作成しプログラムを置いてください。

置くのは以下のファイルです。

+ main.py :実行するPythonファイルです。**ファイル名は必ずmain.pyにしてください**
+ kvファイル
+ android.txt：アプリの情報を各ファイルです。**必須ファイルです。**
+ icon.pic :アプリのメニュー一覧で表示される画像ファイルです。必須ではないです。

android.txtですが中身は以下になります

```
title=Touchtracer
author=Kivy team
orientation=landscape
```

「title」にはアプリの名前を「author」には作者名をいれてください。
「orientation」は起動時に縦、横どちらの向きを表示するかです。「landscape」では横向きを、「portrait」では縦の向きになります。

#### 参考　Kivy Launcherのバッググラウンドプロセスについて
Kivy Lanucherで起動したプログラムですがバッググラウンドで動かすことが可能だそうです。活用するとアラームアプリなども作成が可能です。

参考

+ [「Building a background application on android with Kivy.」が期待通りのものだった話](http://hhsprings.pinoko.jp/site-hhs/2016/08/%E3%80%8Cbuilding-a-background-application-on-android-with-kivy-%E3%80%8D%E3%81%8C%E6%9C%9F%E5%BE%85%E9%80%9A%E3%82%8A%E3%81%AE%E3%82%82%E3%81%AE%E3%81%A0%E3%81%A3%E3%81%9F%E8%A9%B1/)


####  ③アプリを起動して動かす

実際に動かしてみます。

#### １．Kivy Lancherを実行する
Android端末でKivy Lancherを実行します。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/11002/9988615c-1482-a95f-6e30-7e35112b8599.png)

待ち画面が表示されます。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/11002/ea71c0f8-f107-4a51-8d39-7741ebb065ac.png)

#### ２．アプリを選択する
アプリの一覧が表示されるので、アプリを選択してください。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/11002/0e431f2d-ef0a-ba6a-7480-c965b2836bc9.png)

#### 3．アプリの起動画面
選択後、待ち画面が表示され、しばらく立つと選択したアプリが端末上で動作できます。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/11002/ac692a5b-30c7-1bf7-6083-9c397718fc3a.png)


# 前回のアプリを動してみる
前回のアプリを実際に動かしてみます。「Touch tracer」のように動かそうとしますが、Kivy Lancher上から選択して起動しようとしてもうまく動かず、アプリ自体がクラッシュしてしまいます。
Android本体の.kivyの内部のLogを回収してみました。以下がログの中身の抜粋です。

```py3
[INFO              ] Kivy: v1.9.1
[INFO              ] Python: v2.7.2 (default, Mar 20 2016, 23:30:13) 
```

Python2.7で実行されていました・・・。
そのために、前回作成していたプログラムを動かすためには、Pytho3からPython２系に変換しないといけませんでした。具体的には以下の変換を行いました。
なお筆者はPythonは３系から始めたので２系はほとんどやっていませんでした。

+ 検索結果のdata(list型)の初期化をdel　list[:]に変更する。
+ 日本語の文字列周りのエンコードエラーの対応のために「.encode('utf-8')」を適宜入れる。
+  Requests ライブラリが使用できなかったためKivy独自のライブラリUrlRequestを使用し、それに関する修正を行う。

このうち、最後のUrlRequestの修正について説明します。

## KivyのUrlRequestの使い方

ソースで修正した箇所を以下に抜粋します。

```py3:main.py

from kivy.network.urlrequest import UrlRequest
import urllib

class AddSearchBookForm(BoxLayout):
    def search_book(self):
        set_title = urllib.quote((self.search_input.text).encode('utf-8'))
        req_url = "http://iss.ndl.go.jp/api/sru?operation=searchRetrieve&query=title%3d%22{0}%22%20AND%20from=%22{1}%22&maximumRecords={2}&mediatype=1".format(set_title, set_fromdate, set_maximum_records)

        res = UrlRequest(req_url, self.gotBooklists)
        
    def gotBooklists(self, req, results):
        result_records = result_parse(results)

```

UrlRequestですが、今回の修正に伴う特徴は２つあります。

+ URLエンコードが必要。
+ UrlRequestは**非同期通信**である。

[UrlRequest](https://kivy.org/docs/api-kivy.network.urlrequest.html)のAPIリファレンスを見ると以下のような仕様になっています。

```py3
req = UrlRequest(url, on_success, on_redirect, on_failure, on_error,
                 on_progress, req_body, req_headers, chunk_size,
                 timeout, method, decode, debug, file_path, ca_file,
                 verify)
```

まずURLは%文字列である必要があるため、urllibで%文字列に変換して第一引数にいれました。
また実行時に返却する値のreqにはurlからのPOSTした返却結果が格納されますですが非同期通信のために、サーバから結果が返らず、すぐには値が入ってこないのでプログラムが先に進んでしまいます。そのため前回のままだと、POSTした結果の処理が上手くいかないという問題があります。
第２引数のon_successに、サーバーサイドからのPOST結果が返ってきた場合の処理（メソッド）を設定するか、または返り値にwait()を使用して、返却結果が戻るのを待つ必要があります。今回は前者のon_successを使用する方法を用いて、gotBooklists()をon_sucessに設定し、gotBooklists()に結果をパースして整形をおこなう処理を実行するようにしました。

参考

+ [In kivy python how to get data from a url request(stackoverflow)](http://stackoverflow.com/questions/38152228/in-kivy-python-how-to-get-data-from-a-url-request)
+ [UrlRequest(API Reference)](https://kivy.org/docs/api-kivy.network.urlrequest.html)


## 実行結果

Pytho2系の対応をして、動作を行うとKivy Lancher上でプログラムが実行できました。

![1_40.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/1c861ec8-7032-6326-abfa-56af44fb9538.jpeg)

また、日本語入力についてですが、WindowsOS上では全角入力時にはIMEが開きませんでしたが、Android端末上では日本語入力時にもIMEが開き快適に入力できます。

![ideapad.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/e1dd977f-355a-cd43-6f79-cc6a66f387c3.jpeg)



## 参考　Android特有のAPIを実行する方法
今回は使用しませんが、KivyではAndroid固有のJAVAのAPIに関してはPlyerとPyjniusを使用することで実行できます。これを使用することでアプリ内でカメラを起動して写真を撮影するやメールを送るといったことが可能です。Androidアプリで標準的な機能はPlyerまたはPyjniusを使用することで実現できます。

+ **Plyer**  Pythonラッパーのプラットフォーム非依存API群。
+ **Pyjnius** PythonからJava / Android APIへの動的アクセスする。

実際に国内で使用されている方の記事と公式サイトのリンクをあげておきます

+ [pyjniusを使って写真を撮る - Kivy Advent Calendar 2013](http://d.hatena.ne.jp/cheeseshop/20131214/1386987210)
+ [plyer.compass が使い物にならない件](http://hhsprings.pinoko.jp/site-hhs/2016/07/plyer-compass-%E3%81%8C%E4%BD%BF%E3%81%84%E7%89%A9%E3%81%AB%E3%81%AA%E3%82%89%E3%81%AA%E3%81%84%E4%BB%B6/#more-8424)
+ [Using Android APIs(Android APIを使用)](https://pyky.github.io/kivy-doc-ja/guide/android.html#using-android-apis)
+ [Play (github)](https://github.com/kivy/plyer)
+ [Pyjnius(github)](https://github.com/kivy/pyjnius)

## 参考　iOSへ対応について

iOSに関しては筆者は試したことがないですが、iOSアプリの開発も可能です。
コードはPython2系対応のみとなりPytho3系は未対応です。
toolchainという機能を使用してXcode用のプロジェクトを作成し、そのプロジェクトからビルドできるようになるようです。

参考

+ [PythonのマルチプラットフォームGUIライブラリkivyを使ってMac, Ubuntu, iOS用のGUIアプリを作る方法](http://myenigma.hatenablog.com/entry/2016/05/06/170854)
+ [Programming Guide(翻訳済み) » Creating packages for OS X(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/packaging-osx.html)

iOS特有のAPIに関してはこれもまたPyobjusを使用することでアプリ内で使用できるそうです

参考

+ [Pyobjus](https://github.com/kivy/pyobjus)

国内では小樽商科大学の原口先生がKivyアプリを作成してAppStoreに出されて言います。
原口先生はまたKivyの公式マニュアルの翻訳(https://pyky.github.io/kivy-doc-ja/ )の主要メンバーの一人です。

参考
[小樽商科大学　原口研究室](http://puzzle.haraguchi-s.otaru-uc.ac.jp/)

## 参考 Pythonの外部ライブラリを使用するには

モバイルでMatplotlibなどのPythonの標準ライブラリ以外を使用するにはKivy gardenというアドオンの機能を使用して実現することになります。

参考

+ [kivyLauncher 環境でグラフ (+ kivy garden について)](http://hhsprings.pinoko.jp/site-hhs/2016/08/kivylauncher-%E7%92%B0%E5%A2%83%E3%81%A7%E3%82%B0%E3%83%A9%E3%83%95-kivy-garden-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)

+ [Kivy Garden (github)](https://github.com/kivy-garden/)


## 参考 Kivyで作成されたアプリについて

公式サイトのWikiを見るとKivyを使用して作成された、アプリプロジェクトの一覧があります。
これを見ると実際にどのようなアプリが作成可能かがわかるかと思います。

参考

+ [List of Kivy Projects](https://github.com/kivy/kivy/wiki/List-of-Kivy-Projects)

# まとめ
サーバーサイドと連携して表示するアプリをAndroid端末で動かすことが実際にできました。Androidのアプリに関しては２D画像主体のアプリですと、カード系のソーシャルゲームや検索アプリなど、大体の物は開発が可能だと思います。

個人的にはAndroidアプリを作成するにあたり、Kivyを使用するかどうかは微妙なところです。Androidアプリを出すということはiOS版の開発も視野にいれてやるのが主流かと思います。そうなるとPytho2系での開発が前提になりますが、日本語（マルチバイト文字）の扱いに手間がかかります。日本でのコミュニティもないので、XamarinやUnityといったC#を使ったマルチプラットフォームの開発や、Andoriネィテイブで開発する方が現時点ではよいのかなと思っています。
少なくとも国内でのPythonエンジニアの数と相まって、積極的に採用するものではないと思います。

Python3系の対応がiOSでも正式にリリースされ、Kivyｍ Lancherのような簡易のプレビューアプリができればまた話は変わってくるとは思いますが、現段階ではこのような評価になります。


# 全体のまとめ
全4回にわたってKivyの使い方について説明しました。まだ説明していない主要な機能としてはAnimationがありますが機会があれ触れようと思っています。
今までの説明を読めば一般的なアプリを開発する事が可能、もしくは取っ掛かりにはなると思います。またKivyがどんなライブラリで何ができて何ができないかもおぼろげながらに分かってきたかと思います。

Kivyの利点と欠点を上げておくと以下になるかと思います。

利点

+ Pythonでアプリが書ける
+ Kv Languageを使えばレイアウトの変更が簡単にできる
+ MITライセンスなのでライセンスフリーで使用可能。

欠点

+ TextInputのバグでOSによっては日本語入力でIMEが開かない
+ マルチプラットフォームと銘打っているがiOS/Android対応になるとPython2系での開発が必要
+ iOS/Android対応に標準ライブラリ以外を使用する場合には工夫が必要

このあたりを踏まえてKivyを使用するかしないかを考えてみてもらえると幸いです。
またバグに関してはオープンソースなのでissueや要望を上げていく、改良してコミットするということで改善はされていくのでそこはユーザー次第かと思います。

参考

+ [User’s Guide(翻訳済み) » Contributing(翻訳済み)](https://pyky.github.io/kivy-doc-ja/contribute.html)
+ [User’s Guide(翻訳済み) » Contact Us(翻訳済み)](https://pyky.github.io/kivy-doc-ja/contact.html)


Kivyに関しては現在もgithub上で活発なやり取りをされていてオープンソースとしての将来性はあると思っています。
この記事をよんでKivyを使ってみたいと思いましたら幸いです。