Kivy service stops when app is closed

前端 未结 1 1123
一个人的身影
一个人的身影 2021-01-24 14:45

I\'m starting a service from my Kivy app:

service = autoclass(\'net.saband.myapp.ServiceMyservice\')
mActivity = autoclass(\'org.kivy.android.PythonActivity\').m         


        
相关标签:
1条回答
  • 2021-01-24 15:22

    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.

    0 讨论(0)
提交回复
热议问题