Kivy入門(version1系)

Kivy入門(version1系)

目次

1 概要

  • Pythonのライブラリ
  • クロスプラットフォームの開発環境
  • Kivy + buildozer で Androidアプリを作ってみる
  • 環境は Ubuntu version 20.04ベースで行う(Dockerを利用すれば、Dockerを利用できる他のプラットフォームでも同じ手順で行える)

2 関連リンク

2.1 使うかもしれないパッケージ

3 インストール

3.1 以下の操作を行っている動画

3.2 kivyのUbuntu20.04へのインストール手順

  • 手順の確認はDockerのUbuntu 20.04を利用した
  • 以下の手順で共有ディレクトリを作成し、Dockerは1000のuidのユーザーで行った
sudo mkdir /work/kivy
sudo chown 1000.1000 /work/kivy/
  • 起動は以下のコマンドで行った
docker run -it --rm -v /work/kivy:/home/ ubuntu:20.04 

3.3 手順

3.3.1 必要パッケージのインストール

apt update
apt install python3-kivy 
  • 一般ユーザーで以下を行う場合は 以下のように先頭に sudoをつける
sudo apt update
sudo apt install python3-kivy 

4 空のApp作成

4.1 以下の説明を行っている動画

4.2 空のApp作成手順

  • tutorial001.py というファイル名で以下内容のファイル作成
from kivy.app import App

class HelloWorldApp(App):
  pass

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

4.2.1 実行

python3 tutorial002_helloworld.py 

4.3 この章のまとめ

  • 空のアプリ作成

5 サンプル用のHello Worldプログラム作成(Label利用)

5.1 以下の説明を行っている動画

5.2 HelloWorld

  • tutorial002_helloworld.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label

class HelloWorldApp(App):

    def build(self):
        return Label(text='Hello World!')

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

5.2.1 実行

python3 tutorial002_helloworld.py 

5.3 この章のまとめ

  • Labelを利用して、Hello World作成

6 BoxLayout

6.1 以下の説明を行っている動画

6.3 BoxLayout利用

  • tutorial003_boxlayout.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout

class HelloWorldApp(App):
    def build(self):
        b = BoxLayout(orientation="vertical")
        l1 = Label(text='Hello',font_size=150)
        l2 = Label(text='World',font_size=150)

        b.add_widget(l1)
        b.add_widget(l2)
        return b

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

6.3.1 実行

python3 tutorial003_boxlayout.py

6.4 この章のまとめ

  • 部品を良い感じで並べてくれるツールの内BoxLayoutを使ってみた

7 Module: kivy.lang.builder

7.1 以下の説明を行っている動画

7.3 Builder 利用

  • tutorial004_builder.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

kv='''
BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Hello'
        font_size: 150
    Label:
        text: 'World'
        font_size: 150
'''

class HelloWorldApp(App):
    def build(self):
        return Builder.load_string(kv)

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

7.3.1 実行

python3 tutorial004_builder.py

7.4 この章のまとめ

  • builderを利用して、kivy言語を利用

8 Kivy言語の利用(外部ファイル)

8.1 以下の説明を行っている動画

8.3 Kivy言語外部ファイルを利用

8.3.1 tutorial005_kivy.py というファイル名で以下内容のファイル作成

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
#from kivy.uix.widget import Widget
#from kivy.lang.builder import Builder

class HelloWorld(BoxLayout):
  pass

class Tutorial005App(App):
    def build(self):
        return HelloWorld()

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

8.3.2 tutorial005.kv ファイルを以下の内容で作成

  • ファイル名はAppを継承したクラス名の最後のAppを除いた物が自動で検索される
  • 例 今回だと Tutorial005App から tutorial005.kv
  • 例 TutorialApp なら tutorial.kv
<HelloWorld>:
    orientation: 'vertical'
    Label:
	text: 'Hello'
	font_size: 150
    Label: 
	text: 'World'
	font_size: 150

8.3.3 実行

python3 tutorial005_builder.py

8.4 この章のまとめ

  • 外部ファイルで、kivy言語を利用

9 Module: kivy.uix.button

9.1 以下の説明を行っている動画

9.3 buttonを利用する手順例

9.3.1 tutorial006.py というファイル名で以下内容のファイル作成

  • on_release でボタン押して離した時にイベント発生する記述を行う
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

import random

kv='''
<HelloWorld>
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'Change Color'
        font_size: 80
        on_release: root.changeColor()
''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    def changeColor(self):
        print("changeColor")
        for key, val in self.ids.items():
            print("key={0}, val={1}".format(key, val))
        print(self.ids)
        mylabel=self.ids['label1']
        mylabel.color=[random.random(),random.random(),random.random(),1]

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

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

9.3.2 実行

  • Ubuntuでは pythonではなくpython3の必要あるケースあり
python tutorial006.py 

9.3.3 tutorial006-2.py というファイル名で以下内容のファイル作成

  • kivy言語側で、クリックイベントの処理記述
  • kivy言語側で、randomモジュール読み込み
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

import random

kv='''
#:import random random
<HelloWorld>
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'Change Color'
        font_size: 80
        on_release: root.ids['label1'].color=[random.random(),random.random(),random.random(),1]
''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

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

9.3.4 実行

  • Ubuntuでは pythonではなくpython3の必要あるケースあり
python tutorial006-2.py 

9.4 この章のまとめ

  • Module: kivy.uix.buttonを使ってみた
  • ボタンを押して離した時にイベント発生する処理を書いた

10 Module: kivy.uix.textinputを利用して足し算アプリ作成

10.1 以下の説明を行っている動画

10.3 Module: kivy.uix.textinputを利用して足し算アプリ作成 手順

10.3.1 tutorial007.py というファイル名で以下内容のファイル作成

  • input_filterで整数のみ入力可能にしてある
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.lang.builder import Builder

import random

# https://kivy.org/doc/stable/api-kivy.uix.textinput.html

kv='''
#:import random random
<HelloWorld>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 150
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 150
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 150
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))

''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

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

10.3.2 実行

python3 tutorial007.py 

10.4 この章のまとめ

  • Module: kivy.uix.textinputの基本的な使い方紹介
  • Module: kivy.uix.textinputを利用して足し算アプリ作成

11 設定を行う機能

11.1 以下の説明を行っている動画

11.3 設定を行う機能の利用手順

11.3.1 tutorial008.py というファイル名で以下内容のファイル作成

  • ホームディレクトリの .kivy/config.ini というファイルが設定を変更すると更新される
  • app.open_settings() でセッティング画面が表示される
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.lang.builder import Builder

import random

kv='''
#:import random random
<MyAdd>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 100
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 100
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 100
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
    Button:
        text: 'setting'
        font_size: 80
        on_release: app.open_settings()
''' 

Builder.load_string(kv)

class MyAdd(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return MyAdd()
        #return Builder.load_string(kv)

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

11.3.2 実行

python3 tutorial008.py

11.3.3 tutorial008-2.py というファイル名で以下内容のファイル作成

  • ホームディレクトリの .kivy/config.ini というファイルが設定を変更すると更新される
  • app.open_settings() でセッティング画面が表示される
  • self.settings_cls=SettingsWithSidebar を追加すると横にメニューが追加
  • self.use_kivy_settings=False の行の#を外して有効化すると、元々のメニューは選択できなくなる
  • 独自メニュー追加
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.settings import SettingsWithSidebar
from kivy.lang.builder import Builder

import json
import random

Builder.load_string('''
#:import random random
<MyAdd>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 100
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 100
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 100
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
    Button:
        text: 'setting'
        font_size: 80
        on_release: app.open_settings()
''')

settings_json=json.dumps([
    {'type': 'title', 'title': 'example title'},
    {'type': 'bool', 'title': 'a boolean setting', 'desc': 'Boolean description text', 'section':'example', 'key':'boolexample'},
    {'type': 'numeric', 'title': 'a numerical setting', 'desc': 'Numeric description text', 'section':'example', 'key':'numericalexample'},
    {'type': 'options', 'title': 'a options setting', 'desc': 'Option description text', 'section':'example', 'key':'optionsexample', 'options':['1','2','3']},
    {'type': 'string', 'title': 'a string setting', 'desc': 'String description text', 'section':'example', 'key':'stringexample'},
    {'type': 'path', 'title': 'a path setting', 'desc': 'Path description text', 'section':'example', 'key':'pathexample'},
    ])

class MyAdd(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        self.settings_cls=SettingsWithSidebar
        # self.use_kivy_settings=False
        setting1 = self.config.get('example', 'optionsexample')
        print(self.config.items('example'))
        return MyAdd()
        #return Builder.load_string(kv)

    def build_config(self, config):
        config.setdefaults('example', {
            'boolexample':True,
            'numericalexample':1,
            'optionsexample':'3',
            'stringexample':'abc',
            'pathexample':'./',
            })

    def build_settings(self, settings):
        settings.add_json_panel('test', self.config, data=settings_json)

    def on_config_change(self, config, section, key, value):
        print([config, section, key, value])

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

11.3.4 実行

python3 tutorial008-2.py

11.4 この章のまとめ

  • ベースはCrash Courseの13番目の動画を参考に作成
  • 設定関係の説明を行った
  • 独自メニューの追加方法も紹介

12 スクリーンマネジャー(画面切替)

12.1 以下の説明を行っている動画

12.3 スクリーンマネジャー(画面切替) 手順

12.3.1 tutorial009.py というファイル名で以下内容のファイル作成

  • スクリーンマネジャーはScreenManagerを継承
  • 切り替える画面はScreenを継承
  • クラスの定義はkivy言語の読み込み前に行わないとエラーになっていた
  • kivy.uix.screenmanager.FadeTransitionをkivy言語側でインポート
  • transition: FadeTransition() の 先頭の#をはずすと、画面切替の様子が変更になる
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.settings import SettingsWithSidebar
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

import json
import random

class MyScreenManager(ScreenManager):
    pass

class MyAdd(Screen):
    pass

class MySub(Screen):
    pass

root_widget = Builder.load_string('''
#:import random random
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

MyScreenManager:
    #transition: FadeTransition()
    MyAdd:
    MySub:

<MyAdd>
    name : 'MyAdd'
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: textinput1
            font_size: 100
            input_filter: 'int'
            text: '1'
        TextInput:
            id: textinput2
            font_size: 100
            input_filter: 'int'
            text: '1'
        Label:
            id: label1
            text: ''
            font_size: 100
        Button:
            text: 'calc add'
            font_size: 80
            on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
        Button:
            text: 'setting'
            font_size: 80
            on_release: app.open_settings()
        Button:
            text: 'go to sub'
            font_size: 80
            on_release: app.root.current = 'MySub'
