老话说的好:躲得了初一,躲只是高三 ! 大多数的Android开发人员遇到的一个问题—怎样保证Service常驻内存。 近期我最终也在项目中务必幸运的遇到了

先来了解一下什么是Service常驻内存。

所谓Service常驻内存,意思就是想让自己写的Service服务在手机开机之后就永远处于执行状态。

举个Example先, 比如大家最熟悉的微信和QQ,每当手机开机之后,微信和QQ都是自己主动就在后台执行,实时的接收聊天信息,而且QQ和微信差点儿是永远处于执行状态(即使是用户通过各种暴力方式将Service服务关掉页也没用)

再看一下Service可能被关掉的几种方式

第一种 Android系统有一个内存保护机制。当系统可用内存不足时。为了保证当前正在执行的进程(或者说Activity)能够正常执行。系统会主动的将一些优先级比較低的进程给杀掉,当然在此进程中的Service也会随着一起被杀死。

对于进程的优先级是怎么排的 能够參考一下几个优先级排序的规则 :

在Android中一共同拥有5种进程的分类,依照优先级从高到低的顺序各自是:

  1. 前台进程

    • a . 进程中包括处于前台的正与用户交互的activity;
    • b. 进程中包括与前台activity绑定的service;
    • c. 进程中包括调用了startForeground()方法的service;
    • d. 进程中包括正在执行onCreate(), onStart(), 或onDestroy()方法的service;
    • e. 进程中包括正在执行onReceive()方法的BroadcastReceiver.
    • f. 系统中前台进程的数量非常少, 前台进程差点儿不会被杀死. 仅仅有当内存低到无法保证全部的前台进程同一时候执行时才会选择杀死某个前台进程.
  2. 可视进程

    • a. 进程中包括未处于前台但仍然可见的activity(调用了activity的onPause()方法, 但没有调用onStop()方法). 典型的情况是执行activity时弹出对话框, 此时的activity尽管不是前台activity, 但其仍然可见.
    • b. 进程中包括与可见activity绑定的service.
    • c. 可视进程不会被系统杀死, 除非为了保证前台进程的执行而不得已为之
  3. 服务进程

    • 进程中包括已启动的service.
  4. 后台进程

    • a. 进程中包括不可见的activity(onStop()方法调用后的activity).
    • b. 后台进程不会直接影响用户体验, 为了保证前台进程/可视进程/服务进程的执行, 系统随时都有可能杀死一个后台进程.
    • c. 一个正确的实现了生命周期方法的activity处于后台时被系统杀死, 能够在用户又一次启动它时恢复之前的执行状态.
  5. 空进程

    • 不包括不论什么处于活动状态的进程是一个空进程. 系统常常杀死空进程, 这不会造成不论什么影响. 空进程存在的唯一理由是为了缓存一些启动数据, 以便下次能够更快的启动.

另外一种 用户能够在App管理界面主动的将Service服务强制关闭,如图所看到的:

第三种 就是如今市面上常见的一些Clear Master之类的App清理器。比如MIUI自带的清空RAM、手机管家、360等等。

通过这些相似的三方APP。也能够将正在执行中的进程给强制关闭

最后再来看一下我们这篇文章的主题:怎样创建一个在以上三种清空下都不会被强制关闭的Service(听起来有点吊炸天的赶脚)

首先我们须要了解一点,以上三种方式事实上在最终framework层都是调用PM的killProcess方法将某进程给直接杀死。可是我们在做上层App开发时(源代码下的二次开发另当别论),又无法改动framework层的相关代码,所以我们不可能从根本上避开进程被杀死这一行为。

因此我的思路就是假设提供某一种机制。这样的机制能够在规定时间内。频繁的去启动某Service, 而假设我们去启动一个已经被创建的Service时,它的onCreate方法是不会再被调用的。

详细实现方式有例如以下几种:

1 改动Service的onStartCommand方法中的返回值。onStartCommand方法有三种返回值,依次是

START_NOT_STICK:

  • 当Service被异常杀死时。系统不会再去尝试再次启动这个Service

START_STICKY

  • 当Service被异常杀死时。系统会再去尝试再次启动这个Service,可是之前的Intent会丢失,也就是在onStartCommand中接收到的Intent会是null

START_REDELIVER_INTENT

  • 当Service被异常杀死时,系统会再去尝试再次启动这个Service。而且之前的Intent也会又一次被传给onStartCommand方法

通过改动onStartCommand方法的返回值这一方法足以解决上面我们提到Service被关闭的第一种情况。 可是对于用户主动强制关闭和三方管理器还是没有效果的

2 通过监听某些系统常常发出的广播,当接收到广播之后我们能够主动的去尝试启动Service,假设此Service已经被创建,则不会再走onCreate方法。否则这个Service就会被再次启动.

举几个常常使用的系统广播的样例:

  • Intent.ACTION_BATTERY_CH 电池电量发生改变
  • Intent.ACTION_AIRPLANE_MODE_CHANGED; 打开或关闭飞行模式
  • Intent.PHONE_STATE_CHANGED_ACTION 电话状态发生改变

