由于一些需求的原因需要让自己App长时间在后台。虽然这样的做法是很Orz的,但是由于项目需求有时候不得不这样做。QQ、微信之所以没被第三方应用直接给kill掉,从市场原因腾讯的软件已经深入人心,很多厂家或是软件早就把这些软件加入白名单中!

  但是作为App的开发人员来说肯定是强烈建议不要这么做,不仅仅从用户角度考虑,作为Android开发者也有责任去维护Android的生态环境。就是因为越来越多的这样的占用系统内存的进程越来越多才使得android手机越来越卡,android碎片化的原因越来越多的第三方App可以通过清理内存的方式将后台进程给直接Kill掉来增加run可用内存。

  但是通过技术层面如何解决这个不被kill掉进程的问题呢?

  • Service设置成START_STICKY,kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样。(PM1中提供参考)
  • ​通过 startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别​,除非在系统内存非常缺,否则此进程不会被 kill
  • 双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程
  • QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
  • 在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)
  • Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。鉴于目前提到的在Android-Service层做双守护都会失败,我们可以fork出c进程,多进程守护。死循环在那检查是否还存在,具体的思路如下(Android5.0以下可行)
  1. 用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。
  2. 在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。
  3. 主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。
  • 联系厂商,加入白名单

  PM1:

在基类service的oncreate中定义了一个notification,重要属性:
notification.flags = Notification.FLAG_NO_CLEAR|Notification.FLAG_ONGOING_EVENT;然后startForeground(setClass().hashCode(), notification);使得服务能挂在通知栏,感谢1、3楼提供的思路。接着我监听了一个系统广播Intent.ACTION_TIME_TICK,这个广播每分钟发送一次,我们可以每分钟检查一次Service的运行状态,如果已经被结束了,就重新启动Service。关键代码:
boolean isServiceRunning = false;
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
  for (RunningServiceInfo service :manager.getRunningServices(Integer.MAX_VALUE)) {
    if("com.XXX.XXX.XXXService".equals(service.service.getClassName())){
    isServiceRunning = true;
    }
  }
  if (!isServiceRunning ) {
 Intent i = new Intent(context, com.XXX.XXX.XXXService.class);
  i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  context.startService(i);
  } 
  
PM2:

Notification notification = new Notification(R.drawable.icon, "服务开启", System.currentTimeMillis());
notification.flags|= Notification.FLAG_NO_CLEAR;
notification.flags=Notification.FLAG_ONGOING_EVENT;
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, "service", "防止服务被任务管理器所杀", pendingIntent);
startForeground(ONGOING_NOTIFICATION, notification);

  后来一次 做自定义Notification的时候,通知栏没有显示通知,查看后发现 service 也没被kill 。所以就进一步去研究了下 最后发现 只用两行代码就能保持服务不会被kill,并且不会有通知栏通知代码如下:

1
2
Notification notification = new Notification();
startForeground(1, notification);

实例代码如下:

  

public class TestService extends Service {
 private static final Class[] mStartForegroundSignature = new Class[] {
   int.class, Notification.class };
 private static final Class[] mStopForegroundSignature = new Class[] { boolean.class };
 private NotificationManager mNM;
 private Method mStartForeground;
 private Method mStopForeground;
 private Object[] mStartForegroundArgs = new Object[2];
 private Object[] mStopForegroundArgs = new Object[1];
 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }
 @Override
 public void onCreate() {
  super.onCreate();
  mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  try {
   mStartForeground = TestService.class.getMethod("startForeground",
     mStartForegroundSignature);
   mStopForeground = TestService.class.getMethod("stopForeground",
     mStopForegroundSignature);
  } catch (NoSuchMethodException e) {
   mStartForeground = mStopForeground = null;
  }
  // 我们并不需要为 notification.flags 设置 FLAG_ONGOING_EVENT,因为
  // 前台服务的 notification.flags 总是默认包含了那个标志位
  Notification notification =new Notification();
  // 注意使用 startForeground ,id 为 0 将不会显示 notification
  startForegroundCompat(1, notification);
 }
 @Override
 public void onDestroy() {
  super.onDestroy();
  stopForegroundCompat(1);
 }
 // 以兼容性方式开始前台服务
 private void startForegroundCompat(int id, Notification n) {
  if (mStartForeground != null) {
   mStartForegroundArgs[0] = id;
   mStartForegroundArgs[1] = n;
   try {
    mStartForeground.invoke(this, mStartForegroundArgs);
   } catch (IllegalArgumentException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   } catch (InvocationTargetException e) {
    e.printStackTrace();
   }
   return;
  }
  mNM.notify(id, n);
 }
 // 以兼容性方式停止前台服务
 private void stopForegroundCompat(int id) {
  if (mStopForeground != null) {
   mStopForegroundArgs[0] = Boolean.TRUE;
   try {
    mStopForeground.invoke(this, mStopForegroundArgs);
   } catch (IllegalArgumentException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   } catch (InvocationTargetException e) {
    e.printStackTrace();
   }
   return;
  }
  // 在 setForeground 之前调用 cancel,因为我们有可能在取消前台服务之后
  // 的那一瞬间被kill掉。这个时候 notification 便永远不会从通知一栏移除
  mNM.cancel(id);
 }
}
  除了加入白名单这种官方解决方法,谷歌提出了使用:ForegroundService 前台服务,让服务一直以前台任务的方式运行,可以在service 的oncreate来实现前台服务, 通过这个方法必须发送一个通知栏,让用户知道服务在运行。关于前台服务将在下一篇随笔中记录。
 

