【Android】Service foreground模式

一般来说,一个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) {
    }
}

 

posted @ 2018-06-20 15:44  门罗的魔术师  阅读(719)  评论(0编辑  收藏  举报