<MySub>
    name : 'MySub'
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: textinput1
            font_size: 100
            input_filter: 'int'
            text: '1'
        TextInput:
            id: textinput2
            font_size: 100
            input_filter: 'int'
            text: '1'
        Label:
            id: label1
            text: ''
            font_size: 100
        Button:
            text: 'calc sub'
            font_size: 80
            on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)-int(root.ids['textinput2'].text))
        Button:
            text: 'setting'
            font_size: 80
            on_release: app.open_settings()
        Button:
            text: 'go to add'
            font_size: 80
            on_release: app.root.current = 'MyAdd'
''')

# ここで定義するとエラーに
#class MyScreenManager(ScreenManager):
#    pass
#
#class MyAdd(Screen):
#    pass
#
#class MySub(Screen):
#    pass
#

settings_json=json.dumps([
    {'type': 'title', 'title': 'example title'},
    {'type': 'bool', 'title': 'a boolean setting', 'desc': 'Boolean description text', 'section':'example', 'key':'boolexample'},
    {'type': 'numeric', 'title': 'a numerical setting', 'desc': 'Numeric description text', 'section':'example', 'key':'numericalexample'},
    {'type': 'options', 'title': 'a options setting', 'desc': 'Option description text', 'section':'example', 'key':'optionsexample', 'options':['1','2','3']},
    {'type': 'string', 'title': 'a string setting', 'desc': 'String description text', 'section':'example', 'key':'stringexample'},
    {'type': 'path', 'title': 'a path setting', 'desc': 'Path description text', 'section':'example', 'key':'pathexample'},
    ])


class HelloWorldApp(App):
    def build(self):
        self.settings_cls=SettingsWithSidebar
        self.use_kivy_settings=False
        setting1 = self.config.get('example', 'optionsexample')
        print(self.config.items('example'))
        return root_widget
        #return Builder.load_string(kv)

    def build_config(self, config):
        config.setdefaults('example', {
            'boolexample':True,
            'numericalexample':1,
            'optionsexample':'3',
            'stringexample':'abc',
            'pathexample':'./',
            })

    def build_settings(self, settings):
        settings.add_json_panel('test', self.config, data=settings_json)

    def on_config_change(self, config, section, key, value):
        print([config, section, key, value])

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

12.3.2 実行

python3 tutorial009.py

12.4 この章のまとめ

13 今後

  • 今後も文書追加していきます。

14 この文書のチェンジログ

  • 2020/08/13 初版
  • 2020/08/14 Module: kivy.lang.builder の章, Module: kivy.lang.builderの章, Kivy言語の利用(外部ファイル) の章追加
  • 2020/08/14 Module: kivy.uix.buttonの章, Module: kivy.uix.textinputを利用して足し算アプリ作成 の章, 設定を行う機能 の章, スクリーンマネジャー(画面切替) の章追加

著者: NM Max

Created: 2020-08-14 金 19:25

Validate

Kivy と buildozer で スマホアプリ作成

Kivy と buildozer で スマホアプリ作成

目次

1 概要

  • Android純正の開発環境重すぎ
  • クロスプラットフォームの開発環境で作りたい(ソースの使い回し)
  • ということで、これができる開発環境の一つである、Kivy + buildozer で Androidアプリを作ってみる
  • 環境は Ubuntu version 20.04ベースで行う(Dockerを利用すれば、Dockerを利用できる他のプラットフォームでも同じ手順で行える)

2 リンク

3 Ubuntuでコンパイル

3.1 以下の操作を行っている動画



3.2 buildozerのUbuntu20.04へのインストール手順

  • 手順の確認はDockerのUbuntu 20.04を利用した
  • 以下の手順で共有ディレクトリを作成し、Dockerは1000のuidのユーザーで行った
sudo mkdir /work/kivy
sudo chown 1000.1000 /work/kivy/
  • 起動は以下のコマンドで行った
docker run -it --rm -v /work/kivy:/home/ ubuntu:20.04 

3.3 手順

3.3.1 必要パッケージのインストール

apt update
apt install sudo python3-kivy python3-pip python3-virtualenv vim default-jdk zlib1g-dev
apt install -y sudo vim git aidl ffmpeg python3 automake autoconf libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev libltdl-dev libssl-dev lld clang lldb zip unar unzip
  • 一般ユーザーで以下を行う場合は 以下のように先頭に sudoをつける
sudo apt update
sudo apt install sudo python3-kivy python3-pip python3-virtualenv vim default-jdk zlib1g-dev
sudo apt install -y sudo vim git aidl ffmpeg python3 automake autoconf libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev libltdl-dev libssl-dev lld clang lldb zip unar unzip

3.3.2 一般ユーザー追加

  • これは通常のUbuntuでは不要、Dockerで行っていて、操作を一般ユーザーで行いたいときに、以下の手順を実行
  • この例ではユーザー名はyoutubeとしている
  • 通常のUbuntu 20.04の場合はこの手順は恐らく不要
adduser youtube
  1. 追加した一般ユーザーがsudo使えるようにする(これは特に必要ない手順)
    • これは通常のUbuntuでは不要、Dockerで行っていて、操作を一般ユーザーで行いたいときに、以下の手順を実行
    • この例ではユーザー名はyoutubeとしている
    adduser youtube sudo
    

3.3.3 virtual環境で実行

  • ここでは kivy_buildozer ディレクトリで行う
virtualenv  --no-packaging  kivy_buildozer
cd kivy_buildozer
source bin/activate

3.3.4 git で管理できるようにしとく

  • ユーザー名と、メールアドレスは、自分にあわせてください。ここでは”Your Name”, “you@example.com”としてます。
git init
git add -A
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
git commit -m "first"

3.3.5 必要なPythonパッケージのインストール

pip3 install Cython
pip3 install buildozer

3.3.6 自分のプロジェクト用のディレクトリ作成

mkdir app
cd app
mkdir test001
cd test001/

3.3.7 サンプル用のHello Worldプログラム作成

  • main.py というファイル名で以下内容のファイル作成
import kivy

from kivy.app import App
from kivy.uix.label import Label

class HelloWorldApp(App):

    def build(self):
        return Label(text='Hello World!')

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

3.3.8 Android用のapkファイル作成

  • bin ディレクトリにエラーがなければ、apkファイルが作成されます
buildozer init
buildozer android debug deploy run
  • 実行中にAndroid用のライセンス表示されるので、yを入力しエンターを押す必要があるケースあり

3.4 この章のまとめ

  • Ubuntu 20.04に kivy+buildozerを利用したスマホアプリ開発環境インストールし、Androidアプリを作成
  • Dockerを利用すれば、同じ手順で環境構築と、Androidアプリ作成可能

4 Kivy+buildozer関連リンク

  • 開発ツール関係文書

4.1 以下の説明を行っている動画

4.3 使うかもしれないパッケージ

5 Kivy Launcherの使い方

5.1 以下の説明を行っている動画

5.3 概要

  • Androidにkivy Luncherをインストール
  • adbコマンドで db push kivy/ storage/sdcard0 で kivyディレクトリ以下のプロジェクトファイルをコピー(storage/emulated/0/kivy 以下にプロジェクトディレクトリを準備)
  • プロジェクトはディレクトリにまとめて、android.txtファイルを準備(以下が例)
    • title にアプリの名前
    • author に作者名
    • orientation に画面の方向
title=accelerometer_basic
author=plyer example
orientation=portrait

5.4 実際の手順

  • Android端末(スマホ)に、kivy Launcherをインストール(Google Playストア)
  • Androidの端末でUSBデバッグ可能に設定(ファイル転送にadbコマンドを使う場合 Ubuntuでadbパッケージ)
    • Androidの設定を起動
      • システム→端末情報を開き、一番下の「ビルド番号」を何度もタップ(7から8回)すると、開発者むけオプションが有効になる
      • システムに戻ると、「開発者向けオプション」ができてるので、それをタップ、「USBデバッグ」を有効に変更
  • adbコマンド等で、/storage/emulated/0/kivy/ディレクトリ以下にプロジェクトファイルをコピー

5.4.1 kivyソースに含まれるサンプルをコピー

  • コピーするプロジェクトがはいっているディレクトリを用意
mkdir kivy
  • ソースをゲットするディレクトリを作成し、そのディレクトリに移動(使い慣れたツールでやってもOK)
mkdir github
cd github
  • kivy,plyerのソースをgitコマンドでコピー(ダウンロードして展開してもOK)
git clone https://github.com/kivy/kivy.git
git clone https://github.com/kivy/plyer.git
  • ソースに含まれているAndroid用サンプルを、一つしたのディレクトリのkivyディレクトリにコピー
cp -r kivy/examples/settings/ ../kivy/
cp -r kivy/examples/demo/showcase/ ../kivy/
cp -r kivy/examples/demo/pictures/ ../kivy/
cp -r kivy/examples/demo/touchtracer/ ../kivy/
cp -r kivy/examples/widgets/sequenced_images/ ../kivy/
cp -r kivy/examples/keyboard/ ../kivy/
cp -r kivy/examples/android/takepicture/ ../kivy/
cp -r kivy/examples/android/compass/ ../kivy/
cp -r plyer/examples/accelerometer/basic/ ../kivy/accelerometer_basic/
  • accelerometer_basic用のandroid.txtがないので追加 ( ../kivy/accelerometer_basic/android.txt )
title=accelerometer_basic
author=plyer example
orientation=portrait
  • PCとAndroidをUSBケーブルで接続
  • adbコマンドでAndroidにコピー
adb push ../kivy/ /storage/emulated/0/
  • android側でKivy Launcher起動
  • 動かしたいのを選択して起動

5.5 Kivy Launcherの使い方のまとめ

  • Kivy Launcher でapk作成せずに、手軽に効率良く、android本体で動作テストする手順
  • temuxとか、sl4aとか、QPython等があるが、色々なパッケージとの連携を行いながら、しかもapkパッケージ化が難しく、kivy Launcherが良さげ
  • 次の章で、Google Playストアで配布されているKivy Launcherには含まれていないplyerを含んだ、Kivy Launcherをビルドする

6 plyer入りのKivy Launcherの作成とインストール(好きなパッケージ入りのKivy Launcherの作り方)

6.1 以下の説明を行っている動画



6.2 関連文書

6.3 カスタマイズした、Kivy Launcherの作成手順

6.3.1 ソースゲット

git clone https://github.com/kivy/kivy-launcher.git

6.3.2 buildozer.specの requirements = kivy, androidの後に追加したパッケージを記述

  • plyer, python3, pyjniusを追加
...省略
requirements = kivy, android, plyer, python3, pyjnius
...省略

6.3.3 ビルドインストール

  • Androidを開発モードにして、USBデバッグ可能にしてから、PCとUSB接続
  • 以下のコマンドで、「Ubuntuでコンパイル」の章の https://www.youtube.com/embed/-xUmhSMK4Jk で作成した環境にはいる
source ~/kivy_buildozer/bin/activate
  • それから、以下のコマンドを実行
buildozer android debug deploy

6.4 この章のまとめ

  • Kivy Launcherをカスタマイズして、plyerのパッケージが必要なソースを動くようにしてみた

7 plyer関係の機能の利用方法の調べ方

  • exampleをメインで、関係文書を元に調べると、使い方を効率的に調べれそう

7.1 以下の説明を行っている動画

7.2 関係文書

7.3 手順

  • ソースに含まれるサンプルコードを調べれば使い方だいたいわかる。(あと公式文書、ソースも)
  • plyerのソースをgitコマンドでコピー(ダウンロードして展開してもOK)
git clone https://github.com/kivy/plyer.git
  • plyer/examples/ディレクトリ内に多数サンプルある
  • android用のバーチャル環境にはいり、apk生成出来る環境に
source ~/kivy_buildozer/bin/activate
  • buildozer.specファイルあるものは、そのディレクトリに移動し、以下のコマンドで、コンパイル、転送、実行
buildozer android debug deploy run
  • 一部のサンプルは動かないものもあった(Androidの機種によって、そのセンサーはいってないとか)
  • gpsサンプルは、simがはいっていて、位置情報の詳細がオン設定になっていないと動作しなかった(GPSじゃなくて、ネットで位置を調べているように感じた)

7.4 サンプルディレクトリ

  • accelerometer/basic/ 加速度計 こっちは正常動作
  • accelerometer/using_graph/ 加速度計 こっちは動かなかった
  • audio/ ファイルのパーミッション変更が必要
  • barometer/ 気圧計(F1 Playには気圧計ないみたい、Pixcel3aXLでは正常動作)
  • battery/ バッテリー関係
  • bluetooth/ 未チェック
  • brightness/ 起動できず
  • call/ 未チェック
  • camera/ 動作せず
  • compass/ コンパス(方位磁石) 起動できず
  • email/ eメイル,未チェック
  • filechooser/ ファイル選択
  • flash/ 未チェック
  • gps/ gps関係、gpsの電波がないところでも動作しており、simカードがないとエラーになっていた、基地局利用の位置情報?
  • gravity/ 重力
  • gyroscope/ ジャイロスコープ
  • humidity/ 湿度,未チェックorコンパイル時にエラー
  • light/ 明るさセンサー
  • notification/ 通知
  • orientation/ 向き?
  • proximity/ 近接?,enableでダウン
  • screenshot/ スクショ? buildozer.specがないため未チェック
  • sms/ SMS関係
  • spatialorientation/ 空間定位
  • speech2text/ 動作させたがスタートおしてもすぐに止まる、マイクの権限与えてもダメ
  • storagepath/ ストレージのパス
  • temperature/ 気温?、動作せず
  • text2speech/ 文字を発音、文字化けしてた
  • uniqueid/ ユニークなID取得
  • vibrator/ バイブ
  • wifi/ 未チェック

7.4.1 コンパイルして、次々とインストールする場合

  • Android端末をUSB接続して、plyer/exampleディレクトリにはいって、以下のコマンドを実行
cd accelerometer/basic/  ; buildozer android debug deploy run; cd ../..
cd accelerometer/using_graph/ ; buildozer android debug deploy run; cd ../..
cd audio/ ; buildozer android debug deploy run; cd ..
cd barometer/ ; buildozer android debug deploy run; cd ..
cd battery/ ; buildozer android debug deploy run; cd ..
cd bluetooth/ ; buildozer android debug deploy run; cd ..
cd brightness/ ; buildozer android debug deploy run; cd ..
cd call/ ; buildozer android debug deploy run; cd ..
cd compass/ ; buildozer android debug deploy run; cd ..
cd email/ ; buildozer android debug deploy run; cd ..
cd flash/ ; buildozer android debug deploy run; cd ..
cd gps/ ; buildozer android debug deploy run; cd ..
cd gravity/ ; buildozer android debug deploy run; cd ..
cd gyroscope/ ; buildozer android debug deploy run; cd ..
cd humidity/ ; buildozer android debug deploy run; cd ..
cd light/ ; buildozer android debug deploy run; cd ..
cd notification/ ; buildozer android debug deploy run; cd ..
cd orientation/ ; buildozer android debug deploy run; cd ..
cd proximity/ ; buildozer android debug deploy run; cd ..
cd sms/ ; buildozer android debug deploy run; cd ..
cd spatialorientation/ ; buildozer android debug deploy run; cd ..
cd speech2text/ ; buildozer android debug deploy run; cd ..
cd storagepath/ ; buildozer android debug deploy run; cd ..
cd temperature/ ; buildozer android debug deploy run; cd ..
cd text2speech/ ; buildozer android debug deploy run; cd ..
cd uniqueid/ ; buildozer android debug deploy run; cd ..
cd vibrator/ ; buildozer android debug deploy run; cd ..

7.5 Androidの特殊機能を利用する方法

7.5.1 pyler利用

  • クロスプラットフォームのソースになる
  • しかしiOSでサポートされていない機能多い

7.5.2 Pyjnius等を利用して、PythonからJavaを利用

  • Androidの開発ツールのライブラリを利用できる
  • 情報少ない

7.5.3 import Androidで利用

  • 情報少ない(あまり文書をみつけれてない、みつけたらまたリンクはっときます)

7.6 この章のまとめ

  • スマホ固有の機能の動作させるライブラリplyer関係の使い方の調べ方紹介
  • かたっぱしからコンパイルしてインストールすると相当時間かかるが、ソースみるまえに動作させた方がわかりやすい
  • exampleをメインで、関係文書を元に調べると、使い方を効率的に調べれそう
  • 全部コンパイルすると、30-40Gの容量が必要

8 広告

8.1 以下の説明を行っている動画



8.2 使えそうなパッケージ

8.2.2 手順

  • 以下の手順で(Ubuntuでコンパイルhttps://www.youtube.com/embed/EF0PNSlblYYの手順をDocker内のUbuntuではなく、通常のUbuntuで行って構築した環境)apkを作成できる環境に移行
source ~/kivy_buildozer/bin/activate
  • KivMod Github https://github.com/MichaelStott/KivMobの記述どうりの手順で行う(INTERSTITIALタイプ、全画面タイプで広告表示)
  • package.domain部分がorg.testのままだと、広告が表示されないので、org.kivyなどorg.test以外に変更
  • 以下のコマンドでインストール実行
buildozer android debug deploy run
  • KivMob Tutorial http://kivmob.com/tutorials.htmlにあるBannerタイプとか、Rewarded Videoタイプ(広告のかわりに、なにかユーザーにプレゼントするタイプ)とかもコンパイルして実行する

8.3 この章のまとめ

  • KivModを利用すると、GoogleのAdMobを利用して簡単に色々なタイプの広告を表示可能

9 課金

9.1 以下の説明を行っている動画

10 KivyMD

  • ナイスなルックスで、豊富な部品があるライブラリ
  • Kivy純正の部品よりも、KivyMDの部品で作成した方がルックス良いアプリ作成簡単にできそう

10.1 以下の説明を行っている動画

10.3 install (Ubuntu ユーザースペース)

  • pip install kivymd==0.104.1 をしろとGitHubに書いてあるが、以下でも同じバージョンがはいった(2020/08/21)
pip3 install kivymd
  • その時のアウトプット
Collecting kivymd
  Using cached kivymd-0.104.1-py3-none-any.whl (2.4 MB)
Requirement already satisfied: kivy in /usr/lib/python3/dist-packages (from kivymd) (1.10.1)
Requirement already satisfied: pillow in /usr/lib/python3/dist-packages (from kivymd) (7.0.0)
Requirement already satisfied: requests in /usr/lib/python3/dist-packages (from kivymd) (2.22.0)
Installing collected packages: kivymd
Successfully installed kivymd-0.104.1

10.4 pkg作成時にKivyMDを利用する

  • buildozer.specのrequestsにkivymdを追加

10.5 デモのコンパイルと実行

  • KivyMDのソースゲット
git clone https://github.com/kivymd/KivyMD.git
  • 取ったソースのバックアップ(20200821にゲットしたので、その日付をつけた、KivyMD.20200821.tgz を作成)
tar cvzf KivyMD.20200821.tgz KivyMD/
  • 前作成したapk作成環境に移行(virtualenvで作成した環境にはいる)
source ~/kivy_buildozer/bin/activate
  • AndroidをUSBケーブルでPCと接続
  • デモのあるディレクトリに移動し、コンパイル実行
cd KivyMD/demos/kitchen_sink/
buildozer android debug deploy run

10.6 各部品の使い方の調べ方

  • 上の文書のリンクと、動かしたサンプルソースのソースを調べれば、簡単に使い方を調べることが可能
  • 使う部品は

10.7 この章のまとめ

  • ルックスの良いKivyMDを紹介
  • デフォルトのKivyの部品よりもKivyMDの部品を使うべき
  • 動画では、サンプルの動作の様子も紹介

11 デバッグ手法いくつか紹介

11.1 以下の説明を行っている動画

11.3 手順

  • USBデバッグを可能にしたAndroid実機とPC接続
  • ソースにprint文とかlogging文をいれる
  • 特殊な文字列をいれとくと後で検索しやすくなる
  • 確認したい行の前後にいれるとかも良い
  • そこを通過してるかの確認にも使える
  • 変数の値のチェックにも便利
  • 以下はLoggerを使っているが、print文でもログに出る
from kivy.logger import Logger
... 省略
Logger.info('#####情報#####')
  • テストしたい動作の手前で以下を実行し、ログを適当なファイル名で保存(下の例だとlog001.txt)
adb logcat > log001.txt 2>&1
  • 以下にしとくと画面にも表示しながらファイルに保存
adb logcat 2>&1 | tee log001.txt

11.4 バグの例

  • org.renpy.android.PythonActivity’がみつからない例
08-22 21:10:02.938 30206 30239 I python  :  jnius.jnius.JavaException: Class not found b'org/renpy/android/PythonActivity'
  • 特殊文字をいれてわかりやすくした例
........... 省略
08-23 15:20:12.353 15129 15161 I python  : [INFO   ] #####before vibrate#####
08-23 15:20:12.353 15129 15161 I python  : [INFO   ] [Base        ] Leaving application in progress...
........... 省略
08-23 15:20:12.357 15129 15161 I python  :    File "/storage/emulated/0/kivy/vibrate02/main.py", line 56, in vibrate
08-23 15:20:12.357 15129 15161 I python  :      jvibrator.vibrate(1000)
08-23 15:20:12.358 15129 15161 I python  :    File "jnius/jnius_export_class.pxi", line 745, in jnius.jnius.JavaMethod.__call__
08-23 15:20:12.358 15129 15161 I python  :  jnius.jnius.JavaException: Invalid call, number of argument mismatch, got 1 need 4
08-23 15:20:12.358 15129 15161 I python  : Python for android ended.
........... 省略

11.5 この章について

  • 低次元のデバッグ方法の一種を紹介

12 Kivy Launcherの拡張その2

12.1 以下の説明を行っている動画

12.2 関係動画

12.3 関係ソース

12.4 以下のようにKivy Launcherのbuildozer.specのrequestsを追加

  • opencv関係や、sympy関係もいれたかったが、現状のバージョンだと、エラーになる、配布元でのデバッグ終わったら入れるべき
requirements = kivy, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas

12.5 KivMobhttps://github.com/MichaelStott/KivMobのサンプル用の修正を行う(buildozer.spec)

12.6 この章のまとめ

  • これによってかなりのものを実際にapkファイルを作成することなく、Kivy Launcherで動作確認可能になる
  • 広告関係のサンプルも、Kivy Launcherでテスト可能に

13 pyjniusを使って、java経由でAndroid特有の機能の利用

13.1 以下の説明を行っている動画

13.3 バイブを行ってみた

13.3.1 まずは、pyjniusをつかわず、plyerを使って、バイブできるのを作った

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from plyer import vibrator
Builder.load_string('''
#:import vibrator plyer.vibrator
<My>:
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'vibrate'
        font_size: 80
        on_release: vibrator.vibrate(5)
