前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android service原理及免杀(3)

android service原理及免杀(3)

作者头像
随心助手
发布2019-12-19 11:27:05
7060
发布2019-12-19 11:27:05
举报
文章被收录于专栏:nginx遇上redisnginx遇上redis

三. 如何免死

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隐藏掉。

代码语言:javascript
复制
@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()时候:

代码语言:javascript
复制
@Overridepublic void onDestroy(){
    stopForeground(true);
    Intent intent = new Intent("com.example.demo.destroy");
    sendBroadcast(intent);
    super.onDestroy();}

在MyReceiver中:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档