Instructions on how to generate one APK, containing Flutter UI as a frontend, and a Python Service as a backend.
Using the p4a project for bundling python scripts and cross-compiling python libraries with native components (like numpy/scipy/pandas/tflite-runtime).
NOTE: This tutorial requres at minimum p4a version v2022.07.20 and buildozer version 1.4.0
https://buildozer.readthedocs.io/en/latest/installation.html
cd libapp
buildozer init
Edit a sample python file called srv.py
import time
while True:
time.sleep(1)
print('hello world')
Edit buildozer.spec
package.domain = org.domain
# kivy introduces conflicting dependencies and is not needed
requirements = python3
# select service bootstrap
p4a.bootstrap = service_library
# ask p4a to output aar instead of apk
android.release_artifact = aar
# specify your runtime python package dependencies here (comma separated)
requirements = python3
# foreground : so that OS does not kill us (optional)
# sticky : so that OS restarts us on exit/crash (optional)
services = Srv:srv.py:foreground:sticky
# pick ABI(s) - NOTE: listing more than needed here grows the final .apk size
android.archs = arm64-v8a, x86
buildozer android release
cd ..\
flutter create -i objc -a java testapp
# change minSdkVersion to match p4a aar library.
minSdkVersion 21
# add aar as a dependency
dependencies {
implementation files('../../../libapp/bin/myapp-0.1-arm64-v8a_x86-release.aar')
}
Here we assume you wish to start the service when your app starts and you are using a sticky foreground service.
edit testapp/android/app/src/main/java/com/example/testapp/MainActivity.java
package com.example.testapp;
import io.flutter.embedding.android.FlutterActivity;
import android.os.Bundle;
import org.domain.myapp.ServiceSrv;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ServiceSrv.prepare(this);
ServiceSrv.start(this, "");
}
}
Optionally, you can add a hook when the app exits to stop the python service with ServiceSrv.stop(this)
API
Optional if you selected foreground
when specifying the service in buildozer.
Edit testapp/android/app/src/main/AndroidManifest.xml
write to <manifest>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
flutter run
At this point, you should see 'hello world' printed if you adb locat
, while the flutter demo app running. Communicating between the two is an excercse to the user, you can use raw sockets, ZeroMQ, Nanomsg-NG libraries to name a few.
Some useful projects:
-keep public class org.kivy.android.** {
*;
}
-keep public class org.jnius.** {
*;
}