Pythonでandroidアプリをつくるよ〜kivy & buildozer on MacOS

Pythonで使えるGUIライブラリはいろいろあるが、PCでもスマホでも使えるクロスプラットフォームGUIは少ない。Kivyはそんな数少ないクロスプラットフォームGUIの一つである。ただしKivyライブラリを使っても、あくまでpythonプログラムなので、そのままではandroid で実行できない。pythonプログラムからAPKファイル(androidでの実行形式ファイル)を作る必要がある。それをやってくれるのが、Buildozer である。

Kivy & BuildozderはMacPortsでもHomebrewでもインストール可だが、ここでは、Macports を使ってのインストールを説明する。

作動確認したマシーンは以下の通り

Python のインストール

KivyをPC上で使うだけなら、pythonのバージョンはどれでも構わないが、buildozerを使ってapk ファイルを作るときにエラーが出るので、pythonのマイナーバージョンまで注意すべし。

動作確認したバージョン
不可
Macports Python3.6.7 Python3.7.1(現時点のmacportsでの安定版の最新)
Homebrew Python3.7.2, 3.7.0

         --- Python3.7.1がダメなのか?!

portコマンドでpythonとpipをインストール

$ sudo port install python36
$ sudo port select --set python python36
$ sudo port install pip-36
$ sudo port select --set pip pip-36

/opt/local/bin および /opt/local/Library/Frameworks/Python.framework/Versions/3.6/bin にパスを通すのを忘れずに。

Kivy のインストール

Kivyのインストール

Kivyおよび依存関係のあるツールをインストール。

$ sudo port install libsdl2 libsdl2_image libsdl2_ttf libsdl2_mixer
$ sudo pip install -I Cython==0.29.2
$ sudo pip kivy

kivyのバージョンによって、不適合なcythonのバージョンがある。今の場合、kivy-1.10.1がインストールされたが、Cython-0.29.2で問題ないことは確認した。

Kivyの動作確認

サンプルとして、“Hello World”と表示させるプログラムを書く。

from kivy.app import App
from kivy.uix.label import Label
	  
class HelloApp(App):
    def build(self):
        return Label(text='Hello World')

if __name__ == '__main__':
    HelloApp().run()

main.py という名前で保存。(buildozerを使うときは必ずmain.pyにすべし)

$ python main.py

新しくwindow が現れて“Hello World”と表示されればOK。

Buildozer のインストール

Buildozer本体のインストール

$ sudo pip install buildozer

これでBuildozer-0.37がインストールされるが、実はこのバージョン、バグがあるので、開発版にアップグレードする。

$ sudo pip install git+http://github.com/kivy/buildozer

Buildozer-0.38.dev0がインストールされる。Buildozerを正常に作動させるには他にもいくつかのツールのインストールが必要。

CrystaX NDKのインストール

あとでbuidozer起動する時に、デフォルトではGoogleのNDKを勝手にやってくれるのだが、GoogleのNDKだと途中でエラーが出る。代わりに、CrystaX NDKを使う。https://www.crystax.net/en/downloadから crystax-ndk-10.3.2-darwin-x86_64.tar.xz をダウンロード。

$ xz -dc crystax-ndk-10.3.2-darwin-x86_64.tar.xz | tar xvf -

で解凍。crystax-ndk-10.3.2 ディレクトリ内に展開される。

Java Development KitJDK)のインストール

JDKの最新版はバージョン11だが、buildozer はバージョン8しか対応していないことに注意。

$/usr/libexec/java_home -V

で現在インストールされているJDKのリストと、アクティヴになっているバージョンを表示される。

Matching Java Virtual Machines (5):
11.0.1, x86_64: "Java SE 11.0.1" /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home
1.8.0_192, x86_64: "OpenJDK 8" /Library/Java/JavaVirtualMachines/openjdk8/Contents/Home
1.8.0_191, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
1.6.0_65-b14-468, x86_64: "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
1.6.0_65-b14-468, i386: "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home

最後の行がアクティヴになっているバージョンのHome。この場合、バージョン11がアクティヴになっている。”OpenJDK 8“ か”Java SE 8”のどちらかをアクティブにすべし。あとで、buildozer を作動する際に

$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk8/Contents/Home

のように一時的に環境変数を変えると良い。

もし、リストに"OpenJDK 8”も"Java SE 8”がなかったら、

$ sudo port install openjdk8

で"OpenJDK 8”をインストールできる。

Buildozer 起動

Buildozerの設定ファイル

作業ディレクトリ(ここでは“Hello”とする)を作って、そこにmain.py (あれば、他の関連プログラムファイルも) を置く。

