24

我有一项由活动启动(未绑定)的服务。如果活动被破坏(例如通过按下后退按钮),服务将继续运行,这当然是有意的。但是,如果我将活动从“最近的应用程序”列表中滑出,该服务会立即重新启动。这是可重现的,每次将活动/应用程序从列表中滑出时,都会对服务的 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。

每次发生这种情况时,不仅服务的状态,而且服务正在做的工作都会丢失。我只想知道为什么滑动是这个原因。

4

4 回答 4

21

从最近的任务列表中滑动应用程序实际上会杀死托管应用程序的操作系统进程。由于您的服务与您的活动在同一进程中运行,因此这有效地终止了该服务。它不调用onDestroy()服务。它只是杀死了这个过程。繁荣。死的。走了。您的服务不会崩溃

由于您的服务START_STICKY从对 的调用返回onStartCommand(),Android 识别出您的服务应该重新启动并安排重新启动被终止的服务。但是,当您的服务重新启动时,它将处于一个新创建的进程中(您可以看到onCreate()在服务中调用),因此它必须重新开始工作。

规则 #1:永远不要从最近的任务列表中滑动应用程序 ;-)

于 2013-09-04T15:34:19.833 回答
0

也许这可能是清单中定义的广播接收器的问题。

您是否在应用程序级别的清单中定义了一些接收器/意图过滤器?我曾经遇到过同样的问题,这是由于在应用程序级别的清单中声明的​​接收器

于 2013-12-11T11:07:34.230 回答
0

通过刷卡,不能保证您的进程被系统杀死。不,您只删除应用程序任务(或返回堆栈)。申请任务不等于申请进程。

因此,如果您有任何后台作业(线程、服务等)与您的后台堆栈相关,并且您有一个很好的取消政策。如果适合以后使用,系统可能会尝试缓存您的进程。

但是,如果您从任务管理器中终止应用程序进程,则意味着您的进程将被系统删除,因此您的 JVM/沙箱会被系统主动删除。

于 2015-11-09T09:33:08.857 回答
-2

使用 *START_NOT_STICKY* 作为 onStartCommand 返回

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v(TAG, "onStartCommand");
    return START_NOT_STICKY;
}
于 2013-10-24T11:43:47.903 回答