gpt4 book ai didi

android - 即使我使用了 START_NOT_STICKY,为什么当进程被终止时我的 Android 服务会重新启动?

转载 作者:IT王子 更新时间:2023-10-28 23:42:25 25 4
gpt4 key购买 nike

我的应用程序使用了一种模式,我使用 Context#startService() 启动服务以及使用 Context#bindService() 绑定(bind)到它.这样我就可以独立于当前是否有任何客户端绑定(bind)到它来控制服务的生命周期。但是,我最近注意到,每当我的应用程序被系统杀死时,它很快就会重新启动所有正在运行的服务。此时将永远不会告诉服务停止,这会在发生时导调用池耗尽。这是一个最小的例子:

我发现有人遇到类似问题 here ,但从未被诊断或解决。

服务:

@Override
public void onCreate() {
Toast.makeText(this, "onCreate", Toast.LENGTH_LONG).show();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
return new Binder();
}

Activity :

@Override
protected void onStart() {
super.onStart();
Intent service = new Intent(this, BoundService.class);
startService(service);
bindService(service, mServiceConnection, 0);
}

@Override
protected void onStop() {
unbindService(mServiceConnection);
Toast.makeText(this, "unbindService", Toast.LENGTH_SHORT).show();
super.onStop();
}

为了测试它,我启动了应用程序,它启动了服务并绑定(bind)到它。然后我退出了应用程序,该应用程序解除绑定(bind)(但使服务保持运行)。然后我做了

$ adb shell am kill com.tavianator.servicerestart

果然,5 秒后,“onCreate”toast 出现,表示服务再次启动。 Logcat 显示:

$ adb logcat | grep BoundService
W/ActivityManager( 306): Scheduling restart of crashed service com.tavianator.servicerestart/.BoundService in 5000ms
I/ActivityManager( 306): Start proc com.tavianator.servicerestart for service com.tavianator.servicerestart/.BoundService: pid=20900 uid=10096 gids={1028}

如果我用 BIND_AUTO_CREATE 替换 startService() 模式,问题就不会发生(即使我在应用程序仍然绑定(bind)到服务时崩溃)。如果我从不绑定(bind)到服务,它也可以工作。但是 start、bind 和 unbind 的组合似乎永远不会让我的服务死掉。

在杀死应用程序之前使用 dumpsys 会显示:

$ adb shell dumpsys activity services com.tavianator.servicerestart
ACTIVITY MANAGER SERVICES (dumpsys activity services)
Active services:
* ServiceRecord{43099410 com.tavianator.servicerestart/.BoundService}
intent={cmp=com.tavianator.servicerestart/.BoundService}
packageName=com.tavianator.servicerestart
processName=com.tavianator.servicerestart
baseDir=/data/app/com.tavianator.servicerestart-2.apk
dataDir=/data/data/com.tavianator.servicerestart
app=ProcessRecord{424fb5c8 20473:com.tavianator.servicerestart/u0a96}
createTime=-20s825ms lastActivity=-20s825ms
executingStart=-5s0ms restartTime=-20s825ms
startRequested=true stopIfKilled=true callStart=true lastStartId=1
Bindings:
* IntentBindRecord{42e5e7c0}:
intent={cmp=com.tavianator.servicerestart/.BoundService}
binder=android.os.BinderProxy@42aee778
requested=true received=true hasBound=false doRebind=false

最佳答案

看看这个document部分:服务生命周期变化(从 1.6 开始)

更新

经过一些调查(已创建项目,逐步运行描述的命令等)我发现代码的工作方式与“服务生命周期更改”中描述的完全一样

我发现了什么:
adb shell am kill com.tavianator.servicerestart杀死什么都没有
(尝试adb shell,然后在shell中am kill com.tavianator.servicerestart
您将面临错误消息Error: Unknown command: kill)

所以,
运行您的应用程序,
运行adb shell
在shell中运行ps命令
查找您的应用的PID号
在shell运行命令kill <app_xx_PID>
你的PID号在哪里
重复杀死服务的步骤(如果它在自己的进程中运行)
检查服务是否正在运行(不应该),5-7秒后重新启动
更新
一种解决方案(不够好,但在某些情况下可用)是stopSelf()例如:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
stopSelf();
return START_NOT_STICKY;
}


更新
更新的解决方案

void writeState(int state) {
Editor editor = getSharedPreferences("serviceStart", MODE_MULTI_PROCESS)
.edit();
editor.clear();
editor.putInt("normalStart", state);
editor.commit();
}

int getState() {
return getApplicationContext().getSharedPreferences("serviceStart",
MODE_MULTI_PROCESS).getInt("normalStart", 1);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (getState() == 0) {
writeState(1);
stopSelf();
} else {
writeState(0);
Toast.makeText(this, "onStartCommand", Toast.LENGTH_LONG).show();
}
return START_NOT_STICKY;
}

为什么进程被杀死时服务会重新启动?

据此document :

When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and consuming battery power. If necessary, other components can stop the service by calling stopService(). Even if you enable binding for the service, you must always stop the service yourself if it ever received a call to onStartCommand()

从另一手文件说:

*START_NOT_STICKY* - If the system kills the service after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.

因此,在阅读本文档和一些实验后,我认为系统将手动终止的服务视为未完成(崩溃:@see W/ActivityManager(306): Scheduling restart of crashed service)并重新启动它,尽管 onStartCommand 返回了值。


stopSelf() 或 stopService() - 不重启,如果工作完成了,为什么不呢?

关于android - 即使我使用了 START_NOT_STICKY,为什么当进程被终止时我的 Android 服务会重新启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12648447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com