应用程序关闭时 Kivy 服务停止

时间:2023-03-21
本文介绍了应用程序关闭时 Kivy 服务停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在从我的 Kivy 应用程序启动一项服务:

I'm starting a service from my Kivy app:

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

它有效.如果我使用后退按钮关闭我的应用程序,我的服务仍然有效.但是,如果我通过从最近的应用程序列表中刷出我的应用程序来关闭我的应用程序,那么该服务就会终止.

It works. And if I close my app using the back button my service still works. But if I close my app by swiping it out from the recent apps list the service dies.

我发现这个问题 并尝试使用startForeground 由这篇文章指导.它可以工作,但通知不可删除,所以这个解决方案不适合我.

I've found this issue and tried to use startForeground guided by this article. It works but the notification is not removable so this solution doesn't suit me.

我已阅读 这个问题,看起来我使用 START_STICKY 可以得到帮助......但它是 kivy 服务,所以我该如何实现它?我试图在我的 python-for-android 模板中编辑 Service.tmpl.java 并更改它:

I've read this question and it looks like I could be helped using START_STICKY... but it's kivy service so how can I implement it? I've tried to edit Service.tmpl.java in my python-for-android templates and change this:

public class Service{{ name|capitalize }} extends PythonService {
    {% if sticky %}
    @Override
    public int startType() {
        return START_STICKY;
    }
    {% endif %}
...

到这里:

public class Service{{ name|capitalize }} extends PythonService {

    @Override
    public int startType() {
        return START_STICKY;
    }

(是的,我知道 {% if sticky %} 意味着我可以将它设置在 official docs 没有一个字.)

(Yes, I understand that {% if sticky %} means that I can set it somewhere but in the official docs there is not a word about it.)

但没有任何改变,服务仍然停止.根据日志安排重启:

But nothing changed, the service still dies. According the logs the restart is scheduled:

11-17 22:52:07.140  1496  1511 I ActivityManager: Killing 29431:net.saband.myapp/u0a122 (adj 9): remove task
11-17 22:52:07.219  1496  3404 I WindowState: WIN DEATH: Window{3c605b3 u0 net.saband.myapp/org.kivy.android.PythonActivity}
11-17 22:52:07.220  1496  3404 W WindowManager: Force-removing child win Window{5ed4ff u0 SurfaceView} from container Window{3c605b3 u0 net.saband.myapp/org.kivy.android.PythonActivity}
11-17 22:52:07.225  1496  2871 W WindowManager: Failed looking up window
11-17 22:52:07.225  1496  2871 W WindowManager: java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@c7f2770 does not exist
11-17 22:52:07.225  1496  2871 W WindowManager:     at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8821)
11-17 22:52:07.225  1496  2871 W WindowManager:     at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:8812)
11-17 22:52:07.225  1496  2871 W WindowManager:     at com.android.server.wm.WindowState$DeathRecipient.binderDied(WindowState.java:1212)
11-17 22:52:07.225  1496  2871 W WindowManager:     at android.os.BinderProxy.sendDeathNotice(Binder.java:558)
11-17 22:52:07.225  1496  2871 I WindowState: WIN DEATH: null
11-17 22:52:07.247  1496  3311 D ActivityManager: cleanUpApplicationRecord -- 29431
11-17 22:52:07.250  1496  3538 I ActivityManager: Killing 29366:net.saband.myapp:service_myservice/u0a122 (adj 8): remove task
11-17 22:52:07.304  1496  3557 D ActivityManager: cleanUpApplicationRecord -- 29366
11-17 22:52:07.305  1496  3557 W ActivityManager: Scheduling restart of crashed service net.saband.myapp/.ServiceMyservice in 1000ms

但是什么也没发生.

即使应用程序从最近的应用程序列表中滑出,我也需要该服务继续工作.我需要可移动的通知.就这样.许多应用程序都可以做到.但是有没有办法用 Kivy 和 python-for-android 做到这一点?

I need the service to continue to work even when the app is closed by swiping it out from the recent apps list. And I need removable notifications. That's all. Many apps can do it. But is there a way to do it with Kivy and python-for-android?

谢谢.

推荐答案

我做到了.但这需要更改 java 代码,并且解决方案是硬编码的.奇怪和令人不快的是,python-for-android 开发人员没有预见到这一点.

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.

嗯,解决办法.

打开文件.buildozer/android/platform/build/dists/myapp/src/org/kivy/android/PythonService.java.在函数 startType() 中将 START_NOT_STICKY 更改为 START_STICKY:

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;
}

现在服务将重新启动.但这还不够,因为在函数 onStartCommand(Intent intent, int flags, int startId) 重新启动后,intent 将为 null,因此我们将收到错误消息:

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

所以我们需要在这个函数中添加if语句:

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();
}

但这还不够,因为现在我们在 nativeStart 函数调用中出现另一个错误,因为没有额外的:

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'

所以我在 run() 函数中添加了 null 检查和一些默认值(其中 2 个是硬编码的):

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();
}

现在可以了.

这篇关于应用程序关闭时 Kivy 服务停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:KivyMD,在 android 中看不到图标,但在 linux 上工作 下一篇:使用 buildozer 打包 apk 时出现 mpmath 和 sympy 错误

相关文章