老话说的好:躲得了初一,躲只是高三 ! 大多数的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. jenkins发布maven项目

    (1)环境介绍 (2)配置ssh配置:系统管理--->系统设置 做这样的配置是方便打包之后war包或jar包复制到/tomcat/update目录下 (3)安装git 1丶不要使用1.8版本以下 ...

  2. 微信公众号开发--用.Net Core实现微信消息加解密

    1.进入微信公众号后台设置微信服务器配置参数(注意:Token和EncodingAESKey必须和微信服务器验证参数保持一致,不然验证不会通过). 2.设置为安全模式 3.代码实现(主要分为验证接口和 ...

  3. php实现微信分享朋友圈

    class JSSDK {  private $appId;  private $appSecret; public function __construct($appId, $appSecret) ...

  4. React Native踩坑之FlatList组件中的onEndReached

    最近在做一个RN项目,有使用到FlatList这样一个RN封装的组件去做上拉加载更多功能,在iOS和Android平台上,总结了以下几个遇到的问题及解决方案 1. 进入页面onReached开始就被触 ...

  5. 【AI in 美团】深度学习在文本领域的应用

    背景 近几年以深度学习技术为核心的人工智能得到广泛的关注,无论是学术界还是工业界,它们都把深度学习作为研究应用的焦点.而深度学习技术突飞猛进的发展离不开海量数据的积累.计算能力的提升和算法模型的改进. ...

  6. JDK源码分析(四)——LinkedHashMap

    目录 LinkedHashMap概述 内部字段及构造方法 存储元素 取出元素 删除元素 迭代器 利用LinkedHashMap简单实现LRU算法 总结 LinkedHashMap概述   JDK对Li ...

  7. 理解Linux的进程,线程,PID,LWP,TID,TGID

    在Linux的top和ps命令中,默认看到最多的是pid (process ID),也许你也能看到lwp (thread ID)和tgid (thread group ID for the threa ...

  8. eclipse 设置文本模板中 insert variable... 函数 详解

    设置文本模板简要图: 设置文本模板详细过程:http://www.cnblogs.com/lsy131479/p/8478711.html 此处引出设置文本模板中 insert variable... ...

  9. ActiveMQ (三):项目实践

    1. 简单项目demo Com.hoo.mq路径下(除了com.hoo.mq.spring)是普通java中使用activeMQ. Com.hoo.mq.spring路径下是非web环境spring集 ...

  10. redis 客户端命令

    Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接 1 .CLIENT LIST 返回连接到 redis 服务的客户端列表 2 .CLIENT SETNA ...