$ cd Hello
$ buildozer init

とすると、作業ディレクトリ内に”buildozer.spec”というファイルができる。 buildozer.specは、以下の部分を書き換える。

# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3crystax==3.6,kivy

# (int) Android API to use
android.api = 27

# (int) Minimum API required
android.minapi = 21
  
# (int) Android SDK version to use
android.sdk = 24
  
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
android.ndk_path = (crstax-ndkディレクトリのパス)/crystax-ndk-10.3.2/

# (str) python-for-android branch to use, defaults to stable
p4a.branch = master

# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
log_level = 2

Buildozer でAPKファイルを作る

$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk8/Contents/Home 
$ buildozer android debug

成功すると

# Android packaging done!
# APK myapp-0.1-debug.apk available in the bin directory

と表示され、作業ディレクトリ中のbin ディレクトリにmyapp-0.1-debug.apkが作られている(アプリ名とバージョンはbuildorzer.spec内で設定されている)。基本的にはこれだけでOKのはずだが、初めて起動されるときは、環境によってはツールが足りなくてエラーがでる。

例えば、

pkg_resources.DistributionNotFound: The ’sh’ distribution was not found and is required by buildozer

というエラーメッセージが出たら、

$ sudo pip install sh

でshライブラリをインストールすれば良い。

OSError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

ってエラーが出ることも。このときは

$ sudo port install curl

curl をインストールしたらエラーを回避できた。

APKファイルをAndroidに移動

android端末にて

まずはインストールしたいandroid 端末をディベロッパーモードにする必要がある。
[設定] —> [システム]—>[端末情報]
ビルド番号をしばらく連打するとディベロッパーになれる。

続いて、
[端末情報] —> [システム] —> [開発者向けオプション]

開発者向けオプション → ON
USBデバッグ → ON

に設定する。
Macandroid をUSBケーブルでつなぐとUSB使用のポップアップが出るので、 「ファイルを転送」を選択。

Mac にて
$ buildozer android debug deploy run

Android 端末側でアプリの起動が確認できればOK。

MacProにSSDを増設したよ

Mac Pro (Mid2010)にSSDを増設した。

増設前--- シングルブート
    ・HDD 1TBOS X 10.8.5 Mounten Lion

増設後--- デュアルブート
    ・HDD 1TB OS X 10.8.5 Mounten Lion
    ・Samsung SSD 850 EVO 500GB
                           OS X 10.11.6 El Capitan

SSDのOSは最終的には El Capitanにしたが、当初は最新OSの High Sierra を入れようとしていた。しかし、いろいろ問題が発覚したので El Capitan にダウングレードした。High SeirraのSSDからは普通に起動できHDも認識するが、従来のHDから起動しようとしても起動すらできない。また、SSDから起動した場合でも、ネットワークでファイル共有するとHDにはアクセスできても、なぜかSSDにが全く表示されない。High SeirraのSSDのみの起動しかせず、ネットワークによる共有も使わないのであればこれでもOKだが、当方の使用目的には合わないので、なくなくEl Capitanにダウングレードした。

