I\'m starting a service from my Kivy app:
service = autoclass(\'net.saband.myapp.ServiceMyservice\')
mActivity = autoclass(\'org.kivy.android.PythonActivity\').m
I did it. But this required changing the java code and the solution is hardcoded. It's strange and unpleasantly that python-for-android developers didn't foresee this.
Well, the solution.
Open file .buildozer/android/platform/build/dists/myapp/src/org/kivy/android/PythonService.java
. In function startType()
change START_NOT_STICKY
to START_STICKY
:
public int startType() {
return START_STICKY;
}
Now the service will be restarted. But this is not enough because after restart in function onStartCommand(Intent intent, int flags, int startId)
intent will be null so we will get an error:
E AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference
So we need to add the if statement in this function:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (pythonThread != null) {
Log.v("python service", "service exists, do not start again");
return START_NOT_STICKY;
}
if (intent != null) {
startIntent = intent;
Bundle extras = intent.getExtras();
androidPrivate = extras.getString("androidPrivate");
androidArgument = extras.getString("androidArgument");
serviceEntrypoint = extras.getString("serviceEntrypoint");
pythonName = extras.getString("pythonName");
pythonHome = extras.getString("pythonHome");
pythonPath = extras.getString("pythonPath");
pythonServiceArgument = extras.getString("pythonServiceArgument");
pythonThread = new Thread(this);
pythonThread.start();
if (canDisplayNotification()) {
doStartForeground(extras);
}
} else {
pythonThread = new Thread(this);
pythonThread.start();
}
return startType();
}
But this is steel not enough because now we have another error in nativeStart
function call because there are no extras:
F DEBUG : Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: GetStringUTFChars received NULL jstring'
So I've added the null check and some default values (2 of them is hardcoded) to run()
function:
@Override
public void run(){
String package_root = getFilesDir().getAbsolutePath();
String app_root = package_root + "/app";
File app_root_file = new File(app_root);
PythonUtil.loadLibraries(app_root_file);
this.mService = this;
if (androidPrivate == null) {
androidPrivate = package_root;
}
if (androidArgument == null) {
androidArgument = app_root;
}
if (serviceEntrypoint == null) {
serviceEntrypoint = "./service/main.py"; // hardcoded
}
if (pythonName == null) {
pythonName = "myservice"; // hardcoded
}
if (pythonHome == null) {
pythonHome = app_root;
}
if (pythonPath == null) {
pythonPath = package_root;
}
if (pythonServiceArgument == null) {
pythonServiceArgument = app_root+":"+app_root+"/lib";
}
nativeStart(
androidPrivate, androidArgument,
serviceEntrypoint, pythonName,
pythonHome, pythonPath,
pythonServiceArgument);
stopSelf();
}
Now it works.