这样的方法能够解决Service被关闭的全部情景。 可是缺点是不是非常稳定,毕竟要接收到某些系统广播之后才干执行启动Service的操作,因此有一定的延时,甚至没有成功的再次启动Service (对于希望Service被再次启动的渴望非常强烈的童鞋,不建议使用这样的方法)

3 通过调用AlarmManager的setRepeating方法,我们能够每隔一段时间就去启动Service一次,代码例如以下所看到的:

Calendar cal = Calendar.getInstance();
Intent intent = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0); AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE); // 每分钟启动一次。这个时间值视详细情况而定
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60*1000, pintent);

这样的方式也能够解决Service被关闭的全部情景。而且能够在一分钟内不断的去尝试启动Service。这个时间值是能够自己调的。

应该还会有其它更好的解决的方法,欢迎指正或补充

Android几种Service常驻内存的小思路的更多相关文章

  1. 关于Service常驻内存不被清理的解决方法.

    众所周知, Service是跑后台的. 但是有些Rom厂商把一键清理做的真是太好用了, 以至于一键清理变成了一种习惯, Service已经变的不再是Service了. 那为什么像诸如360, 微信, ...

  2. 「转载」关于Service常驻内存不被清理

    http://www.cnblogs.com/fangyucun/p/3533731.html 作个记录

  3. Android MarsDaemon实现进程及Service常驻

    前段时间.就讨论过关于怎样让Service常驻于内存而不被杀死,最后的结论就是使用JNI实现守护进程,可是不得不说的是,在没有改动系统源代码的情况下,想真正实现杀不死服务,是一件非常难的事情.眼下除了 ...

  4. Android 四大组件 Service 服务

    1.Service简单介绍 依照使用范围分类: 类别 优点 缺点 差别 应用 本地服务 Local  Service 本地服务在一定程度上节约了资源,另外本地服务由于是在同一进程,因此不须要IPC,也 ...

  5. Android Training - 管理应用的内存

    http://hukai.me/android-training-managing_your_app_memory/ Random Access Memory(RAM)在任何软件开发环境中都是一个很宝 ...

  6. Android中的service

    1.service简介:service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息 ...

  7. 关于Android中图片大小、内存占用与drawable文件夹关系的研究与分析

    原文:关于Android中图片大小.内存占用与drawable文件夹关系的研究与分析 相关: Android drawable微技巧,你所不知道的drawable的那些细节 经常会有朋友问我这个问题: ...

  8. Android 中的 Service 全面总结(转载)

    转载地址:http://www.cnblogs.com/newcj/archive/2011/05/30/2061370.html 感谢作者 Android 中的 Service 全面总结 1.Ser ...

  9. Android 服务类Service 的详细学习

    http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建   目录(?)[+] 什么是服务 服务有 ...

随机推荐

  1. USACO 4.3 Buy Low, Buy Lower

    Buy Low, Buy Lower The advice to "buy low" is half the formula to success in the stock mar ...

  2. elastucasearch基础理论以及安装

    一.elasticasearch核心概念 Near Realtime(NRT 近实时) Elasticsearch 是一个近实时的搜索平台.您索引一个文档开始直到它被查询时会有轻微的延迟时间(通常为1 ...

  3. nginx一些细节知识点补充

    1.upstream 配置代理 upstream local_tomcat { server localhost:8080; } server{ location / { proxy_pass htt ...

  4. (转)python随机数用法

    进行以下操作前先 import random ,导入random模块 1. random.seed(int) 给随机数对象一个种子值,用于产生随机序列. 对于同一个种子值的输入,之后产生的随机数序列也 ...

  5. Java反射机制的缺点

    来自官方指南(Tutorial):http://docs.oracle.com/javase/tutorial/reflect/index.html 反射的用途 Uses of ReflectionR ...

  6. Servlet的一点小结

    1.什么是servlet servlet是一个Java applet,一个帮助程序.用于帮助浏览器从服务器中获取资源.浏览器-servlet-服务器三者的关系如图所示. 2.servlet的生命周期 ...

  7. dSploitzANTI渗透教程之修改MAC地址与Wifi监听器

    dSploitzANTI渗透教程之修改MAC地址与Wifi监听器 dSploitzANTI基本配置 渗透测试是一种安全性较大的工作.所以,在实施渗透测试之前进行一些简单设置.如修改MAC地址.了解网络 ...

  8. 安装部署VMware vSphere 5.5文档 (6-6) 集群和vMotion

    部署VMware vSphere 5.5 实施文档 ########################################################################## ...

  9. [HDU6198]number number number

    题目大意: 给定一个数k表示你可以从包括0的斐波那契数列中任取k个数,得到它们的和.求最小的不能得到的自然数. 思路: 打表找规律,可以发现答案为f(2k+3)-1,然后用公式f(i)=f(i/2)* ...

  10. [java][jboss]改变jboss部署目录(虚拟目录)

    原文: [java][jboss]改变jboss部署目录(虚拟目录) 在开发过程中,有时候我们希望将程序放在我们的源代码目录中,比如d:\code下,而不是放在jboss的deploy下,怎么办? 我 ...