結論から言うと、問題の原因は High Sierra が新しいファイルシステム "APFS" を採用したことにある。原因が分かってしまえば、なんてことないが、当初は問題がHigh Sierraに起因しているとは全く予想してなくて、High Sierra インストールの際のファームウェア更新とか、SSDMacの相性とか、いろいろな要因を疑った。「mac」、「SSD」、「認識しない」なんてキーワードで検索しても、"APFS"のことなんて引っかからないのである。(代わりに"SSDが壊れている" とか"そのメーカーのSSDMacの起動を保証してない”とか出てくるので、非常に凹む。)ここではHigh Sierraをインストールで起こったさまざまな問題を書き綴っておく。がその前に、SSD増設、OSインストールの手順を手短に述べておく。

SSD増設手順

1. SSD取り付け

MacProの電源を切ってサイドカバーを開く。4つのシリアルATAディスクのスロットの一番左が元々装着されているHD。今回は隣の2つ目のスロットにSSDを装着する。スロット金具は引っ張ると簡単に外れるのでこれにSSDを固定して、スロットに戻しサイドカバーを閉じれば装着完了。
ただし、MacProのシリアルATAディスクのスロットは3.5インチであり、一方、購入した "Samsung SSD 850 EVO 500GB" は 2.5インチ。取り付けのためのアジャスターが必要。ここでは、「Mac Pro専用2.5インチSSD/HDDマウンタ SSD Mounter Pro (林檎派)」を使った。

2. SSD初期化

Macを起動すると、”読み込めないディスクがあります”とポップアップが出るので、「初期化」をクリック。すると「ディスクユーティリティ」が立ち上がる。左側のボックス内のディスク一覧から「Samsung 850 EVO 500GB」を選び、右側のフィールドの「消去」をクリック。

フォーマット:OS X 拡張(ジャーナリング
名前:Macintosh SSD

として、フォーマットを開始。

3. OSインストール

Apple Store からHigh Sierraを入手。ダウンロードさたれ「High Sierra インストーラー」をクリックすると、インストールにはファームウェアの更新が必要といわれる。そのためにシステム終了して、長押しで電源スイッチいれるが、この時、結構な時間長押ししなければならない。電源ランプが点滅したら離してよし。ファームウェアの更新の一連の作業が終わったら、再び「High Sierra インストーラー」をクリックすると今度はインストールが始まる。あとは指示に従うだけ。

問題発生!

SSDへのHigh Sierra のインストールが完了して、SSDからの起動も確認、無事作業終了と思って、HDから起動を試みる。

「システム環境設定」→「起動ディスク」→「Macinton HD OS X 10.8.5」

そして「再起動」をクリック...が、HDから起動できない!!アップル画面に現れたのは

panic( cpu 0 caller ..........

で始まるエラーメッセージ。ここからはもう進まない。仕方がないので、電源ボタン長押しで電源を落とす。一度はSSDから起動できたので、起動ディスクの設定さえSSDに変えられれば良いはず。そこで、

・セーフモードで起動
・リカパリーモードで起動

をこころみる。

セーフモードで起動

電源を入れた直後に「shift」キーを押し、そのまま押し続け、ログイン画面になったら離す。HDのMounten Lion がセーフモードで立ち上がる。ここまではクリア。ログインして、「システム環境設定」→「起動ディスク」ところが、「コーンピュータの起動に使用したいシステムを選択してください」の下のBoxには "Macinton HD OS X 10.8.5"しかない。つまりSSDを選べない!しかも、ファインダーのサイドバーを見ると、「デバイス」の項目にはSSDが見当たらない。SSDはマウントすらされてない。

リカバリーモードで起動

電源を入れた直後に「Command + R」キーを押す。「OS X ユーティリティ」が立ち上がるが、それは置いといて、アップルメニューから「起動ディスク」を選択。ところが、これまた「コーンピュータの起動に使用したいシステムを選択してください」の下のBoxには"Macinton HD OS X 10.8.5"しかない。やっぱりSSDを選べない!これはまずい。SSDは壊れてる?

しかたがないので、メニューバーの「起動ディスク」→「起動ディスクを終了」で終了させて、「OS X ユーティリティ」に戻る。「ディスクユーティリティ」を選ぶと左側のボックスに表示されたディスクは次の通り。


▼500.11 GB Samsung SSD 850 EVO 500GB Media
  disk0s2


▼disk2
  Mac OS X Base System
▼1 TB WDC WD1001FALS-41Y6A1 Media
  Macinton HD


むむむ?Samsung 850 EVO以下のパーディション名が "disk0s2"?SSD取り付け後に行ったディスクの初期化で名前を "Macintosh SSD" としたはず。しかも、「OS X 拡張(ジャーナリング)」でフォーマットしたはずなのに、フォーマットされてないことになっている。「ディスクを検証」してみるが異常なし。フォーマットが失敗してるだけ?もう一度、フォーマットして High SierraSSDにインストールしてみるが、さっきと同じ。High SierraSSDから起動はできるが、HDディスクから起動を選んだら最後。もうSSDに戻れない。

うーん。一応はSSDから起動できるんでSSDは壊れてないってこと?ただ、このHD からの起動だとSSDの中身が全然見えないってこと?じゃあ、USBフラッシュドライブに起動ディスクを作成したら?ただし、High Sierraの場合、12GBの容量が必要。手元にあるUSBドライブはそんなに容量がない。買いに行かねばならんのか...と一瞬悩んだが、そもそもUSBドライブを起動ディスクとして選ぶには「Startup Manager」を起動させるんだ。「Startup Manager」だっだら、問題のSSDも選択できるかも。

Startup ManagerでSSDを選択

再起動をかけたらすぐ「option」キーを押すと Start Manager が立ち上がる。
選択できる起動ドライブは

 ・Macinton HD OS X 10.8.5
 ・Macinton SSD OS X 10.13.2
 ・復旧-10.8.3

にょにょにょ?SSD、見えてるじゃん...「Macinton SSD OS X 10.13.2」をポチッと選ぶ。SSD、無事起動。腑に落ちないけど、一応起動できた。HDの中もちゃんと見える。アプリも普通に開ける。まあ、普通に使えるからいいか...と思ったが、ネットワークでのファイル共有が!同じLAN上の別のマシーン、MacBookからネットワークでこのMacProが見えるのだか、接続すると"Macintosh HD"しか表示されない。SSDは何処に?!これは使えない。

で、いろいろ試行錯誤して検索したら、High Sierra から新しいファイルシステム”APFS”を採用したことがわかった。今回はMounten Lion でSSDをフォーマットしたが、フォーマット方式の選択肢の中には”APFS”などもちろんない。従来方式の "OS X 拡張(ジャーナリング)" でフォーマットしても、High Sierraのインストールの際、勝手に"APFS"に直されるらしい。そんなわけで、High Sierra はあきらめて従来方式の El Capitan でやり直した。

結論:互換性を考えると、High Sierra はまだ早い

 

オバマの時代が終わる

バラク・オバマ大統領の任期が終わろうとしている。"Change-Yes, We Can"のスローガンで、民衆からの絶大な支持を受け選ばれた、黒人初のアメリカ合衆国大統領

在任中の最も評価される仕事は何か、と問われれば、多くの日本人は「広島訪問」と答えるだろう。現職合衆国大統領として初の訪問である。平和記念公園の原爆慰霊碑への献花、核兵器廃絶を訴える17分の心を打つスピーチ、被爆者と交わした抱擁、70年にも渡るわだかまりを解かす感動の瞬間であった。あのとき本当に感動した。しかし、同時に虚しさも覚えた。大統領就任間もない7年前のプラハ演説とは明らかにトーンが違う。亡くなった被爆者を慰霊する目的があるから、トーンが違うのは当たり前だが、そういう意味でトーンが違うというのではない。プラハでのバラク・オバマは自信に満ち溢れていた。

核保有国として、核兵器を使用したことがあるただ一つの核保有国として、米国は行動する道義的な責任を持っています。私たちは一カ国ではこの努力を成功させることはできませんが、リードすることはでき、始めることはできます。

だから今日、私は明白に、信念とともに、米国が核兵器のない平和で安全な世界を追求すると約束します。私は無知ではありません。ゴールはすぐには到達できないでしょう。私が生きている間には恐らく(難しいでしょう)。忍耐と粘り強さが必要です。しかし今、私たちは世界は変わることは出来ないという声を無視しなければいけません。私たちは主張しなければいけません、「イエス・ウィー・キャン」と。

プラハ演説http://www.nikkei.co.jp/senkyo/us2008/news/20090423u0c4n000_23.html

そこでは、核なき世界に向けて、アメリカ政府がどういう貢献をするか、アメリカ大統領の立場で語られていた。それに対して、広島の演説ではどうだったか。核なき世界を訴えるオバマ大統領の想いはひしひしと伝わってきた。しかし、それはアメリカの一市民活動家が語ったものだとしてもおかしくはない内容だった。

8年前、アメリカの多くの人々が ”Change-Yes We Can" という言葉を信じていた。バラク・オバマが合衆国大統領になることで、アメリカを変えられる。アメリカが変われば世界も変わる。しかし、オバマが大統領になっても大して変わらなかった。それどころか核なき世界の逆を行こうとしている。アメリカは老朽化した核弾頭を最新式のものに更新するために巨額の取り組みを開始している。その費用は今後30年で1兆ドルに達するとの試算がある。どうもアメリカ大統領にはアメリカの軍事政策の決定権はないらしい。

オバマ大統領の広島訪問は日本人にとって記憶に深く残った歴史的な出来事であるのは間違いない。記録より記憶に残る…とよく言われる。しかし、スポーツや芸能の世界ではそれでよかろうが、 政治の世界ではそうはいかない。記憶だけでは前に進んだことにはならない。記憶は所詮、ただの思い出だ。もう三週間後にはドナルド・トランプが大統領に就任する。感動的な記憶が台無しにならなければよいが。

 

We have known the agony of war. Let us now find the courage, together, to spread peace, and pursue a world without nuclear weapons.

私たちは戦争の苦しみを経験しました。共に、平和を広め核兵器のない世界を追求する勇気を持ちましょう。 

これは、原爆慰霊碑での献花に先立って訪れた原爆資料館の芳名録に寄せたオバマ大統領のメッセージである。自分自身に言い聞かせているのだろうか?とも思った。しかし、皆が心に刻むべき言葉である。記憶はだだの思い出だ。されども、それが人々の行動の原動力になることも事実だ。戦争の苦しい記憶があるから、人々は平和を切望する。世界平和や核兵器廃絶なんてものは、一国のリーダーがなんとかするものではなくて、世界中の人々の声や行動の積み重ねで実現させるものなのかもしれない。

 

微妙に怖い本当の話

お盆だよ。今日は微妙な怪談で。

 

湯川遥菜…シリアでISILに拘束され、ジャーナリスト後藤健二氏が救出に向かうが無惨にも二人共処刑されてしまった。あれからもう一年半が経ち、世間では忘れられた感がある。そんななか最近、湯川のblogを見つけた。と言ってもネットの世界ではわりと知られたblogらしい。 

マスコミから伝え聞く彼のプロファイルは、民間軍事会社のCEOであるもののこの分野のド素人で、英語のできないただのミリオタおやじである。しかし彼のblogを読むとだいぶ印象が異なる。彼のblogを信じるならば、かなりコミュニケーション能力が高くビジネスに長けた人物に見える。英語ができないという見聞も疑わしくなってくる。仕事の能力については異論もあろうが、ここではこれ以上立ち入らない。かわりに彼のスピリチュアルな側面について語ろう。

湯川曰く、彼は清朝末期の皇族の一人、愛新覺羅顯㺭(日本名・川島芳子)の生まれ変わりらしい。また、他の人には見えないものが見えてしまうなど、霊感も強いらしい。前世とか霊感とか、全く荒唐無稽な話だ。しかし、次のことは事実だ。彼がblogで綴った自分についての予見がその通りになっている。少なくとも三つの事柄について!

一つ目は、後藤健二氏とのこと。後藤氏との出会いは、湯川がISILに拘束される何ヶ月か前の2014 年4月であった。この時、湯川は自由シリア軍に拘束されていて、たまたまシリアに取材に来ていた後藤氏が自由シリア軍の幹部と交渉してくれたおかげで釈放された。後藤氏との出会いを湯川はblogに書いている。

僕の仕事はジャーナリストとの関係は絶対必要だと思っていたところに必然にもシリアで出会う事になった。そして初めて一緒に行動した。直感で感じたが、一生の友になるだろう。

「必然にもシリアで会うことになった」ジャーナリストとは後藤氏のこと。まさに、死をともにするほどの《一生の友》となってしまった。

二つ目は彼の仕事について。彼が民間軍事会社を立ち上げる少し前、これから始める仕事について、ぼやかしながらblogで語っていた。「proof of life」という映画を紹介し、これが自分が始めようとする仕事に関係がある、と書いている。映画のあらすじは次のとおり。

ーー南アメリカのとある国に赴任したダムの建築技師が反政府ゲリラに誘拐されてしまう。建築技師の所属する会社は社員が誘拐されたときの為に誘拐保険に加入していたため、保険会社は契約通り反政府ゲリラと人質解放交渉のため、元イギリス陸軍特殊部隊を現地に派遣する。交渉では救出できないと悟ったは元特殊部隊員は強行救出するーー

湯川は人質救出の仕事がしたかったのか…そして、この日のblogはこう締めくくられている。

僕が実際にこの様な救出する仕事をする事は無いかも知れないが、近い感じの出来事は、もしかすると有るかも知れない。

そう、映画にドンピシャなのことではなく、まさに《近い感じの出来事》が起きたわけだ。

 最後に自分の死期のこと。

僕は自分で短命で寿命が40歳代で死ぬのは知っていた。

こう自分の死について予見していた。実際、彼は42歳でこの世を去る。では、なぜそう思っていたのか?それは彼は自分が川島芳子の生まれ変わりだと信じていたことと関係がある。川島芳子は、清朝の皇族・第10代粛親王善耆の第十四王女としてこの世に生を受けるが、幼少期に日本人・川島浪速のところに養女に出されたため、芳子という日本名をもつ。

男装の麗人 川島芳子として生き、そして生まれ変わっても、同じ様な人生経験をしている。

 湯川はblogでこう書いていた。芳子は40歳で死去したので、現世でも同じくらいの寿命になると感じていたようだ。実は芳子の最期は壮絶で、戦後間もなく中華民国政府によって漢奸として逮捕され、処刑されたのである。湯川の言うとおり、最期までも《同じ様な人生経験》となった。

 

こう見てみると、湯川遥菜には本当にスピリチュアルな能力があるような気がしてくる。彼は、自分の死に直面したとき、それが運命だからと素直に受け入れたのだろうか?それとも、誰かを恨んだのだろうか?もし、彼に死へのレールをひいた人間がいるのであれば、気をつけたほうがいいかもしれない。