最近项目用到Service常驻后台,研究了一下发现手Q和微信都是使用了双进程来保证一键清理后自动复活,copy网上双进程Service的例子,再结合onTrimMemory(),基本实现一键清理后自动复活。

使用双进程Service,关键是在AndroidManifest.xml里面定义Service时加入Android:process=":service1":

 <service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service>
<service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service>

双进程Service可以让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程。

--------以下onTrimMemory的解释引用于网络

onTrimMemory()是Android 4.0之后提供的API,系统会根据不同的内存状态来回调。根据不同的内存状态,来响应不同的内存释放策略。OnTrimMemory的参数是一个int数值,代表不同的内存状态:

TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理
TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。
TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。
TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。 
以上4个是4.0增加
TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个),并且该进程优先级比较高,需要清理内存
TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存 
以上3个是4.1增加。

本文的例子源码可以到这里下载http://pan.baidu.com/s/1qW3KvtM

以下是本文运行DEMO的结果:开启服务后双进程Service分别启动(Toast显示出来),然后使用“一键加速”来清理内存,双进程Service被逐一清理(触发Service的onTrimMemory()),但后面又分别重新启动了。

代码分析 :

AndroidManifest.xml

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicetest2"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" > <activity android:name="com.service.demo.Main">
<intent-filter >
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- 关键代码 -->
<service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service>
<service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service> </application> </manifest>