通过查询资料有人提到这个program:: droidwolf/NativeSubprocess · GitHub
  创建 linux 子进程的 so 库,当初用在 service 免杀上,经测试,在大部分机子上有用。NativeSubprocess 是一个可以让你在 android 程序中创建 linux 子进程并执行你的 java 代码的 so 库。由于市面上典型的内存清理工具值清理 apk 包关联的进程,而不会处理 linux 原生进程。回头试试看这样是否好使。

参考文章:http://www.jb51.net/article/73976.htm

  最后的最后还是要说:请不要做流氓软件!!让本来就碎片化的Android手机能运行的更顺畅。

关于防止App被第三方应用Kill掉的问题的更多相关文章

  1. Android: HowTo设置app不被系统kill掉

    有一种方法可以设置app永远不会被kill,AndroidManifest.xml 中添加: android:persistent="true" 适用于放在/system/app下 ...

  2. Android 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

  3. Android下写一个永远不会被KILL掉的进程/服务

    Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用.当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些 ...

  4. 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护

    本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context  ↳an ...

  5. 【代码】Android: 怎样设置app不被系统k掉

    有一种方法可以设置app永远不会被kill,AndroidManifest.xml 中添加: android:persistent="true" 适用于放在/system/app下 ...

  6. mapreduce作业reduce被大量kill掉

    之前有一段时间.我们的hadoop2.4集群压力非常大.导致提交的job出现大量的reduce被kill掉.同样的job执行时间比在hadoop0.20.203上面长了非常多.这个问题事实上是redu ...

  7. 防止Android程序被系统kill掉的处理方法

    转载请注明出处:http://blog.csdn.net/cuiran/article/details/38851401 目前遇到一个问题程序需要一直运行,并显示在最前端,但是运行一段时间发现会被系统 ...

  8. ORACLE快速彻底Kill掉的会话

    在ORACLE数据库当中,有时候会使用ALTER SYSTEM KILL SESSION 'sid,serial#'杀掉一个会话进程,但是使用这个SQL语句杀掉会话后,数据库并不会立即释放掉相关的资源 ...

  9. windows系统下在dos命令行kill掉被占用的pid (转)

    原文出自:http://www.2cto.com/os/201304/203771.html   windows系统下在dos命令行kill掉被占用的pid   1.开始-->运行-->c ...

随机推荐

  1. redis该如何分区-译文(原创)

    写在最前,最近一直在研究redis的使用,包括redis应用场景.性能优化.可行性.这是看到redis官网中一个链接,主要是讲解redis数据分区的,既然是官方推荐的,那我就翻译一下,与大家共享. P ...

  2. javascript——三元操作符

    {{C?A:B}} C条件成立则为A,不存在取B 比如在跟后台交互时,有许多要设默认值 <script type=''text/javascript> var value = docume ...

  3. ACM-ICPC如何起步

    刚刚绝定投身ACM-ICPC的同学先要过两关. 第一关:程序设计语言 如果学校有开设相关课程,则省去了很多麻烦.如果没有则可以选择<程序设计导引及在线实践>作为教材.现在的比赛中允许使用的 ...

  4. position:fixed 属性在iphone 中不起作用

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 史上最简单,一步集成侧滑(删除)菜单,高仿QQ、IOS。

    重要的话 开头说,not for the RecyclerView or ListView, for the Any ViewGroup. 本控件不依赖任何父布局,不是针对 RecyclerView. ...

  6. .NET LINQ查询操作中的类型关系

    LINQ 查询操作中的类型关系      若要有效编写查询,您应该了解完整的查询操作中的变量类型是如何全部彼此关联的. 如果您了解这些关系,就能够更容易地理解文档中的 LINQ 示例和代码示例. 另外 ...

  7. 【Xcode 4 无法打开 Xcode 5 DP 打开过的工程文件 解决方法】

    试用Xcode 5 DP打开现有工程文件后再用Xcode4打开后 Xcode 4 会进入崩溃模式折腾了几次发现下面的方法可以让工程文件恢复 如果在Xcode5-DP中打开过xib文件需要在侧栏中修改I ...

  8. 【转】B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树: ⑴树中每个结点至多有m 棵子树: ⑵若根结点不是叶子 ...

  9. UE移植到SAE云平台

    应用架在新浪的SAE上,而同时功能中又需要用上编辑器,鉴于百度的UEditor功能强大,可定制,文档全,所以理所当然的用它.而新浪把本地文件的IO操作禁止了,使得UEdiotr的图片上传.附件和在线涂 ...

  10. windows自带FTP开启后,浏览器打不开的问题

    问题描述:最近需要安装一个FTP服务器,傻瓜式的下一步下一步之后,用IE登录却发现登录不上,总是显示连接中,查找了一下网上别人的回答,发现原来系统的FTP是由主动跟被动的区别的. 问题解决:在IE下, ...