一般来说,一个Service默认情况下是background模式,这意味着当系统需要腾出更多的内存空间给前台应用的时候(或者系统休眠一段时间之后)就会把这些background模式的Service给杀死掉,并回收其内存空间。但是,如果把一个Service设置为foreground模式的话,就可以避免被回收这个问题。
拿音乐播放器来举个例子,一般的做法是定义一个Service,并设置为foreground模式,然后调用MediaPlayer来播放音乐(播放的时候,可以在通知栏显示一个Ongoing Notification,表示正在播放音乐)。这个时候,即使系统需要为前台应用腾出内存空间,系统也不会主动终止这个Service,当然也包括系统休眠的情况。而且,就算在【最近任务】中把所有任务都移除掉,这个Serivce也不会被杀死。可以说,foreground模式比background模式更不容易被回收,驻留时间更长。PS:感觉QQ就用了这个模式。 通过
Service.startForeground()和Service.stopForeground(),可以启用或停止foreground模式。 一般来说,只需要在
onStartCommand()里面调用startForeground()就可以将服务设置为foreground模式,然后再onDestroy()里面调用stopForeground()就切换为background模式! 参考源码如下:
/**
* Make this service run in the foreground, supplying the ongoing
* notification to be shown to the user while in this state.
* By default services are background, meaning that if the system needs to
* kill them to reclaim more memory (such as to display a large page in a
* web browser), they can be killed without too much harm. You can set this
* flag if killing your service would be disruptive to the user, such as
* if your service is performing background music playback, so the user
* would notice if their music stopped playing.
*
* If you need your application to run on platform versions prior to API
* level 5, you can use the following model to call the the older setForeground()
* or this modern method as appropriate:
*
* @param id The identifier for this notification as per
* {@link NotificationManager#notify(int, Notification)
* NotificationManager.notify(int, Notification)}; must not be 0.
* @param notification The Notification to be displayed.
* @see #stopForeground(boolean)
*/
public final void startForeground(int id, Notification notification) {
try {
mActivityManager.setServiceForeground(new ComponentName(this, mClassName),
mToken, id, notification, true);
} catch (RemoteException ex) {
}
}
/**
* Remove this service from foreground state, allowing it to be killed if
* more memory is needed.
*
* @param removeNotification If true, the notification previously provided
* to {@link #startForeground} will be removed. Otherwise it will
* remain
* until a later call removes it (or the service is destroyed).
* @see #startForeground(int, Notification)
*/
public final void stopForeground(boolean removeNotification) {
try {
mActivityManager.setServiceForeground(new ComponentName(this, mClassName),
mToken, 0, null, removeNotification);
} catch (RemoteException ex) {
}
}