''')

class My(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return My()

if __name__ == '__main__':
    HelloWorldApp().run()
  • android.txtが以下(3行にすること)
title=Vibrate 001 android.vibrate
author=NM Max
orientation=portrait

13.3.2 pyjniusを使うバージョン

  • https://kivy.org/doc/stable/guide/android.html の断片ソースを利用してやろうとしたら酷い目にあった
    • バージョンが新しいとこのソース動かない
    • org.renpy.android.PythonActivity は org.kivy.android.PythonActivity になってた
      • 前の前の章のデバッグ手法で気づいた org.renpy.android.PythonActivity でつまづいていることに
    • そこらもプログラムで取得可能なようで、plyerのソースを参考に変更した
    • Androidの開発環境のVibrator関係も変更になっていて、vibrate関数の使用が変更となり、VibrationEffectを利用するようになってた
  • plyerのソースの plyer/platforms/android/__init__.py と、plyer/platforms/android/vibrator.pyを参考に作成
  • そうして改造したのが以下 main.py
from os import environ
from jnius import autoclass, cast

try:
    from android import config
    ns = config.JAVA_NAMESPACE
except (ImportError, AttributeError):
    ns = 'org.renpy.android'
PythonActivity = autoclass(ns + '.PythonActivity')
activity = PythonActivity.mActivity

ANDROID_VERSION = autoclass('android.os.Build$VERSION')
SDK_INT = ANDROID_VERSION.SDK_INT

Context = autoclass("android.content.Context")
vibrator_service = activity.getSystemService(Context.VIBRATOR_SERVICE)
vibrator = cast("android.os.Vibrator", vibrator_service)
if SDK_INT >= 26:
    VibrationEffect = autoclass("android.os.VibrationEffect")

from kivy.logger import Logger
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

Builder.load_string('''
<My>:
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'vibrate'
        font_size: 80
        on_release: root.vibrate(5)
