最近需要寫一隻常駐的Service,但是印象中之前曾經有稍微眼尖看到,在記憶體不足的情況之下,Android會依照他特定的順序去回收資源,剛好Service又正好是Android回收清單的前幾名,既要常駐Service,那就是得要讓Service活得久一點。
How to restart a Service after getting Killed by apps like “Advanced Task Killer”?
這篇提到的方式是透過在onStartCommand
回傳START_STICKY
,讓Service被砍了之後,能夠自行重新開啟
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Service API changes starting with Android 2.0
這篇有提到START_STICKY
,START_NOT_STICKY
,START_REDELIVER_INTENT
的說明
The key part here is a new result code returned by the function, telling the system what it should do with the service if its process is killed while it is running:
值 | 說明 |
---|---|
START_STICKY | is basically the same as the previous behavior, where the service is left “started” and will later be restarted by the system. The only difference from previous versions of the platform is that it if it gets restarted because its process is killed, onStartCommand() will be called on the next instance of the service with a null Intent instead of not being called at all. Services that use this mode should always check for this case and deal with it appropriately. |
START_NOT_STICKY | says that, after returning from onStartCreated(), if the process is killed with no remaining start commands to deliver, then the service will be stopped instead of restarted. This makes a lot more sense for services that are intended to only run while executing commands sent to them. For example, a service may be started every 15 minutes from an alarm to poll some network state. If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires. |
START_REDELIVER_INTENT | is like START_NOT_STICKY, except if the service’s process is killed before it calls stopSelf() for a given intent, that intent will be re-delivered to it until it completes (unless after some number of more tries it still can’t complete, at which point the system gives up). This is useful for services that are receiving commands of work to do, and want to make sure they do eventually complete the work for each command sent. |
Android Service被系统回收的解决方法
這篇有提到增加優先權的方式:
- 把service写成系统服务.
addandroid:persistent="true"
into thesection in your AndroidManifest.xml
在Manifest.xml文件中设置persistent属性为true,则可使该服务免受out-of-memory killer的影响。但是这种做法一定要谨慎,系统服务太多将严重影响系统的整体运行效率。 - 提高service的优先级
设置android:priority=”1000”
1 | <!-- 为了消去加上android:priority="1000"后出现的警告信息,可以设置android:exported属性,指示该服务是否能够被其他应用程序组件调用或跟它交互 --> |
- 将服务写成前台服务foreground service
重写onStartCommand方法,使用StartForeground(int,Notification)方法来启动service。
1 | Notification notification = new Notification(R.drawable.logo,"wf update service is running",System.currentTimeMillis()); |
- START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
- START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
- START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
- START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。