android守护进程

Service组件在android开发中经常遇到,其经常作为后台服务,需要始终保持运行,负责处理一些必要(见不得人)的任务。而一些安全软件,如360等,会有结束进程的功能,如果不做Service的保持,就会被其杀掉。

在早些时候,我们可以通过在

1. service中重写onStartCommand方法,这个方法有三个返回值, START_STICKY是service被kill掉后自动

public int onStartCommand(Intent intent, int flags, int startId) {        

   return START_STICKY;    

}

2. 配置android:persistent="true" 

3. setForeground(true); 

4. android:process=”com.xxx.xxxservice”配置到单独的进程中

以上的方法要么只是提升service优先级或者存活率, 并不能解决被安全软件强行杀死的问题.

要么像第四种单独的进程运行service在360老的版本是可以的,但是在360的比较新的版本中仍然会被杀死.

如何保持Service的运行状态是现在要说明的,核心就是利用ANDROID的系统广播,触发自己的程序检查Service的运行状态,如果被杀掉,就再起来。

常用的有开机广播,解锁屏幕的广播,电量变化等等, 其中解屏的广播算比较频繁的了,但是也并不能保证一定的频率,尤其是在特定的时间里(比如用户睡觉的时候,用户并不进行解锁操作).而我们仍要做一些操作的时候,就没有办法了.

因此,我采用了一种别的方案. 另外再加上两个类似一守护进程的Service, 分别检查Service的运行状态,注册响应的广播,对其进行守护,一旦发现没有运行就将其启动.

我利用的系统广播是

Intent.ACTION_TIME_TICK,这个广播每分钟发送一次,我们可以每分钟检查一次Service的运行状态,如果已经被结束了,就重新启动Service。

它的优点就是间隔时间短而且非常稳定, 而其他的广播并不能保证这一点,当然,在具体的应用中还是要根据需求使用, 结合其他广播来保证自己的service一定会被重启.

毕竟现在安全软件是越来越厉害了,更新得也是非常频繁. 有时间还是要看下还有没有其他的方法,综合几种来使用.

下边就是具体的代码和注意事项了:

1、 Intent.ACTION_TIME_TICK的使用

我们知道广播的注册有静态注册和动态注册,但此系统广播只能通过动态注册的方式使用。即你不能通过在manifest.xml里注册的方式接收到这个广播,只能在代码里通过

registerReceiver()方法注册。

在ThisApp extends Application 或者在service里注册广播:

 IntentFilter filter = newIntentFilter(Intent.ACTION_TIME_TICK);   
  
     MyBroadcastReceiver receiver = new MyBroadcastReceiver();   
     registerReceiver(receiver, filter);   

在广播接收器MyBroadcastReceiver extends BroadcastReceiver的onReceive里

  boolean isServiceRunning = false;   
  
  
  if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {   
  
  //检查Service状态  
  
     ActivityManager manager = (ActivityManager)AppApplication.getContext().getSystemService(Context.ACTIVITY_SERVICE);   
  for (RunningServiceInfo service :manager.getRunningServices(Integer.MAX_VALUE)) {   
  if("so.xxxx.xxxxService".equals(service.service.getClassName()))   
  
      {   
      isServiceRunning = true;   
     }   
  
      }   
  if (!isServiceRunning) {   
     Intent i = new Intent(context, xxxService.class);   
            context.startService(i);   
     }   
  
  
 }   

终极解决方案: 使用Kni,在 c端 fork进程,检测Service是否存活,若Service已被杀死,则进行重启Service.   至于检测方式,可以轮询获取子进程Pid,若为1, 则说明子进程被Init进程所领养,已经成为了孤儿进程.    但是这种方式比较消耗电量,并且由于不同手机系统定制的改变,当应用被强制停止时,父进程并不一定被真正杀死,因此在一些特定机型上是无法通过此方式进行判断. 这里推荐使用liunx socket的方式进行类似心跳包的检测,并且当触发检测Service是否被杀死之前,需要判断应用是否已经被卸载,如果应用已经被卸载,则不再进行检测Service行为,直接调用exit(0)退出子进程,避免浪费系统资源和消耗电量.

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

JavaWeb项目架构之Kafka分布式日志队列

架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Kafka做消息队列罢了。

79810
来自专栏木木玲

Netty 那些事儿 ——— Reactor模式详解

5287
来自专栏Jerry的SAP技术分享

如何在ABAP Netweaver和CloudFoundry里记录并查看日志

要记录日志需要有一个checkpoint group,可以自行创建也可以使用标准的。这里我重用标准的group:DEMO_CHECKPOINT_GROUP。

2337
来自专栏Gaussic

OpenBR安装与编译过程 原

首先要安装VS2013,官网上说装Express版本就行,我这边装了Professional中文版,除了编译的时候经常出现字符问题,其他没什么影响。

1031
来自专栏开发技术

spring-session实现分布式集群session的共享

  HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是我们把应用搭建成分布式的集群,然后利用LVS或...

1251
来自专栏运维

RH413-RHEL6.4课程总结

RH413-RHEL6.4课程总结 Unit1 Tracking Security Updates 更新分以下三类 RHSA RHBA RHEA yum up...

1331
来自专栏owent

集成Qt Webkit 到cocos2d-x

近期倒腾下客户端,想搞个cocos2d的工具。 之前的那个集成到Win32工具下的调试辅助工具是直接用的windows api。拓展起来巨麻烦。而且Windo...

1142
来自专栏自由而无用的灵魂的碎碎念

Boot Manager菜单的显示语言设置

我的系统原来是Windows Vista中文版,最近又以双系统的方式安装了Windows 7 RC 英文版。这样原来的启动的操作系统的选择菜单、F8高级启动菜单...

772
来自专栏散尽浮华

LVM常规操作记录梳理(扩容/缩容/快照等)

基本介绍 Linux用户安装Linux 操作系统时遇到的一个最常见的难以决定的问题就是如何正确地给评估各分区大小,以分配合适的硬盘空间。随着 Linux的逻辑盘...

2436
来自专栏容器化

转载NodePort,LoadBalancer还是Ingress?我该如何选择 - kubernetes

1.2K4

扫码关注云+社区

领取腾讯云代金券