我有一个由活动启动(未绑定)的服务。如果活动被破坏(例如通过按下后退按钮),则服务继续运行,这当然是预期的。 但是,如果我将活动从“最近的应用”列表中滑出,则会立即重新启动该服务。这是可重现的,每次从列表中删除活动/应用程序时,都会对服务的onCreate方法进行新调用。中间没有打电话给onDestroy!
首先我认为服务被android杀死了,尽管我没有看到杀人的理由(活动和服务都没有资源消耗的东西,实际上它们是简约的,什么都不做)。但后来我注意到服务实际崩溃了。
V/MainActivity(856): onDestroy // swipe out of the list
I/ActivityManager(287): Killing 856:com.example.myapp/u0a10050: remove task
W/ActivityManager(287): Scheduling restart of crashed service com.example.myapp/.TestService in 5000ms
代码不值得注意,但这里是
的活动:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "onCreate, starting service...");
startService(new Intent(this, TestService.class));
}
@Override
protected void onStart() {
super.onStart();
Log.v(TAG, "onStart");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
//[...]
}
服务:
public class TestService extends Service {
private static final String TAG = "Service";
// onBind omitted
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
}
简而言之: 我的服务独立于活动的生命周期,但只要我不刷新最近的应用列表的应用程序。在这种情况下,服务重新启动但没有调用onDestroy。
每次发生这种情况时,不仅服务状态,而且服务正在进行的工作也会丢失。我只是想知道为什么滑动就是这个原因。
答案 0 :(得分:21)
从最近的任务列表中滑动应用程序实际上会杀死托管应用程序的操作系统进程。由于您的服务在与您的活动相同的过程中运行,因此有效地杀死了该服务。它不会在服务上调用onDestroy()
。它只会杀死这个过程。繁荣。死。不见了。您的服务不会崩溃。
由于您的服务从START_STICKY
调用返回onStartCommand()
,因此Android会识别您的服务应该重新启动,并安排重新启动已终止的服务。但是,当您的服务重新启动时,它将处于新创建的流程中(您可以看到服务中调用的onCreate()
),因此必须重新开始工作。
规则#1:不要从最近的任务列表中滑动应用程序; - )
答案 1 :(得分:0)
可能是清单中定义的广播接收器存在问题。
您是否在应用程序级别的清单中定义了一些接收器/ intent-filter?我曾经有同样的问题,这是由于在应用程序级别的清单中声明的接收器
答案 2 :(得分:0)
通过滑动,您的进程无法保证被系统杀死。不。您只需删除applciation任务(或后台堆栈)。应用程序任务不等于申请流程。
因此,如果你有任何后台工作(线程,服务等)绑定到你的后台堆栈,你有一个很好的取消政策。如果系统适用于以后,系统可能会尝试缓存您的流程。
如果您从任务管理器中删除了应用程序进程,那么这意味着您的进程将被删除,因此系统会主动删除您的JVM /沙箱。
答案 3 :(得分:-2)
使用* START_NOT_STICKY *作为onStartCommand返回
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
return START_NOT_STICKY;
}