专栏首页nginx遇上redisandroid service原理及免杀(3)

android service原理及免杀(3)

三. 如何免死

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(GGame_over_the_world)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 谷歌,既成功又扑街

    9 月 26 日是 Google Search 的 20 岁生日,目前在 Google Doodle 上能够看到这 20 年纪念视频。

    HyperAI超神经
  • Shader实例(流光实现)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    bering
  • 1000千米高空俯瞰 React Native

    Native 用上 React 的话,也能获得 React 的种种好处。当然,这只是一方面,背后的真正源动力是希望 Native 开发能像 Web 一样 mov...

    ayqy贾杰
  • React Native 在 Airbnb 的起起落落

    感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学...

    ayqy贾杰
  • SQLite 爬坑记

    作为从零开始的Web开发人员,在项目开发中总是遇到这样那样的坑,其中数据库的坑最多。由于在功能完善过程中需要变换频繁,不可避免地要更改DB Schema,不过我...

    岂不美哉Frost
  • 写给 Android 开发者的 I/O 18 大会精华导读

    Google 发布了 Android Jetpack,帮助开发者加快应用开发速度。

    HyperAI超神经
  • 一年一度的程序员春晚,你知道多少?

    每年的 Google I/O 和 MDCC 之类的技术大会往往会被大家称为「程序员春晚」,除了因为在这些大会上经常会发布革命性的技术、产品和未来趋势,还因为这些...

    HyperAI超神经
  • 谷歌:进不了中国,我还有非洲兄弟

    Google 大概是想要称霸地球吧,一面想要敲开中国的高墙,一面在第三世界集结力量,他们正打算在非洲加纳的首都阿克拉成立 AI 研究实验室,希望把 AI 带入非...

    HyperAI超神经
  • React Native 从诞生到现在

    感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学...

    ayqy贾杰
  • shader实例(二)色彩融合之地球仪

    结合前面的UV动画,控制白云的颜色并与地球的材质融合,形成一个带有白云的地球仪效果,原理都写在注释里了。

    bering

扫码关注云+社区

领取腾讯云代金券