''')

class My(BoxLayout):
    def vibrate(self,x):
        Logger.info('#####before vibrate#####')
        if vibrator:
            if SDK_INT >= 26:
                vibrator.vibrate(VibrationEffect.createOneShot(int(1000 * x), VibrationEffect.DEFAULT_AMPLITUDE))
            else:
                vibrator.vibrate(int(1000 * x))
        Logger.info('#####after vibrate#####')

class HelloWorldApp(App):
    def build(self):
        return My()

if __name__ == '__main__':
    HelloWorldApp().run()
  • android.txtが以下(3行にすること) Kivy Launcher用
title=Vibrate 002 pyjnius.vibrate
author=NM Max
orientation=portrait
  • ( buildozer initしたのち)buildozer.specの変更内容
    • title
      • title = My Application を title = Pyjnius vibrator test に修正
    • requirements
      • requirements = python3,kivy を requirements = python3,kivy,pyjnius,plyer に修正
    • android.permissions = INTERNET, VIBRATE を追加
    • buildozer android debug deploy run すれば、USB接続してあるUSBデバッグオンになっているandroidにインストールされ、実行される(binディレクト以下にapkファイルも生成される)

13.4 この章のまとめ

  • 公式の文書に古い記述があり、新しいバージョンでは動かないものも多い
  • plyerやpython-for-androidのソースを参考にすると効率良く動くものをつくれる
  • Kivy用に用意されていないもので、Android用に用意されているJavaライブラリを、pyjniusを使えるようになることで、利用可能になった

14 Kivy Launcherの拡張その3

14.1 以下の説明を行っている動画

14.2 関係文書

14.3 関係動画

14.4 関係ソース

14.5 Kivy Launcherカスタマイズ3の手順

14.5.1 現状(2020/08/28時点)でbuildozerでKivy Gardenを入れる為の手順の説明ありhttps://stackoverflow.com/questions/62260608/kivy-garden-mapview-deploying-error-with-buildozer

  • ~/kivy_buildozer/にvirturlenvで環境作った場合、~/kivy_buildozer/lib/python3.8/site-packages/buildozer/__init__.pyを修正
    • Kivy Gardenのバージョンを0.1.1から0.1.4に変更
self.cmd('pip install Kivy-Garden==0.1.1', env=self.env_venv)
を
self.cmd('pip install Kivy-Garden==0.1.4', env=self.env_venv)
に修正

14.5.2 Kivy Launcherのbuildozer.specのrequirementsを以下に修正

  • ベースは Kivy Launcherのカスタマイズ手順2 https://www.youtube.com/watch?v=Fd4jX-RJ9es の動画でおこなった修正後のファイルに以下の修正を行う
  • pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna を追加している
    • pygame はPython用のゲームエンジンの一つ
    • matplotlib はプロット用
    • websocket-client は多分ウェッブ系の部品だと思われる
    • snappy は Python bindings for the snappy compression library from Google.らしい
    • requests,certifi,urllib3,chardet,idna
      • requestsは adb logcat で確認したら無いってエラーが出てた、それ以外にも必要なパッケージあるかもしれないので、以下を参考にそれ以下も入れた
      • FarmersMarketFinderTutorial動画のソースhttps://github.com/Dirk-Sandberg/FarmersMarketFinderTutorialで入れられていたパッケージ
requirements = kivy, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas, pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna
  • 本当はOpenCV関係や、Sympy関係も入れたいが、まだ入れれてない

14.5.3 Kivy Launcherのbuildozer.specのgarden_requirementsを以下に修正

  • 沢山あるが、とりあえず、2つ入れた、他にも試したいのあれば、入れてOKう
garden_requirements = matplotlib, mapview

14.5.4 Kivy Launcher ビルドインストール

  • Kivy Launcherのカスタマイズ手順 https://www.youtube.com/watch?v=YyYNBL0VtdM の手順のビルドインストールコマンド実行部分と同じ(設定ファイルの変更はこのリンクの動画ではなく、上の修正を行う)
  • Androidを開発モードにして、USBデバッグ可能にしてから、PCとUSB接続
  • 以下のコマンドで、「Ubuntuでコンパイル」の章の https://www.youtube.com/embed/-xUmhSMK4Jk で作成した環境にはいる
source ~/kivy_buildozer/bin/activate
  • それから、以下のコマンドを実行
buildozer android debug deploy

14.5.5 mapviewEx02ディレクトリを作成し、必要なandroid.txtとmain.pyをいれる

./mapviewEx02/
├── android.txt
└── main.py

14.5.6 android.txtの中身

  • Kivy Launcher用のファイル
title=MapViewEx02
author=NM Max
orientation=portrait

14.5.7 Kivy Gardenのmapviewのexampleのmap_browser.pyを改造し、main.pyとして以下のようにmapviewEx02ディレクトリに入れる

  • 修正箇所は、Pythonの検索パスに、gardenのmapviewを入れるように設定(ファイルの前半部分)
  • 東京駅の座標を入れ、東京のボタンも増やした
  • スマホだとちょっと文字が大きすぎて崩れていたが、とりあえず放置
  • mainのファイルの変数を、kv言語側にもっていくには、#:import MapSource main.MapSource こういう感じでやれば良いらしい
    • ネットをうろうろしていた時に見つけたサイトで知ったのだが、URLをメモしておらず、URLわからない、英語のサイトだった
import sys
import os
print("########")
print(sys.path)
print("########")
#sys.path.append(os.path.join(os.path.dirname(__file__), 'libs/garden/garden.mapview'))
sys.path.append('./libs/garden/garden.mapview')
print("########")
print(sys.path)
print("########")
print(os.listdir(path='.'))
print("########")
from kivy.base import runTouchApp
from kivy.lang import Builder
from mapview import MapSource

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

#:import MapSource __main__.MapSource
root = Builder.load_string("""
#:import MapSource mapview.MapSource

<Toolbar@BoxLayout>:
    size_hint_y: None
    height: '48dp'
    padding: '4dp'
    spacing: '4dp'

    canvas:
        Color:
            rgba: .2, .2, .2, .6
        Rectangle:
            pos: self.pos
            size: self.size

<ShadedLabel@Label>:
    size: self.texture_size
    canvas.before:
        Color:
            rgba: .2, .2, .2, .6
        Rectangle:
            pos: self.pos
            size: self.size

RelativeLayout:

    MapView:
        id: mapview
        lat: 50.6394
        lon: 3.057
        zoom: 8
        #size_hint: .5, .5
        #pos_hint: {"x": .25, "y": .25}

        #on_map_relocated: mapview2.sync_to(self)
        #on_map_relocated: mapview3.sync_to(self)

        MapMarker:
            lat: 50.6394
            lon: 3.057

        MapMarker
            lat: -33.867
            lon: 151.206

        MapMarker
            lat: 35.6809591
            lon: 139.7673068

    Toolbar:
        top: root.top
        Button:
            text: "Move to Lille, France"
            on_release: mapview.center_on(50.6394, 3.057)
        Button:
            text: "Move to Sydney, Autralia"
            on_release: mapview.center_on(-33.867, 151.206)
        Button:
            text: "Move to Tokyo, Japan"
            on_release: mapview.center_on(35.6809591, 139.7673068)
        Spinner:
            text: "mapnik"
            values: MapSource.providers.keys()
            on_text: mapview.map_source = self.text

    Toolbar:
        Label:
            text: "Longitude: {}".format(mapview.lon)
        Label:
            text: "Latitude: {}".format(mapview.lat)
    """)

runTouchApp(root)

14.5.8 Kivy Launcher が読み取れるディレクトリに、作ったファイルをコピー(adbコマンドを利用してPCからAndroidにコピー, AndroidとPCはUSB接続し、AndroidはUSBデバッグ可能な設定済み)

  • mapviewEx02/ディレクトリ内にいるなら、以下のコマンドでOK
adb push ../mapviewEx02/ /storage/emulated/0/kivy/
  • 後は起動して、MapViewEx02を選択肢から選択して、起動すればOK

14.6 この章のまとめ

  • Kivy Gardenを使いたくて、非常に苦労して成功した時の手順説明
  • Kivy Garden mapview 素晴らしすぎる
  • 地図を表示するアプリを簡単に作れるようになった
  • Pythonの検索パスの変更方法や、Androidパッケージ内部での検索パスの調べ方を知った
    • Kivy Launcher のビルドディレクトリの .buildozer/android/app/ 内にパッケージ化するファイル群がある
    • 本来検索パスの設定変更無しにいけるはずだが、その方法まだわかっておらず。知ってる方いたら、教えて下さい。

15 WebView(ウェブブラウザの部品への埋め込みandroid)

15.1 以下の説明を行っている動画

15.2 関係文書

from kivy.utils import platform
....省略
 if platform == 'android':
   ...android用の処理...

15.3 WebViewを使ってみる手順

from kivy.app import App
from jnius import autoclass
from kivy.clock import Clock
from android.runnable import run_on_ui_thread
from kivy.uix.widget import Widget

WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.kivy.android.PythonActivity').mActivity

@run_on_ui_thread
def create_webview(*args):
        webview = WebView(activity)
        webview.getSettings().setJavaScriptEnabled(True)
        wvc = WebViewClient();
        webview.setWebViewClient(wvc);
        activity.setContentView(webview)
        webview.loadUrl('https://blog.123abcsoft.com/2020/07/31/kivy-%E3%81%A8-buildozer-%E3%81%A7-%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%A2%E3%83%97%E3%83%AA%E4%BD%9C%E6%88%90')

class Wv(Widget):
        def __init__(self, **kwargs):
                super().__init__(**kwargs)
                self.__functionstable__ = {}
                Clock.schedule_once(create_webview, 0)


class ServiceApp(App):
        def build(self):
                return Wv()

# https://github.com/kivy/python-for-android/issues/1908

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

15.4 この章のまとめ

  • 部品として、WebViewを使う方法を調べて、動作することを確認した
  • リンク先をクリックするとリンク先に飛ぶ
  • 戻るが効かない、戻るで1つ前に戻るには更にプログラムが必要らしい

16 Kivy Launcherの拡張その4

  • Sympyを使ったアプリを作りたかったが、p4aにSympyのインストール手順が用意されているが、古い為か、現状はbuilder.specのrequirementsにsympyを追加しても、途中でエラーになって入れれなかった
  • KivyMDを利用する時に発生することが多い意味不明のエラー回避の為にKivyのバージョンを2.0.0rc3に
  • pyopenssl追加
  • 日本語フォントを追加
  • KivyMD関連画像を追加

16.1 関連動画、関連文書

16.2 以下の説明を行っている動画

16.3 手順

  • Kivy Launcherのソースのbuildozer.specのrequirementsを以下に修正
  • kivyのバージョンを2.0.0rc3指定、pyopenssl追加
requirements = kivy==2.0.0rc3, android, plyer, python3, pyjnius, kivmob, kivymd, cymunk, pymunk, pandas, libcurl, Pillow, websocket-client, vispy, regex, numpy, pandas, pygame, matplotlib, websocket-client, snappy,requests,certifi,urllib3,chardet,idna,pyopenssl
  • buildozer.specのsource.include_exts を以下に変更
source.include_exts = py,png,jpg,kv,atlas,ttf
  • buildozer.specのsource.include_patterns を以下に変更
source.include_patterns = images/*,fonts/*

16.3.1 日本語フォント追加

  • Kivy Launcherのソースディレクトリにfontsディレクトリを作成し、IPAフォントファイルをそのディレクトリ内にコピーした
  • Ubuntuなら以下のコマンドでOK(ipaフォントのパッケージイスんトール後、 fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic fonts-ipafont-mincho )
sudo apt install fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic fonts-ipafont-mincho 
mkdir fonts
cp /usr/share/texlive/texmf-dist/fonts/truetype/public/ipaex/* fonts/
  • ファイルは、私の環境では以下になった
fonts
├── ipaexg.ttf
├── ipaexm.ttf
├── ipag.ttf
├── ipagp.ttf
├── ipam.ttf
└── ipamp.ttf

16.3.2 KivyMDのロゴ画像を入れた

  • 必要性は低いけど
  • Kivy Launcherのソースディレクトリにimagesディレクトリを作成し、kivyMDのロゴ画像を入れた。画像はKivyMDのGitHubから得た
  • ファイルは、私の環境では以下になった
images/
└── kivymd.png

16.3.3 Kivy LauncherにSympy追加

  • https://github.com/kivy/python-for-android/issues/2303の情報で、Sympy(数式処理パッケージ、前から入れたかった)を入れる方法2つ紹介されている。そのうちの一つ、Pythonで書かれているので、それらのライブラリを、ディレクトリにコピーする手法を選択した
  1. buildozer用のvirturlenvにはいる
    • 私の場合は ~/kivy_buildozer/ に作成したので、以下のコマンドを実行
    cd ~/kivy_buildozer/
    source bin/activate
    
  2. Sympyをインストール
    pip3 install sympy
    
  3. Kivy Launcher のソースディレクトリに移動
    • その後、取ってきてあるkivy Launcherのソースディレクトリに行き,sympyと、それに必要なmpmathをコピーしてくる
    • ~/kivy_buildozer/ の部分は作成したvirturlenvのディレクトリに依存するので、適時変更してください
    cp -r ~/kivy_buildozer/lib/python3.8/site-packages/mpmath .
    cp -r ~/kivy_buildozer/lib/python3.8/site-packages/sympy .
    
  4. ビルドインストール
    • Android端末をPCに接続して以下のコマンドを実行
    • Android端末側でポップアップがでたら、リモートでバッグ可能なように操作
    buildozer android debug deploy run
    
  5. テスト用のプログラムを作成して動かしてみる
    • SympyTest ディレクトリ内に用意する
    mdkir SympyTest
    cd SympyTest
    
    • android.txtを以下で用意
    title=SympyTest
    author=NM Max
    orientation=portrait
    
    • main.pyを以下で作成
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.label import Label
    import sympy
    
    
    x=sympy.Symbol('x')
    y=sympy.Symbol('y')
    
    
    class MyApp(App):
    
        def build(self):
            box = BoxLayout()
            box.orientation = 'vertical'
            box.add_widget(Label(text=str(sympy.expand((x+y)**3)),font_size="20sp"))
            box.add_widget(Label(text=str(sympy.integrate(1/x**3,x)),font_size="30sp"))
            box.add_widget(Label(text=str(sympy.diff(x**2,x)),font_size="30sp"))
            box.add_widget(Label(text=str(sympy.Or(x,y)),font_size="30sp"))
            return box
    
    MyApp().run()
    
  6. ファイルを転送
    • 以下のコマンドで転送する
    adb push ../SympyTest/ /sdcard/kivy/
    
  7. Android端末で動かしてみる
    • 上手く動作した

16.4 この章のまとめ

  • Sympyを入れたバージョンを作成
  • KivyMDと相性のあんま良くないkKivy1系ではなく、最新のKivy2系を入れた
  • 日本語フォントや、KivyMDのロゴも入れておいた

17 Kivyでmatplotlibでグラフ

  • Kivy + Kivy Garden matplotlib + matplotlibでグラフ描いてみた

17.1 関連動画、関連文書

17.2 以下の説明を行っている動画

17.3 手順

  • virtualenvにはいる(私の場合は ~/kivy_buildozer/bin 以下に構築してある)
source ~/kivy_buildozer/bin/activate
  • ディレクトリ matplotlib01 用意
  • コマンドラインでやるなら以下
mkdir matplotlib01
cd matplotlib01
buildozer init
  • buildozer.specのrequestsと,garden_requirementsの行を以下に修正
requirements = python3, kivy==2.0.0rc3, android, jnius, kivmob, kivymd, pandas, numpy, matplotlib
garden_requirements = mapview, matplotlib
  • 以下の内容でmain.pyを用意
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
import matplotlib.pyplot as plt
import numpy as np
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg

fig, ax = plt.subplots()  
xx=range(5)
ax.plot(xx, list(map(lambda x:x**2,xx)), label='x**2', linestyle='--', marker='o')  
ax.plot(xx, list(map(lambda x:x+3,xx)), label='x+3', linestyle='--', marker='o')  
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("title")
ax.legend()
ax.grid()

class MyApp(App):
    def build(self):
        box = BoxLayout()
        box.orientation = 'vertical'
        box.add_widget(FigureCanvasKivyAgg(fig))
        return box

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

17.3.1 Ubuntu側でテストするようにvirturlenvにmatplotlibをインストール、2020/10/01で、最新のmatplotlibをUbuntu20.04で動かそうとするとエラーになるため、2.2系をインストール

  • まずバーチャル環境にはいる(私は~/kivy_buildozer/に準備してある)
source ~/kivy_buildozer/bin/activate
  • それから3.2系最新のmatplotlibをインストール
pip3 install matplotlib==3.2.2
  • main.pyを動かしてみる
python3 main.py

17.3.2 Androidで実行

  • AndroidとUSB接続して以下を実行
buildozer android debug deploy run

17.4 この章のまとめ

  • Kivy で matplotlib を利用して、グラフ描画(Kiby Gardenのmatplotlibライブラリも利用)できた
  • Kivy Launcherでも動かそうとしたが、なぜかKivy Gardenのmatplotlibが読み込めなかった、そのため、新規パッケージ方式でやった。今後解決方法みつけたら、また文書と動画にします。

18 Kivy+Buildozerで作成したAndroidアプリをGoogle Play Storeに出品する手順

18.1 関連動画、関連文書

18.2 手順

  1. AdMobへの登録とアップロード
    • 登録料不要だった。
    • アプリ名と、広告タイプを登録し、アプリのkeyと、広告のkeyをゲット
  2. buildoze.specとソース修正
    • AdMobのkeyがテスト用になっていたので、それを修正しこのアプリ用のKeyに置き換えるようにbuildozer.specとソース修正
    • 64bitCPU用にする必要があった(32bit用だと審査さえしてもらえなくなってる2020/10/23時点)) buildozer.specの armeabi-v7a を arm64-v8a に変更
    • 来年くらいに32bit用はGoogle Playストアから駆逐されるらしい。2年前くらい前発売のAndroidはみな64bitになってて、その前数年が32bitCPUと64bitCPUが混在。その前は32bitCPUだったらしい。
    android.arch = arm64-v8a
    
    • Androidのバージョンが29対応じゃないと審査してもらえない(2020/10/23時点)。buildozer.specの 27を29に。将来もっと上のバージョンの必要がでてくることが予想される
    android.api = 29
    

18.2.1 リリースバージョンの作成

  • .buildozer/ 以下を削除してから、以下のコマンドで作成しなおした 
buildozer android release
  • 今回のSympyCalculatorだと sympycalclator-0.0.2-arm64-v8a-release-unsigned.apk が出来た。(アプリ名とバージョン番号はbuildozer.specの設定によってかわる)
  • Google Play Storeに出品する為には署名が必要だった。

18.2.2 サイン

  1. key作成
    • alies を test1 にした
    • 以下のコマンドでkeyを生成
    • 姓名、県、市、等を聞かれるから、ちゃんと回答、組織単位名は何も入力せずエンターした(私の場合、ある場合は入れて下さい)国のコードはJAにした。
    • 10,000日間有効な2,048ビットのRSAの鍵ペアと自己署名型証明書が生成された、これらを利用して署名した
    mkdir ./keystores
    keytool -genkey -v -keystore ./keystores/sympycalculator-release-key.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias test1
    
  2. サイン作業
    • これやると良いらしい
    zipalign -v -p 4 ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned.apk ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned-aligned.apk
    
    • サインする
    apksigner sign --ks ./keystores/sympycalculator-release-key.keystore --out ./bin/sympycalclator-0.0.2-arm64-v8a-release.apk  ./bin/sympycalclator-0.0.2-arm64-v8a-release-unsigned-aligned.apk
    
    • 以下で確認
    apksigner verify ./bin/sympycalclator-0.0.2-arm64-v8a-release.apk
    
    • これで Google Playに登録可能な sympycalclator-0.0.2-arm64-v8a-release.apk が作成できた
  3. GooglePlayへの登録と、アップロード
    • 登録料で3000円弱払った(為替レートで変化するはず,25ドル)
    • xxxxxxxxxxxxxxxxxxxはGoogle Play Storeのサイトに書いてある方法。色々サインの方法があったけど、この記述があるのを選んだ
    • これでoutput.zipを生成して、Google Play Storeにkeyを登録。その後apkをアップロード出来るようになるので、上の手順でサインしたリリースバージョンのapkをアップロードする。私は最初はオープンテストを選択した。審査に3日ほど必要だった。審査後に公開された。
    • foo.keystore と foo はkey生成時のファイルとワードに変更した
    java -jar pepk.jar --keystore=foo.keystore --alias=foo --output=output.zip --include-cert --encryptionkey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    

18.3 この章のまとめ

  • 64bitCPU用にビルドする必要があった
  • サインするのが結構面倒だった
  • apiを29以上にする必要あった(2020/10/23時点で)今後これはもっと上のバージョンになって行く

19 Googleのツールのbuildozerによる自動ダウンロードが出来なくなっています。(恐らく一時的?次のバージョンアップで解消される? 2021/02/01)

  • いつ出来なくなったのかは、2020/10/25〜2021/2/1のいつか(この間でパッケージビルドしてない為正確な日付不明)

19.1 以下の説明を行っている動画

19.2 手順

  • https://youtu.be/3U5_330aySk のようにして、あらかじめ、コマンドラインにて、必要な開発環境を用意
  • 上の手順でANDROID_SDK_ROOT にセットしたディレクトリ直下に、cmdline-tools/バージョン を tools にシンボリックリンク (最新バージョンインストールしてるなら SDKをいれようとしているディレクトリで、 ln -s cmdline-tools/latest tools)
  • 19cのndkを追加インストール(19cより新しいバージョンいれて、buildozerを動かすと、p4aが推奨してないとエラーが出る。 19bは sdkmanager ではインストール出来ない為, 19bは19cをインストールした時に表示されるURL名のcをbに変更すればダウンロード可能なので、それを ndk/android-ndk-r19b/ に移動)
  • v24のビルドツールを追加インストール(最新バージョンでエラーが出るかも知れないので追加インストールした。最新バージョンでもいけるかも、試してない)
  • buildozer.specのandroid.ndk_path, android.sdk_path, android.ant_pathを設定し

19.3 この章のまとめ

  • 今までの手順でパッケージ作成が出来なくなっているので、可能になる手順の一つを紹介
  • 今後のbuildozerのバージョンアップにて、この問題は恐らく解消?(個人的な予想)

20 opencvのコンパイル方法(邪道2021/02/05)

  • buildozerでopencvをインストールすることが出来なかった
  • buildozerでコンパイルに成功したので、その手順を紹介

20.1 以下の説明を行っている動画

20.2 手順

20.2.1 前準備

  • https://youtu.be/3U5_330aySk のようにして、あらかじめ、コマンドラインにて、必要な開発環境を用意(ndk,sdk,cmake等, Android Studioで用意してもよいかも)
  • 上の手順でANDROID_SDK_ROOT にセットしたディレクトリ直下に、cmdline-tools/バージョン を tools にシンボリックリンク (最新バージョンインストールしてるなら SDKをいれようとしているディレクトリで、 ln -s cmdline-tools/latest tools)
  • 19cのndkを追加インストール(19cより新しいバージョンいれて、buildozerを動かすと、p4aが推奨してないとエラーが出る。 19bは sdkmanager ではインストール出来ない為, 19bは19cをインストールした時に表示されるURL名のcをbに変更すればダウンロード可能なので、それを ndk/android-ndk-r19b/ に移動)
  • v24のビルドツールを追加インストール(最新バージョンでエラーが出るかも知れないので追加インストールした。最新バージョンでもいけるかも、試してない)
sdkmanager --list_installed
  • 上のコマンド実行時の出力が以下
    • cmakeは2種類は不要(試行錯誤したので2種類いれた,新しい方だけでOK)
Path                 | Version      | Description                             | Location             
-------              | -------      | -------                                 | -------              
build-tools;24.0.3   | 24.0.3       | Android SDK Build-Tools 24.0.3          | build-tools/24.0.3/  
build-tools;30.0.3   | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/  
cmake;3.10.2.4988404 | 3.10.2       | CMake 3.10.2.4988404                    | cmake/3.10.2.4988404/
cmake;3.6.4111459    | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459/   
cmdline-tools;latest | 3.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest/
emulator             | 30.3.5       | Android Emulator                        | emulator/            
ndk-bundle           | 22.0.7026061 | NDK                                     | ndk-bundle/          
ndk;19.2.5345600     | 19.2.5345600 | NDK (Side by side) 19.2.5345600         | ndk/19.2.5345600/    
patcher;v4           | 1            | SDK Patch Applier v4                    | patcher/v4/          
platform-tools       | 30.0.5       | Android SDK Platform-Tools              | platform-tools/      
platforms;android-27 | 3            | Android SDK Platform 27                 | platforms/android-27/
platforms;android-29 | 5            | Android SDK Platform 29                 | platforms/android-29/
platforms;android-30 | 3            | Android SDK Platform 30                 | platforms/android-30/
Path                                     | Version      | Description                             | Location                                 
-------                                  | -------      | -------                                 | -------                                  
build-tools;30.0.3                       | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/                      
cmake;3.18.1                             | 3.18.1       | CMake 3.18.1                            | cmake/3.18.1/                            
cmdline-tools;latest                     | 5.0.0 rc1    | Android SDK Command-line Tools (latest) | cmdline-tools/latest/                    
emulator                                 | 30.4.3       | Android Emulator                        | emulator/                                
ndk;22.0.7026061                         | 22.0.7026061 | NDK (Side by side) 22.0.7026061         | ndk/22.0.7026061/                        
patcher;v4                               | 1            | SDK Patch Applier v4                    | patcher/v4/                              
platform-tools                           | 30.0.5       | Android SDK Platform-Tools              | platform-tools/                          
platforms;android-30                     | 3            | Android SDK Platform 30                 | platforms/android-30/                    
sources;android-30                       | 1            | Sources for Android 30                  | sources/android-30/                      
system-images;android-30;google_apis;x86 | 9            | Google APIs Intel x86 Atom System Image | system-images/android-30/google_apis/x86/

20.2.2 buildozerでパッケージ作成

  • 今までのbuildozerの手順でパッケージ作成
  • 前の章の内容のように、現状Googleの自動ダウンロードできなくなっている(2021/2/5現在、将来のバージョンで解決するとは思います)対応
    • buildozer.specのandroid.ndk_path, android.sdk_path, android.ant_pathを設定(上記用意した、NDKやSDKなどにパスを設定する。ndkは新しすぎるとエラーになるので、19系の最新のもので行った)
  • 必要パッケージにopencv追加
  • 作成しようとするとOpenCVのビルド関係でエラーがでるので以下を行った。(これはAndroidの開発環境をホームディレクトリの/Android/SDK/ (${HOME}/Android/SDK/)に入れた場合、他の場所にAndroid環境を入れた場合は、そのパスに設定)
cp ${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake ./.buildozer/android/platform/build-arm64-v8a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/cmake/android/OpenCVDetectAndroidSDK.cmake
chmod -w ./.buildozer/android/platform/build-arm64-v8a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/cmake/android/OpenCVDetectAndroidSDK.cmake
  • これを行ってから再度ビルドすると成功した
  • OpenCVの一部の機能を利用してAndroid端末で動作確認したところ、その機能は正常に動作していた(imread,cvtColor,flip)

20.3 この章のまとめ

  • opencvをbuildozer.specに設定しただけではインストールできなくなっていた不具合をさけて、ビルドすることに成功したので、その手順を紹介した。
  • 今後のbuildozer あるいは python-for-android のバージョンアップにて、この問題は恐らく解消?(個人的な予想)

21 Dlibのクロスコンパイル方法(邪道2021/02/14)

  • クロスコンパイルは、Ubuntu20.04で行った。
  • python-for-androidにDlib用のレシピがなかった。
  • クロスコンパイルもなかなか成功しなかったが、2021年にはいって、ライブラリのクロスコンパイルに成功、しかし、Python用のモジュールに必要な、動的ライブラリの生成に失敗していた。
  • Python用のAndroid用のモジュール、termux環境でpipコマンドにてインストールに成功した、そのファイルを、buildozerのプロジェクトディレクトリにコピーしたが、必要なライブラリが不足していて、termux環境からもってくる必要がありそうだった。Pythonの細かいコンパイル条件も同じではなさそうだったので、この方法は断念。
  • Python用のモジュールに必要な、動的ライブラリのクロスコンパイル、2021/2/13についに成功
  • 途中でエラーがでたときに、操作したりする邪道な手順となっているけど、コンパイルして、buildozerでAndroidのパッケージ化し、インストール動作させて、顔画像のパーツ認識まで成功している

21.2 以下の説明を行っている動画




21.3 手順

21.3.1 前準備

  • コマンドラインにて、AndroidのSDKやNDKをインストール。 https://youtu.be/3U5_330aySk
    • インストールするパッケージは以下で行った。
    • buildozerの現状のバージョンだと、NDKのバージョンは19c以下しか可能ではないので、19の一番新しいバージョンを入れてある
Path                 | Version      | Description                             | Location             
-------              | -------      | -------                                 | -------              
build-tools;24.0.3   | 24.0.3       | Android SDK Build-Tools 24.0.3          | build-tools/24.0.3/  
build-tools;30.0.3   | 30.0.3       | Android SDK Build-Tools 30.0.3          | build-tools/30.0.3/  
cmake;3.10.2.4988404 | 3.10.2       | CMake 3.10.2.4988404                    | cmake/3.10.2.4988404/
cmake;3.6.4111459    | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459/   
cmdline-tools;latest | 3.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest/
emulator             | 30.3.5       | Android Emulator                        | emulator/            
ndk-bundle           | 22.0.7026061 | NDK                                     | ndk-bundle/          
ndk;19.2.5345600     | 19.2.5345600 | NDK (Side by side) 19.2.5345600         | ndk/19.2.5345600/    
patcher;v4           | 1            | SDK Patch Applier v4                    | patcher/v4/          
platform-tools       | 30.0.5       | Android SDK Platform-Tools              | platform-tools/      
platforms;android-27 | 3            | Android SDK Platform 27                 | platforms/android-27/
platforms;android-29 | 5            | Android SDK Platform 29                 | platforms/android-29/
platforms;android-30 | 3            | Android SDK Platform 30                 | platforms/android-30/
  • パッケージ環境を、作業ディレクトリを作成し、buildozer initで作成したあと、以下の変更を行う
    • arm64-v8a に buildozer.specのターゲット変更
    • 必要なパッケージをインストールするように修正
      • imutilsがあるとDlibで顔認識するとき便利なので、これも追加しておくことをオススメします。後から追加でも良いけど。
      • DlibのGUIでの表示コマンドはAndroid+Kivy+buildozerでは動作しなかったので、OpenCVあるいは、Pillow も入れておくことをオススメします。後から追加でも良いけど。OpenCVを入れる場合は現状はエラーになるので、https://www.youtube.com/embed/V0Z5cgzEsRg の手順でやれば回避可能(将来のバージョンでは、こんなややこしい手順不要になると思われる)
      • 追加情報
        • OpenCVの場合、画像表示は、Kivyのcanvasに、上下反転、カラーマップを変更して流し込めばいけた。カラーマップはrgbaにしとかないと、エラーになった。バージョンによって挙動ちがうかも。(kivy 2.0.0, Python3.8.5, OpenCV 4.5.1で試した。OpenCVのバージョンを4.5.1にするには、python-for-androidのOpenCV用のレシピを変更する必要あり)
    • android.ndk_path, android.sdk_path, android.ant_path を、この作業ディレクトリからの相対パスにて設定。
      • シンボリックリンクをはって、そこに設定した方が楽かも。私はこれは行ってないけど
    • その他必要な変更を行う
mkdir ${HOME}/mydlib
cd ${HOME}/mydlib
# source ~/kivy_buildozer/bin/activate # buildozer 用のvirturlenvが ~/kivy_buildozer にある場合
buildozer init
touch main.py # からのmain.pyを作成。何か動くものにした方が良いけど、ここでは空ファイル用意します。
# その後buildozer.specをテキストエディタで変更
  • main.pyを用意
    • dlibのバージョンも表示するようにしてあるので、dlibを入れる前だとエラーになる
    • dlibのPythonを上手くインストールできれば、Kivy, Python, Dlib, OpenCV, imutils のバージョンが表示される
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
import kivy
import sys 
import cv2
import dlib
import imutils

class HelloWorldApp(App):
 def build(self):
  b = BoxLayout(orientation="vertical")
  l2 = Label(text="Kivy:"+kivy.__version__,font_size=50)
  b.add_widget(l2)
  l4 = Label(text="Py:"+sys.version,font_size=20)
  b.add_widget(l4)
  l5 = Label(text="dlib:"+dlib.__version__,font_size=20)
  b.add_widget(l5)
  l6 = Label(text="opencv:"+cv2.__version__,font_size=20)
  b.add_widget(l6)
  l11 = Label(text="imutils:"+imutils.__version__,font_size=20)
  b.add_widget(l11)
  return b

if __name__ == '__main__':
 HelloWorldApp().run()
  • buildozer.specの変更箇所例
    • “… 省略” はbuildozer.specにコピペしない。変更しない箇所という意味
    • ndk,sdk,antのパスは実際用意してある、AndroidのNDKやSDKをあらかじめインストールしてあるパスに設定、この例では、ホームディレクトリのAndroid/SDK以下にインストールしている https://youtu.be/3U5_330aySk
    • android.arch は 現状Googleストアでうけつけてくれる64bitCPU用のものに変更(buildozer initした直後は32bit用のarmeabi-v7aになっている)
    • tiltleとパッケージネームは適当に変更してある
... 省略
title = MyDlibTest001
... 省略
package.name = mydlibtest001
... 省略
source.include_exts = py,png,jpg,kv,atlas,so
... 省略
requirements = python3,kivy==2.0.0,imutils,opencv
... 省略
android.ndk_path = ../Android/SDK/ndk/19.2.5345600
... 省略
android.sdk_path = ../Android/SDK
... 省略
android.ant_path = ../Android/SDK/cmdline-tools/latest/proguard/apache-ant-1.9.4/bin/ant
... 省略
android.arch = arm64-v8a
... 省略
  • Dlibの無い状態で、一旦Android用のバイナリを生成。
    • これによって、作業ディレクトリの .buildozer/ ディレクトリに、Dlibのクロスコンパイルに必要なファイルが生成される
    • OpenCVをrequirementsに追加してるなら、エラー発生現状はするので、前の章の手順で回避https://www.youtube.com/embed/V0Z5cgzEsRg。この手順は将来のバージョンでは不要になると思われる
buildozer android debug deploy run
  • 下が実行例 tee コマンド等でログをファイルに出しておくと良い
buildozer android debug deploy run 2>&1 | tee log001.txt

21.3.2 Dlibのソースゲット

  • 上のパッケージ作成とは別作業ディレクトリに移動。(例えば${HOME}/mydlib_dlibとか)
  • 最新安定バージョンは、コンパイル時にワーニング出まくります。なので今回はGithubの最新ソースをコンパイルします。
  • 最新安定バージョンでも同じ手順で多分クロスコンパイル出来るはず
# mkdir ${HOME}/mydlib_dlib  # 作業用のディレクトリ作成
# cd ${HOME}/mydlib_dlib     # 作業用のディレクトリに移動
git clone https://github.com/davisking/dlib

21.3.3 Dlibソースのバックアップ

  • dateコマンドを組み合わせた方だと、実行時の日付や日時入りのファイル名でバックアップ取れます。
  • 1行目のコマンドなら、dlib.org.tgz でバックアップ取れる
tar cvzf dlib.org.tgz dlib
# or
tar cvzf dlib.`date +%Y%m%d_%H%M`.tgz dlib

21.3.4 Dlibライブラリ(Python用は次の手順)のクロスコンパイル

  • Python用のクロスコンパイルするなら、ここの手順は不要
  • 作業用のディレクトリを作成し、そこに移動
    • これはコマンドラインで行わなくてもOK(使い慣れたツールでやってください)
cd dlib
mkdir build
cd build
  • 作業用のディレクトリを作成し、そこに移動し、以下を実行
    • Android用の開発環境はホームディレクトリの、Android/SDK ディレクトリ以下にインストール済み https://youtu.be/3U5_330aySk
    • ndkは19系の作業時点で一番新しいバージョンを利用した。
    • ターゲットは’arm64-v8a’にしている
    • 動的ライブラリを生成しようとしている -DANDROID_STL=c++_shared を無くせば、静的ライブラリを生成
    • ANDROID_PLATFORM=”android-16″の場合、他のバージョンにするなら、そこを変更
${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DBUILD_SHARED_LIBS=1 -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-std=c++11 -frtti -fexceptions" -DCMAKE_C_FLAGS=-O3 -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-16" -DANDROID_TOOLCHAIN=clang -DANDROID_STL=c++_shared -DANDROID_CPP_FEATURES=rtti exceptions .. 2>&1 | tee log001.txt

21.3.5 DlibライブラリPython用のクロスコンパイル

  • 作業用のディレクトリを作成し、そこに移動し、以下を実行
cd dlib
mkdir tools/python/build
cd tools/python/build
  • 設定のファイルの位置確認1
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname python -type f で探し、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python
  • 設定のファイルの位置確認2
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname Python.h -type f で探し、そのディレクトリを調べておく、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Include 
  • 設定のファイルの位置確認3
    • もし無いなら、find ${HOME}/mydlib/.buildozer/ -iname libpython3.8.so -type f で探し、そのディレクトリを調べておく、cmakeするときのオプションの該当箇所を変更
ls ${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so 
  • 以下のコマンドを実行,ただし、環境にあわせて、コマンド変更する必要あります。
    • 前準備で用意した、Androidパッケージの開発ディレクトリが、下の例だと ${HOME}/mydlib/ になっています。このディレクトリじゃない場合は、前準備で行ったディレクトリに変更してください。
    • Android用の開発環境はホームディレクトリの、Android/SDK ディレクトリ以下にインストール済み https://youtu.be/3U5_330aySk 。他のバージョンを利用する場合は、そこを変更してください。
  • その他の設定について
    • ndkは19系の作業時点で一番新しいバージョンを利用した。
    • ターゲットは’arm64-v8a’にしている
    • android.ndk_apiが21の場合。21以外なら、以下のコマンドの21をその番号に変更
    • lsコマンドで事前に調べたオプションが環境にあってないなら、該当箇所を変更
    • 2行目のコメントアウトしているコマンドは、2021/2/15現在で、python-for-android develp(githubで最新)を使う時のコマンド、Python関係のファイルの位置がちょっと違う
${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-21" -DANDROID_TOOLCHAIN=clang -DANDROID_CPP_FEATURES=rtti exceptions -DPYTHON_EXECUTABLE=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=build/lib.arm64-v8a -DPYTHON_INCLUDE_DIRS=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Include -DPYTHON_LIBRARY=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so .. 2>&1 | tee log001.txt
# ${HOME}/Android/SDK/cmake/3.10.2.4988404/bin/cmake -DANDROID_NDK="${HOME}/Android/SDK/ndk/19.2.5345600" -DCMAKE_TOOLCHAIN_FILE="${HOME}/Android/SDK/ndk/19.2.5345600/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI='arm64-v8a' -DANDROID_PLATFORM="android-21" -DANDROID_TOOLCHAIN=clang -DANDROID_CPP_FEATURES=rtti exceptions -DPYTHON_EXECUTABLE=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/hostpython3/desktop/hostpython3/native-build/python -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=build/lib.arm64-v8a -DPYTHON_INCLUDE_DIRS=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3-libbz2-liblzma/arm64-v8a__ndk_target_21/python3/Include -DPYTHON_LIBRARY=${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3-libbz2-liblzma/arm64-v8a__ndk_target_21/python3/android-build/libpython3.8.so .. 2>&1 | tee log001.txt # python-for-android develの場合こっちだった
  • 上のコマンドでエラーがなければ
make 2>&1 | tee log002.txt
  • これを実行すると、コンパイルには成功しますが、リンクの時にエラーが出ます。以下のようなエラーならOK。100%までコンパイルできずにエラーになってたら、上のcmakeのオプションがまずいので、修正
... 省略
[100%] Linking CXX shared module build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so
... 膨大なエラーメッセージ
  • リンクで失敗しているので、そこの命令をマニュアルで実行します。
  • CMakeFiles/_dlib_pybind11.dir/link.txt にリンク時のコマンドが生成されてるので、-L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 を追加します。私は-latomic の前に挿入しました。
  • ユーザー名がyoutubeの時こんな感じ
/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -frtti  -O2 -DNDEBUG  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -shared  -o build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so CMakeFiles/_dlib_pybind11.dir/src/dlib.cpp.o CMakeFiles/_dlib_pybind11.dir/src/matrix.cpp.o CMakeFiles/_dlib_pybind11.dir/src/vector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_c_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_rank_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/decision_functions.cpp.o CMakeFiles/_dlib_pybind11.dir/src/other.cpp.o CMakeFiles/_dlib_pybind11.dir/src/basic.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cca.cpp.o CMakeFiles/_dlib_pybind11.dir/src/sequence_segmenter.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_struct.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image2.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image3.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image4.cpp.o CMakeFiles/_dlib_pybind11.dir/src/rectangles.cpp.o CMakeFiles/_dlib_pybind11.dir/src/object_detection.cpp.o CMakeFiles/_dlib_pybind11.dir/src/shape_predictor.cpp.o CMakeFiles/_dlib_pybind11.dir/src/correlation_tracker.cpp.o CMakeFiles/_dlib_pybind11.dir/src/face_recognition.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cnn_face_detector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/global_optimization.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image_dataset_metadata.cpp.o CMakeFiles/_dlib_pybind11.dir/src/numpy_returns.cpp.o CMakeFiles/_dlib_pybind11.dir/src/line.cpp.o dlib_build/libdlib.a -latomic -lm
  • -L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 を追加例が以下
/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --gcc-toolchain=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/youtube/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -frtti  -O2 -DNDEBUG  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -shared  -o build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so CMakeFiles/_dlib_pybind11.dir/src/dlib.cpp.o CMakeFiles/_dlib_pybind11.dir/src/matrix.cpp.o CMakeFiles/_dlib_pybind11.dir/src/vector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_c_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_rank_trainer.cpp.o CMakeFiles/_dlib_pybind11.dir/src/decision_functions.cpp.o CMakeFiles/_dlib_pybind11.dir/src/other.cpp.o CMakeFiles/_dlib_pybind11.dir/src/basic.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cca.cpp.o CMakeFiles/_dlib_pybind11.dir/src/sequence_segmenter.cpp.o CMakeFiles/_dlib_pybind11.dir/src/svm_struct.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image2.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image3.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image4.cpp.o CMakeFiles/_dlib_pybind11.dir/src/rectangles.cpp.o CMakeFiles/_dlib_pybind11.dir/src/object_detection.cpp.o CMakeFiles/_dlib_pybind11.dir/src/shape_predictor.cpp.o CMakeFiles/_dlib_pybind11.dir/src/correlation_tracker.cpp.o CMakeFiles/_dlib_pybind11.dir/src/face_recognition.cpp.o CMakeFiles/_dlib_pybind11.dir/src/cnn_face_detector.cpp.o CMakeFiles/_dlib_pybind11.dir/src/global_optimization.cpp.o CMakeFiles/_dlib_pybind11.dir/src/image_dataset_metadata.cpp.o CMakeFiles/_dlib_pybind11.dir/src/numpy_returns.cpp.o CMakeFiles/_dlib_pybind11.dir/src/line.cpp.o dlib_build/libdlib.a -L${HOME}/mydlib/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/android-build -lpython3.8 -latomic -lm
  • このコマンドを実行すると、リンクして build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so が生成されます。ファイル名はlinux用になっていますが、中身は arm64-v8a用(Android64bit用)のバイナリになっています。
  • build/lib.arm64-v8a/以下のファイルが、必要ファイルになります。
  • ファイルサイズが240M程度で大きいので、以下を行うと11M程度までファイルが小さくなります。
${HOME}/Android/SDK/ndk/19.2.5345600/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/strip ./build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so
  • あとは./build/lib.arm64-v8a/dlib/ディレクトリを、Dlibを使いたいbuildozerプロジェクトディレクトリにコピーします。
    • コピー先のディレクトリ名は、各自変更してください。下の例だと ${HOME}/mydlib/ にインストールする場合
cp -r ./build/lib.arm64-v8a/dlib/ ${HOME}/mydlib/
  • 必要な動的ライブラリをコピーします
    • コピーする時にファイル名を変更しました。元のままでも動作するかどうかは未確認。ファイル名をもしかしたら、変更しなくても大丈夫かもしれない
    • コピー先のディレクトリ名は、各自変更してください。下の例だと ${HOME}/mydlib/ にインストールする場合
cp ./build/lib.arm64-v8a/_dlib_pybind11.cpython-38-x86_64-linux-gnu.so ${HOME}/mydlib/_dlib_pybind11.cpython-38.so
  • この例だと ${HOME}/mydlib/ の Dlibを使いたいbuildozerプロジェクトを、再度コンパイルしなおせば、そのパッケージでDlibをPythonから使えます。

21.3.6 DlibライブラリPythonを含めたAndroidパッケージ作成とインストール

  • Android端末にUSB等でPCを接続し、以下のコマンドを実行して、Android端末にインストール、実行する
cd ${HOME}/mydlib/
buildozer android debug deploy run 2>&1 | tee log010.txt

21.4 その他

21.5 この章のまとめ

  • python-for-androidにレシピが用意されていなくて、Androidで使いにくかった、Dlibをbuildozerで利用するのに成功した邪道な作業手順を説明した。
  • もっとスマートな方法もあるとは思う
  • 今後もっと楽になる可能性大(buildozerや、python-for-androidのバージョンあがったら)。Dlibは人気のライブラリだし、レシピ用意されると思う。

22 今後

  • 今後も文書追加していきます。

23 この文書のチェンジログ

  • 2020/07/31 初版
  • 2020/08/13 Kivy+buildozer関連リンク の章追加
  • 2020/08/18 Kivy Launcherの使い方の章追加, plyer入りのKivy Launcherの作成とインストール(好きなパッケージ入りのKivy Launcherの作り方)の章追加
  • 2020/08/19 plyer関係の機能の利用方法の調べ方の章追加、広告の章、 課金の章追加
  • 2020/08/19 sl4a関係はkivyとは別物であったことと、kivy launcherカスタマイズしたが、GooglePlayにあるものと同名のものはソースが異ることを訂正,Kivy Launcherの使い方へのリンク追加
  • 2020/08/20 広告の章にKivModの詳細情報と、実際にサンプルソースを動かす手順を記述, 課金に例のリンクを追加
  • 2020/08/23 デバッグ手法いくつか紹介 の章追加, * pyjniusを使って、java経由でAndroid特有の機能の利用 の章追加, * Kivy Launcherの拡張その2 の章追加, 課金の情報にandroidモジュールの情報,公式Android開発環境の情報も追加
  • 2020/08/29 Kivy Launcherの拡張その3 の章追加
  • 2020/08/31 WebView(ウェブブラウザの部品への埋め込みandroid) の章追加
  • 2020/10/01 Kivy Launcherの拡張その4 の章追加
  • 2020/10/01 Kivyでmatplotlibでグラフ の章追加
  • 2020/10/23 Kivy+Buildozerで作成したAndroidアプリをGoogle Play Storeに出品する手順 の章追加
  • 2021/02/02 Googleのツールのbuildozerによる自動ダウンロードが出来なくなっています の章追加
  • 2021/02/05 opencvのコンパイル方法(邪道2021/02/05) の章追加
  • 2021/02/15 Dlibのクロスコンパイル方法(邪道2021/02/14) の章追加

著者: NM Max

Created: 2021-02-15 月 20:23

Validate