三. 如何免死
3.1 onStartCommand方法中,返回START_STICKY
在StartCommand()几个常量:
START_STICKY
系统重新创建服务并且调用onStartCommand()方法,但并不会传递最后一次传递的intent,只是传递一个空的intent。除非存在将要传递来的intent,那么就会传递这些intent。这个适合播放器一类的服务,不需要执行命令,只需要独自运行,等待任务。
START_NOT_STICKY
系统不重新创建服务,除非有将要传递来的intent。这是最安全的选项,可以避免在不必要的时候运行服务。
START_REDELIVER_INTENT
系统重新创建服务并且调用onStartCommand()方法,传递最后一次传递的intent。其余存在的需要传递的intent会按顺序传递进来。这适合像下载一样的服务,立即恢复,积极执行。
@Override
public intonStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
return super.onStartCommand(intent, flags,startId);
}
手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证任何情况下都被重建,比如进程被干掉。
3.2提升Service优先级
前台服务是被认为用于已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程。前台进程必须发一个notification在状态栏中显示,知道进程被杀死。因为前台服务一直消耗一部分资源,但不像一般服务那样会在需要的时候被杀掉,所以为了节约资源,保护电池寿命,一定要在建前台服务的时候发送notification,提示用户。当然系统提供的方法就必须有notification参数的,所以不要想着怎么把notification隐藏掉。
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Intent notificationIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("Message")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();
startForeground(123456,noti);
return Service.START_STICKY;}
startForeground()方法就是将服务设置为前台服务,参数123456就是这个通知的唯一的id,只要不为0即可。
3.3 在onDestory()中发送广播开启自己
service+broadcast方式,就是当service调用到ondestory()的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;
<receiver android:name="com.example.demo.MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT"/>
<action android:name=com.example.demo.destroy"/>// 这个是自定义的action
</intent-filter>
</receiver>
在service中的ondestroy()
时候:
@Overridepublic void onDestroy(){
stopForeground(true);
Intent intent = new Intent("com.example.demo.destroy");
sendBroadcast(intent);
super.onDestroy();}
在MyReceiver中:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("com.example.demo.destroy")){
Intent sevice = new Intent(this, MyService.class);
this.startService(sevice);
}
}}
当然,从理论上来讲这个方案是可行的,实验一下结果也是可行的。但是有些情况下,发送的广播在消息队列中排的靠后,就有可能服务还没有接收到广播就销毁了(只是猜想)。所以为了能让这个机制完美运行,可以开启两个服务,相互监听,相互启动。服务A监听B的广播来启动B,服务B监听A的广播来启动A。经过实验,这个方案是可行的。
3.4用android8以前的 sdk
本文分享自 nginx遇上redis 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!