【Android】アプリにPythonのプログラムを組み込む

## はじめに

Androidアプリは通常kotlinやFlutterを使って実装しますが、プラグインを用いる事で、Androidアプリのプログラムの中に、Pythonのプログラムを組み込むことができます。そうする事で、例えば、Pythonでお手軽に機械学習の実装をしてAndroidアプリに組み込むことができます。Androidのアプリを開発する中で「Pythonだったら簡単にできるのに…」と感じたことがある方に、ぜひ読んでいただきたいです。

## 動作環境

- Android Studio Hedgehog | 2023.1.1 Patch 2
- kotlin 1.9.22
- macOS 14.1
- Python 3.9.6

## Pythonの導入準備

Android Studioで空のプロジェクトを作成し、Pythonを導入するためにChaquopyというプラグインを追加します。build.gradle.kts (Project) に1行を追加してSync Nowします。
わからない場合は、[こちらのページ](https://chaquo.com/chaquopy/doc/current/android.html)が参考になります。


```jsx
plugins {
    id("com.android.application") version "8.2.2" apply false
    id("org.jetbrains.kotlin.android") version "1.9.22" apply false
    // 1行を追加
    id("com.chaquo.python") version "15.0.1" apply false
}
```

次に、build.gradle.kts (Module) に以下の通り記述を追加してSync Nowします。
これで、AndroidでPython (Chaquopy) が追加できました。
※PCにPython 3.8 ~ 3.12のどれかをインストールしておく必要があります。

```jsx
plugins {
    // 1行を追加
    id("com.chaquo.python")
}

android {
    defaultConfig {
        // 3行を追加
        ndk {
            abiFilters += listOf("arm64-v8a", "x86_64")
        }
    }
}

chaquopy {
    defaultConfig {
        // 1行を追加　　PCにインストールしているPythonのパス
        buildPython("/usr/bin/python3")
    }
}
```

## Pythonの読み込み

Androidアプリのソースコードを記述する前に、Pythonを読み込んでおく必要があります。AndroidManifest.xmlの<application>タグに以下の通り記述を追加します。

```xml
<application
    android:name="com.chaquo.python.android.PyApplication"
>
</application>
```

## Pythonプログラムの作成

src/main/pythonの中にhello.pyを作成し、以下の通り記述します。

```python
def hello_world():
    return "Hello World"
    
def set_text(txt):
    return txt
```

## Androidアプリで動作確認

MainActivity.ktに以下の通り記述を追加します。

```kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // ------ 以下の記述を追加 ------

        // インスタンスを取得
        val py = Python.getInstance()
        // src/main/python/hello.pyを指定する
        val module = py.getModule("hello")
        // hello.pyのhello_world関数を呼ぶ
        val txt1 = module.callAttr("hello_world")
        // hello.pyのset_text関数を呼ぶ。関数の引数も指定できる
        val txt2 = module.callAttr("set_text", "Good Morning")
        // logに出力。Logcatに出力される。
        println(txt1)
        println(txt2)
    }
}

```

実行すると、hello_world, Good MorningがLogcatに出力されると思います。ここまでで、Androidアプリの中でPythonの処理を呼び出すことができました。次に、Pythonでよく使われるライブラリを追加して、動作確認してみましょう。

## Pythonのライブラリ追加

試しに、Pythonのライブラリとしてnumpyとpandasを追加してみます。ライブラリを追加するには、build.gradle.kts (Module) に以下の通り記述を追加してSync Nowします。

```jsx
chaquopy {
    defaultConfig {
        buildPython("/usr/bin/python3")
        
        // ------ 以下の記述を追加 ------
        
        pip {
            // numpyをインストールする
            install("numpy")
            // pandasをインストールする
            install("pandas")
            /* requirements.txtを指定することも可能
            install("-r", "requirements.txt")
            */
        }
    }
}
```

## Pythonプログラムの作成

hello.pyに以下の通り記述を追加します。

numpyやpandasの部分に赤線が引かれてエラーに見える場合がありますが、Android Studioの問題で、実行するとうまく動作するはずです。

```python
import numpy as np # 追加
import pandas as pd # 追加

def hello_world():
    return "Hello World"
    
def set_text(txt):
    return txt
    
# ------ 以下の記述を追加 ------
def test_numpy():
    return np.array([1,2,3,4,5])
    
# ------ 以下の記述を追加 ------
def test_pandas():
    return pd.Series([1,2,3,4,5])
```

## Androidアプリで動作確認

MainActivity.ktに以下の通り記述を追加します。

```kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val py = Python.getInstance()
        val module = py.getModule("hello")
        val txt1 = module.callAttr("hello_world")
        val txt2 = module.callAttr("set_text", "Good Morning")
        println(txt1)
        println(txt2)
        
        // ------ 以下の記述を追加 ------
        val num1 = module.callAttr("test_numpy")
        val num2 = module.callAttr("test_pandas")
        println(num1)
        println(num2)
    }
}
```

実行すると、numpy、pandasで指定した値がLogcatに出力されると思います。以上で、Pythonのライブラリを読み込んで、Androidアプリで使用できることを確認できました。

## おわりに

AndroidアプリにPythonのプログラムを組み込む方法について説明してみました。今までは、Androidアプリで実現するのは難しかったことも、Pythonを組み込むことで実現できる可能性があります。この記事が、今後のAndroidアプリの可能性を広げる事に貢献できれば幸いです。

ぜひ、この記事を引用して、AndroidアプリにPythonを組み込んだ様々なアイデアを発信していただけるとうれしいです！

## 参考文献

- https://chaquo.com/chaquopy/doc/current/android.html
- https://github.com/chaquo/chaquopy-matplotlib/tree/master