閉じる

Python×Kivyでスマホ対応アプリ開発入門(Android/iOS対応)

スマホでも動くPythonアプリを最短で形にしたいなら、Kivyはとても有力な選択肢です。

ひとつのコードベースでAndroidとiOSに対応でき、見た目やレイアウトは専用のkv言語で簡潔に書けます。

本記事では、Python初心者でもKivyで動くアプリをPC上で試し、最終的にスマホへ配布できるところまで丁寧に解説します。

Kivyとは何か

Kivyの特徴(Android/iOS対応のクロスプラットフォーム)

1つのコードで複数OSに対応

KivyはPythonで書いたアプリをデスクトップ(Windows/macOS/Linux)AndroidiOSに展開できるオープンソースフレームワークです。

描画はOpenGLベースで高速に動作し、タッチ操作やジェスチャ、スクロールなどスマホ向けのUI要素も標準で備えています。

kv言語でUIを宣言的に記述

Kivyにはkv言語というテンプレートがあり、Pythonコードと見た目(レイアウトやスタイル)を分離できます。

見た目の変更はkv、ロジックはPythonと役割を分けられるため、学習しやすく保守もしやすくなります。

無償・オープンソース

KivyはMITライセンスで無償利用できます。

商用アプリも配布可能です。

できること・向いているアプリ(初心者向け)

得意分野とユースケース

Kivyは以下のようなアプリに向いています。

複雑な3Dゲームよりはツール系や教育用、業務補助のユーティリティと相性が良いです。

  • 入力フォームやチェックリスト、メモ、タイマーなどの小型ツール
  • データビューア(画像/テキスト/簡単なグラフ表示)
  • 教育/学習アプリ、プロトタイピング
  • センサー/カメラを使うシンプルなネイティブアプリ

実運用の大型アプリや最新のOS固有UIを強く求める場合は工夫が必要ですが、まずは「動くもの」を短時間で作る点では非常に優秀です。

学習の前提(基本のPythonだけでOK)

必要な知識

Pythonの基本文法(関数、クラス、モジュール、import)が分かれば十分です。

非同期処理や並列処理は後から段階的に学べます。

フロントエンドやネイティブ開発の事前知識は不要です。

注意

iOS向けビルドはmacOSとXcode、Apple Developer Program(有料)が必要です。

Android向けビルドはLinuxまたはWSL2(Windows上)が実用的です。

開発環境の準備(インストールと動作確認)

Pythonの用意(推奨バージョン)

どのバージョンを入れるべきか

Kivy 2.2以降はPython 3.10〜3.12での利用実績がありますが、ビルドツール群(特にAndroid)の安定性を考えるとPython 3.10または3.11を推奨します。

Windows/Macは公式インストーラ、Linuxはディストリビューションまたはpyenvを利用してください。

以下は目安です。

OS推奨Python備考
Windows 10/113.10/3.11WSL2でAndroidビルドを行うのが安定
macOS 12以降(Apple Silicon可)3.10/3.11iOSビルドはXcode必須
Ubuntu 22.04/24.043.10/3.11Androidビルドが最も楽

Python 3.12でもPC上の実行は概ね動きますが、Androidパッケージングでは依存関係の相性に注意してください。

venvで仮想環境を作成

OS別コマンド

プロジェクトごとに仮想環境を作ると依存関係が衝突しません。

Windows(PowerShell)
PowerShell
# 任意の作業フォルダへ
PS> mkdir kivy-hello; cd kivy-hello

# 仮想環境の作成
PS> py -3.11 -m venv .venv

# 有効化
PS> .\.venv\Scripts\Activate.ps1

# pipを更新
(.venv) PS> python -m pip install -U pip setuptools wheel

macOS/Linux(Bash)
Shell
# 任意の作業フォルダへ
$ mkdir kivy-hello && cd kivy-hello

# 仮想環境の作成
$ python3 -m venv .venv

# 有効化
$ source .venv/bin/activate

# pipを更新
(.venv) $ python -m pip install -U pip setuptools wheel

Kivyのインストール(pip)

最小構成の導入

