关闭应用程序后Kivy服务停止 [英] Kivy service stops when app is closed

查看:85
本文介绍了关闭应用程序后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可以得到帮助...但是它是一项奇特的服务,那么我该如何实现呢?我试图在我的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 %}意味着我可以将其设置在某个地方,但是可以在

(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)中重启后,意图将为空,因此我们将收到错误消息:

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'

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

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服务停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