Service1.java

 package com.service.demo;

 import java.util.List;

 import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Service;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentCallbacks;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast; /**
*
* @author hellogv
*
*/
public class Service1 extends Service { private String TAG = getClass().getName();
// 用于判断进程是否运行
private String Process_Name = "com.example.servicetest2:service2"; /**
*启动Service2
*/
private StrongService startS2 = new StrongService.Stub() {
@Override
public void stopService() throws RemoteException {
Intent i = new Intent(getBaseContext(), Service2.class);
getBaseContext().stopService(i);
} @Override
public void startService() throws RemoteException {
Intent i = new Intent(getBaseContext(), Service2.class);
getBaseContext().startService(i);
}
}; @Override
public void onTrimMemory(int level){
Toast.makeText(getBaseContext(), "Service1 onTrimMemory..."+level, Toast.LENGTH_SHORT)
.show(); keepService2();//保持Service2一直运行 } @Override
public void onCreate() {
Toast.makeText(Service1.this, "Service1 onCreate...", Toast.LENGTH_SHORT)
.show();
keepService2();
} /**
* 判断Service2是否还在运行,如果不是则启动Service2
*/
private void keepService2(){
boolean isRun = Utils.isProessRunning(Service1.this, Process_Name);
if (isRun == false) {
try {
Toast.makeText(getBaseContext(), "重新启动 Service2", Toast.LENGTH_SHORT).show();
startS2.startService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
} @Override
public IBinder onBind(Intent intent) {
return (IBinder) startS2;
}
}

Service2.java

 package com.service.demo;

 import java.util.List;

 import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Application;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
/**
*
* @author 掌缘生灭
*
*/
public class Service2 extends Service {
private String TAG = getClass().getName();
private String Process_Name = "com.example.servicetest2:service1"; /**
*启动Service1
*/
private StrongService startS1 = new StrongService.Stub() { @Override
public void stopService() throws RemoteException {
Intent i = new Intent(getBaseContext(), Service1.class);
getBaseContext().stopService(i);
} @Override
public void startService() throws RemoteException {
Intent i = new Intent(getBaseContext(), Service1.class);
getBaseContext().startService(i); }
}; @Override
public void onTrimMemory(int level){
Toast.makeText(getBaseContext(), "Service2 onTrimMemory..."+level, Toast.LENGTH_SHORT)
.show();
keepService1();
} public void onCreate() {
Toast.makeText(Service2.this, "Service2 onCreate...", Toast.LENGTH_SHORT).show();
keepService1();
} /**
* 判断Service1是否还在运行,如果不是则启动Service1
*/
private void keepService1(){
boolean isRun = Utils.isProessRunning(Service2.this, Process_Name);
if (isRun == false) {
try {
Toast.makeText(getBaseContext(), "重新启动 Service1", Toast.LENGTH_SHORT).show();
startS1.startService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
} @Override
public IBinder onBind(Intent intent) {
return (IBinder) startS1;
} }

Utils.java

package com.service.demo;

import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context; public class Utils { /**
* 判断进程是否运行
* @return
*/
public static boolean isProessRunning(Context context, String proessName) { boolean isRunning = false;
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> lists = am.getRunningAppProcesses();
for (RunningAppProcessInfo info : lists) {
if (info.processName.equals(proessName)) {
isRunning = true;
}
} return isRunning;
}
}

StrongService.aidl

 package com.service.demo;
interface StrongService{
void startService();
void stopService();
}

(转)Android Service 双进程常驻后台(2)的更多相关文章

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

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

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

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

  3. Android实现双进程守护 (转)

    做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...

  4. Android实现双进程守护

    做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...

  5. android正在运行进程和后台缓存进程的区别

    正在运行的进程:需要占用一定的cpu资源和RAM(内存)空间,多少的话看是什么应用,要消耗一定的电量,影响手机速度等性能. 后台缓存的进程:不需要占用cpu资源,会在RAM中写入一部分数据,当下次打开 ...

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

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

  7. Android 进程常驻(0)----MarsDaemon使用说明

    版权声明:本文为博主原创文章,未经博主允许不得转载. 这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clean mast ...

  8. Android 进程常驻----开机广播的简单守护以及总结

    这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clean master获取root权限下都无法杀死进程 支持系统2.3到 ...

  9. Android 进程常驻、进程守护、进程保活技术的总结

    转载自:http://blog.csdn.net/marswin89/article/details/50917098 这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就 ...

随机推荐

  1. 哈希(3) java中的hashcode

    看看jdk api中对object类的描述 1.http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html 2首先你要知道每个对象都有 ...

  2. Java多线程内存模型

    Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果.在此之前 ...

  3. JAVA 调用Axis2 code generator 生成的webservice

    以下代码为调用 JAVA 调用Axis2 code generator 生成的webservice的代码. package test; import java.rmi.RemoteException; ...

  4. POJ 2955 括号匹配,区间DP

    题意:给你一些括号,问匹配规则成立的括号的个数. 思路:这题lrj的黑书上有,不过他求的是添加最少的括号数,是的这些括号的匹配全部成立. 我想了下,其实这两个问题是一样的,我们可以先求出括号要匹配的最 ...

  5. CodeIgniter开发实际案例-新闻网站【转】

    CodeIgniter开发实际案例-新闻网站 转:http://blog.csdn.net/ict2014/article/details/22104711?utm_source=tuicool&am ...

  6. MKDOCS在线文档编辑器

    http://www.mkdocs.org/  api接口文档编写 ,效果非常不错

  7. 基于SAML的单点登录介绍

    http://blog.csdn.net/csethcrm/article/details/20694993 一.背景知识: SAML即安全断言标记语言,英文全称是Security Assertion ...

  8. 硝烟中的Scrum和XP-我们如何实施Scrum 15)多团队 Part 2/2 16)地理分散 17)检查列表 18)其他

    引入"团队领导"角色 假设有3个团队开发同一个产品 红色的P是PO, 黑色的S是SM, 蓝色是其他团队成员; 如何决定哪些人属于哪个团队? 怎么分配成员? 有人觉得让PO来做人员分 ...

  9. 用apache的httpclient发请求和接受数据

    此处发请求的是用httpclient4,请自己下载所需要的jar包. 发post请求,并得到数据. String url = "http://localhost:8080/lee" ...

  10. java 集合排序(转)

    Java API针对集合类型排序提供了两种支持:java.util.Collections.sort(java.util.List)java.util.Collections.sort(java.ut ...