Shell
(.venv) $ pip install "kivy[base]"  # まずは最小
# 例: 音声や各種機能まで含めたい場合は
# (.venv) $ pip install "kivy[full]"

full版でも数百MBで済むので、後で機能不足でエラーになるから再インストール…とならないために、最初はfull版を利用するのがおすすめです。

こちらのコマンドを使えばWindowsでビルド済みwheelが落ちてくるため、追加のビルドツールなしで入ることが多いです。

失敗した場合はVisual C++再頒布可能パッケージを入れて再試行してください。

エディタ設定(VS Code推奨)

本格的な開発であれば必須級ですが、入れなくても開発可能です。

拡張機能と設定

  • Python拡張機能(Microsoft)とPylanceを導入します。
  • Kivy Language拡張(ある場合)を入れると.kvのシンタックスハイライトが効きます。
  • VS CodeでPythonインタプリタに.venvを選択し、実行/デバッグ構成を作ると便利です。

サンプル起動で確認(Hello World)

最小サンプル

まずは1つのボタンがあるだけのアプリを起動してみます。

クリック(タップ)でコンソールへメッセージを出します。

Python
# main.py
# Kivyの最小例: ボタンを押すとコンソールに"Hello, Kivy!"を表示します。
from kivy.app import App
from kivy.uix.button import Button

class HelloApp(App):
    def build(self):
        # Buttonウィジェットをそのままルートとして返す
        btn = Button(text="Hello Kivy")
        # on_pressイベントにPython関数をバインド
        btn.bind(on_press=self.say_hello)
        return btn

    def say_hello(self, instance):
        print("Hello, Kivy!")  # コンソール出力

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

実行はいつもどおりの実行コマンドで大丈夫です。

Shell
(.venv) $ python main.py
実行結果
Hello, Kivy!
Hello, Kivy!
# ボタンを押すたびに行が増えます

ウィンドウ(またはスマホでは画面)が立ち上がり、ボタンのタップに反応すれば成功です。

最初のKivyアプリ(基本UIとkv言語)

アプリの骨組み(AppとWidget)

Appクラスとルートウィジェット

KivyアプリはAppクラスを継承して作り、build()で返したウィジェットがルートになります。

複数のウィジェットを並べたい場合はレイアウトを使います。

Python
# main.py
# AppとカスタムWidgetを定義し、構造を分かりやすくします。
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MainView(BoxLayout):
    pass  # レイアウトと見た目はkvに任せる

# structure.kvが自動で読み込まれます。
class StructureApp(App):
    def build(self):
        return MainView()

if __name__ == "__main__":
    StructureApp().run()
Kivystructure.kv
#:kivy 2.1.0
# ファイル名はAppクラス名(StructureApp)から"App"を除いた小文字= structure.kv が自動で読み込まれます。
<MainView>:
    orientation: "vertical"
    padding: "12dp"
    spacing: "8dp"
    Label:
        text: "Kivy構造の基本"
        font_size: "20sp"
    Button:
        text: "押してみる"
        on_press: app.root.ids.status.text = "押されました!"  # kvからウィジェット更新
    Label:
        id: status
        text: "待機中..."

ちなみに、デフォルトのフォントは日本語非対応であるため、日本語を扱う場合は日本語に対応しているフォントファイル(.ttfまたは.otf)が必要です。

Pythonフォントファイルを読み込む例
import os
from kivy.resources import resource_add_path
from kivy.core.text import LabelBase, DEFAULT_FONT
# fontsフォルダのパスを追加
resource_add_path(os.path.join(os.path.dirname(__file__), 'fonts'))
# デフォルトフォントをIPAexゴシックに設定
LabelBase.register(DEFAULT_FONT, 'ipaexg.ttf')

日本語フォントの表示を試してみたい場合は、以下のIPAexフォントで試してみてください。

IPAexフォント ゴシック

IPAが提供する無料の日本語ゴシック体フォント。JIS X 0213:2004準拠で文字数が多く、可読性の高さからWebや印刷物、各種ソフトウェアで広く利用される。

レイアウト(BoxLayout/GridLayoutの基礎)

