問題描述
我正在從我的 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 服務停止的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!