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

2024-06-26 14:54:24 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

它起作用了。如果我用后退按钮关闭我的应用程序,我的服务仍然有效。但是,如果我关闭我的应用程序,从最近的应用程序列表中刷出它,服务就会死掉。在

我找到了this issue,并试图在this article的指导下使用startForeground。它可以工作,但通知是不可移动的,所以这个解决方案不适合我。在

我已经读过this question,看来我可以用START\u STICKY来帮助我。。。但这是kivy服务,我如何实现它呢?我试着编辑服务.tmpl.java在我的python for android模板中,更改以下内容:

^{pr2}$

为此:

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

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

(是的,我知道{% if sticky %}意味着我可以将其设置在某个地方,但在official docs中没有关于它的消息。)

但一切都没变,服务还是死机。根据日志,计划重新启动:

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来实现呢?在

谢谢。在


Tags: org应用程序netservicejavamyappatandroid
1条回答
网友
1楼 · 发布于 2024-06-26 14:54:24

我做到了。但这需要更改java代码,而且解决方案是硬编码的。奇怪的是,面向android开发人员的python没有预见到这一点。在

好吧,解决办法。在

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

public int startType() {
    return START_STICKY;
}

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

^{pr2}$

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

@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函数调用中又出现了一个错误,因为没有额外的:

F DEBUG   : Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: GetStringUTFChars received NULL jstring'

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

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

现在它起作用了。在

相关问题 更多 >