横並び/縦並びとグリッド

BoxLayoutは横(horizontal)や縦(vertical)に子要素を並べる最も基本的なレイアウトです。

GridLayoutは行列で整列します。

Kivylayoutsample.kv
#:kivy 2.1.0
BoxLayout:
    orientation: "horizontal"  # 左から右へ並ぶ
    spacing: "6dp"
    Button:
        text: "左"
    Button:
        text: "中央"
    Button:
        text: "右"

上記layoutsample.kvを読み込むなら、LayoutSampleAppクラスを作成して実行します。

Python
from kivy.app import App

class LayoutSampleApp(App):
    pass

if __name__ == "__main__":
    LayoutSampleApp().run()

グリッドレイアウトにしたい場合は、以下のようにGridLayoutを使用します。

Kivygridsample.kv
#:kivy 2.1.0
GridLayout:
    cols: 2  # 2列のグリッド
    row_default_height: "40dp"
    row_force_default: True
    spacing: "4dp"
    Button:
        text: "1"
    Button:
        text: "2"
    Button:
        text: "3"
    Button:
        text: "4"

ウィジェット(Button/Label/TextInput)

よく使う基本ウィジェット

  • Label: 文字を表示
  • Button: 押してイベントを発火
  • TextInput: 文字入力
kvwidgets_sample.kv
#:kivy 2.1.0
BoxLayout:
    orientation: "vertical"
    padding: "12dp"
    spacing: "8dp"
    Label:
        text: "お名前を入力してください"
    TextInput:
        id: name_field
        hint_text: "たろう"
        multiline: False
    Button:
        text: "送信"
        on_press: print("name:", name_field.text)  # コンソールへ出力
実行結果
name: たろう

イベント処理(on_pressなどのバインド)

Python側へイベントを渡す

イベントはbind()でPython関数に紐付けられます。

引数instanceにはイベント元ウィジェットが入ります。

Python
# events.py
# on_pressやテキスト変更イベントを受け取る例
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty

class EventView(BoxLayout):
    message = StringProperty("")

    def submit(self):
        # kvから呼ばれるメソッド
        print(f"submitted: {self.ids.name_field.text}")
        self.message = f"こんにちは、{self.ids.name_field.text}"

class EventApp(App):
    def build(self):
        return EventView()

if __name__ == "__main__":
    EventApp().run()
Kivyeventapp.kv
#:kivy 2.1.0
<EventView>:
    orientation: "vertical"
    padding: "12dp"
    spacing: "8dp"
    TextInput:
        id: name_field
        hint_text: "あなたの名前"
        multiline: False
        on_text: print("typing:", self.text)  # 入力中にコンソールへ
    Button:
        text: "送信"
        on_press: root.submit()  # Pythonメソッドを呼ぶ
    Label:
        text: root.message
実行結果
typing: た
typing: たろ
typing: たろう
submitted: たろう

kv言語の基本(見た目の分離)

規約とバインド

  • MyAppというクラス名のアプリはmy.kvを自動読み込みします(「App」を除いて小文字)。
  • <ClassName>:のルールでウィジェットの見た目を宣言できます。
  • idで参照し、Python側ではself.ids.id名でアクセスします。
Python
# kv_basic.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class KvRoot(BoxLayout):
    pass

class KvBasicApp(App):
    def build(self):
        return KvRoot()

if __name__ == "__main__":
    KvBasicApp().run()
Kivy
#:kivy 2.1.0
# kvbasic.kv (KvBasicApp -> kvbasic.kv)
<KvRoot>:
    orientation: "vertical"
    padding: "12dp"
    spacing: "8dp"
    Label:
        id: title
        text: "kv言語の基本"
        font_size: "22sp"
    Button:
        text: "タイトル変更"
        on_press: title.text = "変更されました"

画面遷移(ScreenManagerの入門)

2画面を往復してみる

ScreenManagerを使うと複数画面の切り替えが簡単です。

Python
# screens.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition

class HomeScreen(Screen):
    pass

class DetailScreen(Screen):
    pass

