Язык Python в среде Android Studio: возможности и реализация
Основной метод: плагин Chaquopoly для глубокой интеграции
Как настроить Android Studio для запуска кода Python внутри приложения?
Chaquopoly (или Chaquopy) это плагин Gradle, который позволяет включать Python в Android проекты. Настройка начинается с добавления репозитория и подключения плагина.
// build.gradle (Project)
buildscript {
repositories {
google()
mavenCentral()
maven { url "https://chaquopy.com/maven" }
}
dependencies {
classpath "com.android.tools.build:gradle:7.4.0"
classpath "com.chaquopy:plugin:15.0.1"
}
}
Android studio python (android studio и python)
// app/build.gradle
apply plugin: 'com.chaquopy'
android {
defaultConfig {
ndk {
abiFilters "arm64-v8a", "x86_64"
}
}
}
chaquopy {
defaultConfig {
python {
version = 3.8
}
}
}
dependencies {
implementation 'com.chaquopy:core:15.0.1'
}
Создание Python скрипта
В папке app/src/main/python размещается файл с функциями.
# app/src/main/python/calculator.py
def sum(a, b):
return a + b
def multiply(a, b):
return a * b
Вызов из Java/Kotlin
// MainActivity.java
import com.chaquopy.PyObject;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PyObject calculator = Python.getInstance().getModule("calculator");
int result = calculator.callAttr("sum", 3, 4).toInt();
Log.d("Result", "Сумма: " + result); // 7
}
}
Возникающие проблемы:
- Ошибка "No Python interpreter": необходимо указать версию Python в Gradle, которая должна совпадать с установленной в системе или скачиваемой автоматически.
- Проблемы с ABI: если не указать фильтры ndk, может отсутствовать библиотека под конкретную архитектуру.
- Библиотеки с нативным кодом (numpy) требуют сборки. Рекомендуется использовать
pipвнутри конфигурации Chaquopy.
Вариант 1: Использование Kivy и Buildozer для создания APK
Как создать полноценное мобильное приложение на Python без Java?
Kivy это фреймворк для мультитач приложений. Buildozer упаковывает код в APK. После сборки Android Studio может использоваться для просмотра ресурсов, манифеста или отладки.
# main.py
from kivy.app import App
from kivy.uix.button import Button
class MyApp(App):
def build(self):
return Button(text='Hello Kivy!')
if __name__ == '__main__':
MyApp().run()
# buildozer.spec (фрагмент)
requirements = python3,kivy
android.permissions = INTERNET
android.add_src = .
# команда сборки
buildozer android debug
Типичные ошибки:
- Отсутствие инструментов (Android SDK, NDK). Необходимо предварительно настроить окружение.
- Ошибки в зависимостях: если библиотека не найдена в репозиториях PyPI для Android.
Вариант 2: BeeWare и проект Briefcase в Android Studio
Как создать кроссплатформенное приложение на Python и открыть его в Android Studio?
BeeWare преобразует Python код в нативные приложения через инструмент Briefcase. Сгенерированный проект Gradle совместим с Android Studio.
# Установка и создание проекта
pip install briefcase
briefcase new
# Выбираем шаблон 'Toga' (GUI)
cd myapp
briefcase android gradle
После выполнения последней команды создаётся папка android с проектом app. Его можно импортировать в Android Studio (File -> Open -> выбрать android/build.gradle).
# myapp/app.py
import toga
def button_handler(widget):
print("Hello from BeeWare!")
def build(app):
box = toga.Box()
button = toga.Button('Нажми меня', on_press=button_handler)
box.add(button)
return box
if __name__ == '__main__':
app = toga.App('MyApp', 'org.example.myapp', startup=build)
app.main_loop()
Проблемы и их решения:
- При импорте в Android Studio могут отсутствовать зависимости Gradle. Необходимо синхронизировать проект.
- BeeWare поддерживает не все библиотеки Python; рекомендуется использовать только чистый Python или библиотеки с Java-обёртками.
Расширенные примеры использования Chaquopoly
Рассмотрим взаимодействие между Java и Python через передачу строк, списков и словарей. Для этого используется преобразование типов через JSON.
Передача словаря из Java в Python
# app/src/main/python/advanced.py
def process_data(data):
# data приходит как строка JSON, преобразуем
import json
obj = json.loads(data)
result = {
'sum': obj['a'] + obj['b'],
'product': obj['a'] * obj['b']
}
return json.dumps(result)
// MainActivity.java
PyObject advanced = Python.getInstance().getModule("advanced");
String jsonData = "{\"a\": 10, \"b\": 20}";
String jsonResult = advanced.callAttr("process_data", jsonData).toString();
// jsonResult = "{\"sum\": 30, \"product\": 200}"
Результат:
{"sum": 30, "product": 200}
Установка дополнительных библиотек (numpy)
В app/build.gradle внутри блока chaquopy добавляется секция pip:
chaquopy {
defaultConfig {
python {
version = 3.8
}
pip {
install "numpy"
install "opencv-python"
}
}
}
После синхронизации Gradle скачает и соберёт библиотеки для целевых ABI. Ошибки возникают, если библиотека содержит C-расширения, несовместимые с Android. Тогда требуется ручная сборка или альтернатива (например, OpenCV Android SDK).
Вызов Python из многопоточного контекста
// Использование AsyncTask
private class PythonTask extends AsyncTask {
@Override
protected Integer doInBackground(Void... voids) {
PyObject module = Python.getInstance().getModule("calculator");
return module.callAttr("sum", 5, 7).toInt();
}
@Override
protected void onPostExecute(Integer result) {
textView.setText("Результат: " + result);
}
}
Python не поддерживает прямой доступ к UI из фонового потока, поэтому результат возвращается через колбэк.
Отладка Python кода
Для отладки можно включить логирование в Gradle:
chaquopy {
defaultConfig {
python {
version = 3.8
debug = true
}
}
}
Тогда сообщения из Python выводятся в Logcat с тегом Python.
Использование Android ресурсов из Python
Python может обратиться к ресурсам Android через JNI. Например, загрузить строку:
# python_utils.py
from java import jclass
def get_app_string(key):
context = jclass('android.app.Activity').getActivity()
resources = context.getResources()
return resources.getString(
jclass('android.R$string').class.getField(key).getInt(None)
)
// Java
String s = Python.getInstance().getModule("python_utils")
.callAttr("get_app_string", "app_name").toString();
Такой подход требует осторожности и используется редко из-за сложности.