class ScreenApp(App):
    def build(self):
        sm = ScreenManager(transition=SlideTransition())
        sm.add_widget(HomeScreen(name="home"))
        sm.add_widget(DetailScreen(name="detail"))
        return sm

if __name__ == "__main__":
    ScreenApp().run()
Kivy
#:kivy 2.1.0
# screenapp.kv
<HomeScreen>:
    BoxLayout:
        orientation: "vertical"
        padding: "12dp"
        spacing: "8dp"
        Label:
            text: "ホーム"
        Button:
            text: "詳細へ"
            on_press: app.root.current = "detail"

<DetailScreen>:
    BoxLayout:
        orientation: "vertical"
        padding: "12dp"
        spacing: "8dp"
        Label:
            text: "詳細画面"
        Button:
            text: "戻る"
            on_press: app.root.current = "home"

画像とアイコンの表示(サイズと比率)

Imageウィジェットの基本

画像はImageで表示できます。

比率保持や伸縮の制御が重要です。

Kivy
#:kivy 2.1.0
# image_sample.kv
BoxLayout:
    orientation: "vertical"
    padding: "12dp"
    spacing: "8dp"
    Image:
        source: "assets/photo.png"   # 画像ファイルの相対パス
        allow_stretch: True          # 親に合わせて伸縮を許可
        keep_ratio: True             # 縦横比は維持
        size_hint_y: 0.7             # 画面の7割を画像に
    Label:
        text: "画像は比率を維持して表示されます"

アイコンはビルド時にアプリ全体のアイコンとして指定します(後述のbuildozer.spec)。

タッチ操作とスクロールの扱い

on_touch_*の基本

独自のタッチ処理はon_touch_down/on_touch_move/on_touch_upをオーバーライドします。

スクロールにはScrollViewを使います。

Python
# touch_scroll.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle # 必要なモジュールをインポート

class TouchArea(FloatLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 背景色を描画するためのcanvas設定を追加
        with self.canvas.before:
            # 色を薄いグレーに設定 (R, G, B, A)
            Color(0.85, 0.85, 0.85, 1) 
            # ウィジェットのサイズと位置に追従する四角形を描画
            self.rect = Rectangle(size=self.size, pos=self.pos)

        # ウィジェットのサイズや位置が変わったときに背景の四角形も更新する
        self.bind(pos=self.update_rect, size=self.update_rect)

    def update_rect(self, instance, value):
        """Rectangleのposとsizeを更新するコールバック関数"""
        self.rect.pos = instance.pos
        self.rect.size = instance.size

    def on_touch_down(self, touch):
        # 自分の領域内だけ処理する
        if self.collide_point(*touch.pos):
            print(f"down: {touch.pos}")
            return True
        return super().on_touch_down(touch)

    def on_touch_move(self, touch):
        if self.collide_point(*touch.pos):
            print(f"move: {touch.pos}")
            return True
        return super().on_touch_move(touch)

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            print(f"up: {touch.pos}")
            return True
        return super().on_touch_up(touch)

class TouchScrollApp(App):
    def build(self):
        root = BoxLayout(orientation="vertical", spacing=8, padding=12)
        root.add_widget(TouchArea(size_hint_y=0.4))
        # 縦スクロール
        scroll = ScrollView(size_hint_y=0.6)
        content = BoxLayout(orientation="vertical", size_hint_y=None, spacing=6)
        content.bind(minimum_height=content.setter("height"))
        for i in range(30):
            content.add_widget(Label(text=f"Item {i}", size_hint_y=None, height=32))
        scroll.add_widget(content)
        root.add_widget(scroll)
        return root

if __name__ == "__main__":
    TouchScrollApp().run()
実行結果
down: (123.0, 250.0)
move: (130.5, 245.0)
up: (130.5, 245.0)

スマホで動かす(Android/iOSのビルド)

Android向け(Buildozerの準備)

Buildozerとは

BuildozerはKivyアプリをAndroid向けにビルドする自動化ツールです。

内部でpython-for-android(p4a)を使い、依存ライブラリもまとめてAPK/AABにします。

LinuxまたはWSL2(Windows)での実行が安定です。

必要パッケージの例(Ubuntu/WSL2)

Shell
# 基本ツール
$ sudo apt update
$ sudo apt install -y python3-venv python3-pip git build-essential \
  openjdk-17-jdk unzip zip libffi-dev libssl-dev

# プロジェクト仮想環境で
$ python3 -m venv .venv && source .venv/bin/activate
(.venv) $ pip install -U pip setuptools wheel cython
(.venv) $ pip install buildozer

Windowsネイティブ上のUSBデバイスはWSLから直接扱いにくいため、APKのインストールはadb(Windows側)で行うか、buildozer android debugで生成したファイルを手動転送します。

APK作成と実機インストール

buildozer.specの生成と編集

Shell
(.venv) $ buildozer init          # buildozer.spec を生成
# 依存ライブラリは requirements にカンマ区切り: kivy, requests など
# パッケージ名やアイコンもspecで設定(後述)

主な編集箇所(抜粋):

INI
# buildozer.spec 抜粋
[app]
title = My Kivy App
package.name = mykivyapp
package.domain = org.example
source.dir = .
version = 0.1.0
# Play向けはAAB推奨
android.release_artifact = aab
# Pythonで使う依存ライブラリ
requirements = python3,kivy,requests
# 自前のアプリアイコン
icon.filename = assets/icon.png

[buildozer]
log_level = 2

デバッグビルドとインストール

Shell
# デバッグAPK/AABの作成
(.venv) $ buildozer -v android debug

# 端末をUSBデバッグ接続し、インストールと起動
(.venv) $ buildozer android deploy run

生成物の場所:

text
bin/  # APKやAABが出力されます

adbで直接入れる場合:

Shell
$ adb install -r bin/mykivyapp-0.1.0-debug.apk

iOS向け(Kivy-iOSとXcodeの流れ)

前提と概略

iOSはmacOSとXcodeが必須です。

配布にはApple Developer Program(有料)が必要です。

Kivy-iOSツールチェーンで依存をビルドし、Xcodeプロジェクトとして開きます。

セットアップの例

Shell
# XcodeとCommand Line ToolsをApp Storeなどから導入
# Homebrewでビルドツール
$ brew install autoconf automake libtool pkg-config
$ python3 -m venv .venv && source .venv/bin/activate
(.venv) $ pip install kivy "cython<3.1"  # 依存相性に応じてピン止め
(.venv) $ pip install kivy-ios
Shell
# Kivy-iOSで依存のビルド(時間がかかります)
(.venv) $ toolchain build python3 kivy sdl2 openssl
# プロジェクトの作成(例: 本体は../myapp ディレクトリ)
(.venv) $ toolchain create ios mykivyapp ../myapp
# 生成されたXcodeプロジェクトを開く
(.venv) $ open mykivyapp-ios/mykivyapp.xcodeproj

Xcodeでターゲットを実機またはシミュレータに合わせ、署名設定(チーム/Bundle ID)を済ませてビルドします。

パーミッション設定(AndroidManifest/iOS Info)

Androidの権限

buildozer.specandroid.permissionsに権限を列挙します。

INI
# buildozer.spec 抜粋
[app]
android.permissions = INTERNET, CAMERA, WRITE_EXTERNAL_STORAGE
# ネットワークやカメラを使う場合は適切な権限を追加

iOSのInfo.plistキー

カメラや写真ライブラリ等を使う場合、利用理由を明記する必要があります。

INI
# buildozer.spec 抜粋
[app]
ios.plist_keys = NSCameraUsageDescription=カメラをQRコード読み取りに使用します, \
    NSPhotoLibraryAddUsageDescription=画像保存のために使用します

画面サイズ対応(解像度とDP)

dp/spを使ってスケーリング

Kivyはkivy.metricsdpspで密度非依存の長さを扱えます。

UI寸法は数値ではなくdp/sp文字列または関数で指定すると、端末解像度が変わっても破綻しにくくなります。

Python
# metrics_dp.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.metrics import dp, sp

class MetricsApp(App):
    def build(self):
        root = BoxLayout(orientation="vertical", padding=dp(12), spacing=dp(8))
        from kivy.uix.label import Label
        from kivy.uix.button import Button
        root.add_widget(Label(text="dp/spの例", font_size=sp(20)))
        root.add_widget(Button(text="押す", size_hint_y=None, height=dp(44)))
        return root

if __name__ == "__main__":
    MetricsApp().run()

kvでも文字列で指定できます(例: "12dp", "20sp")。

パッケージ名/アイコン/バージョン設定

よく使うspec項目

INI
# buildozer.spec 抜粋
[app]
title = Sample App
package.name = sampleapp
package.domain = com.example      # 逆ドメイン形式
version = 1.2.3                   # 人が読む版
android.numeric_version = 10203   # 内部用。1.2.3 -> 10203 のように増加必須
icon.filename = assets/icon.png   # 512x512以上推奨
# AABでPlayに提出する場合
android.release_artifact = aab
# ターゲットAPI等(必要に応じて指定)
# android.api = 34
# android.minapi = 23

よくあるエラーと対処(Build失敗/依存関係)

典型的トラブル一覧

症状/メッセージ原因の傾向対処
Java関連のエラー(JDK not found)JDK未導入/バージョン不整合OpenJDK 17を導入しPATHを確認
Cコンパイラが見つからないbuild-essential未導入Ubuntuならaptでbuild-essentialを入れる
Couldn’t find Android SDK/NDK初回セットアップ未完Buildozerが自動取得するが、プロキシや権限に注意。再実行や環境変数確認
failed building wheel for XXXネイティブ依存のpipパッケージ代替パッケージ検討、バージョン固定、p4aのrecipes対応を確認
Python 3.12でp4a依存が壊れる依存の未対応3.10/3.11へ切り替え、requirementsを見直す
iOSでコードサイン失敗証明書/プロビジョニング未設定XcodeのSigning & Capabilitiesで正しいTeamとBundle IDを設定
Permissionが効かない設定漏れbuildozer.specのpermissions/ios.plist_keysを見直し

ビルドログは長いですが、実際に失敗したステップより少し上に原因があることが多いです。

-vオプションで詳細ログを有効化し、該当箇所を検索してください。

リリースの流れ(Google Play/TestFlight)

Android(Google Play)

  1. バージョンを更新(versionandroid.numeric_versionを増やす)。
  2. AABを作成
    (.venv) $ buildozer android release
    # buildozer.spec に android.release_artifact = aab を設定しておく
    
  3. 署名はGoogle Play App Signingを使う場合、アップロードキーを設定します。Buildozerが生成するキーを使うか、既存の.jksを指定します。
  4. Play Consoleで新しいリリースを作成し、AABをアップロードします。テストトラック(内部/クローズド)で配布して確認後、プロダクションへ昇格します。

初回提出ではプライバシーポリシーやターゲットAPI要件、64bit対応などのチェックがあります。

警告が出た項目を1つずつ解決してください。

iOS(TestFlight/本番配信)

  1. バージョン/ビルド番号をXcode側で更新。
  2. Archiveを作成し、Organizerから「Distribute App」。
  3. App Store Connectにアップロードし、TestFlightでテスター配布。
  4. レビュー申請が通ればApp Storeで公開可能です。

まとめ

KivyはPythonだけでPC・Android・iOSを横断するUIアプリを構築できる実用的なフレームワークです。

kv言語で見た目をすっきり分離し、ScreenManagerScrollViewなどの標準部品を組み合わせれば、初心者でも短期間でプロトタイプから配布まで到達できます。

Android向けにはBuildozer、iOS向けにはKivy-iOS + Xcodeを使い、permissionsやアイコン、バージョンをbuildozer.specで管理するのが基本です。

環境差によるビルドエラーは避けにくいですが、Python 3.10/3.11の採用依存のピン止め詳細ログの確認で多くは解決できます。

まずは本記事のHello Worldから始め、少しずつレイアウトやイベント、画面遷移を加えていけば、スマホで動く「自分のアプリ」に着実に近づけます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!