(转)Android Service 双进程常驻后台(2)
最近项目用到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)的更多相关文章
- Android 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护
本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context ↳an ...
- 保持Service不被Kill掉的方法--双Service守护 && Android实现双进程守护
本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护 第一部分: 一.Service简介:Java.lang.Object ↳Android.content.Context ↳an ...
- Android实现双进程守护 (转)
做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...
- Android实现双进程守护
做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...
- android正在运行进程和后台缓存进程的区别
正在运行的进程:需要占用一定的cpu资源和RAM(内存)空间,多少的话看是什么应用,要消耗一定的电量,影响手机速度等性能. 后台缓存的进程:不需要占用cpu资源,会在RAM中写入一部分数据,当下次打开 ...
- Android MarsDaemon实现进程及Service常驻
前段时间.就讨论过关于怎样让Service常驻于内存而不被杀死,最后的结论就是使用JNI实现守护进程,可是不得不说的是,在没有改动系统源代码的情况下,想真正实现杀不死服务,是一件非常难的事情.眼下除了 ...
- Android 进程常驻(0)----MarsDaemon使用说明
版权声明:本文为博主原创文章,未经博主允许不得转载. 这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clean mast ...
- Android 进程常驻----开机广播的简单守护以及总结
这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就是在系统强杀下,以及360获取root权限下,clean master获取root权限下都无法杀死进程 支持系统2.3到 ...
- Android 进程常驻、进程守护、进程保活技术的总结
转载自:http://blog.csdn.net/marswin89/article/details/50917098 这是一个轻量级的库,配置几行代码,就可以实现在Android上实现进程常驻,也就 ...
随机推荐
- bat坐拥大数据。数据挖掘/大数据给他们带来什么。
阿里巴巴CTO即阿里云负责人王坚博士说过一句话:云计算和大数据,你们都理解错了. 实际上,对于大数据究竟是什么业界并无共识.大数据并不是什么新鲜事物.信息革命带来的除了信息的更高效地生产.流通和消 ...
- 51单片机连接24C02-C语言测试代码
忙了一天多终于透彻了,自己写的不好使,用别人的逐步分析改成自己的,我写得非常简洁易懂. 我总结3点需要注意的地方 1.关闭非IIC通信器件,比如我的开发板SDA和SCL也连接了DS1302,造成干扰会 ...
- HDU 1568 Fibonacci 数学= = 开篇
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1568 分析:一道数学题 找出斐波那契数列的通项公式,再利用对数的性质就可得到前几位的数 斐波那契通项公 ...
- 机器学习笔记1——Linear Regression with One Variable
Linear Regression with One Variable Model Representation Recall that in *regression problems*, we ar ...
- C#实现SOAP调用WebService
最近写了一个SOA服务,开始觉得别人拿到我的服务地址,然后直接添加引用就可以使用了,结果"大牛"告知不行. 让我写一个SOAP调用服务的样例,我有点愣了,因为没做过这方面的,于是搞 ...
- WordPress文件上传与下载问题解决
网上流传了一些修改WordPress文件上传大小限制的做法,大部分是一个版本,而且说得不够准确,特别是对于生手的指导性不强,本文总结了使用Wordpress博客的朋友在文件上传与下载时大小限制,及文件 ...
- Android开发之50个常见实用技巧——活用布局
第一章.活用布局 Hack1. 使用weight属性实现视图的居中显示 ①合用weightSum属性和layout-weight属性 解决问题,如:居中显示按钮,并占据父视图的50%: 代码如: & ...
- VOL.1 利用vmware ThinApp 制作非XP下可以运行的IE6 【无插件版】(windows vista/7/8 x86/x64 )
作为一名前端开发工程师,不免要考虑IE6的兼容性,但是大部分挑剔的同行们估计都不会用XP,所以基本上IE6的兼容性测试,都是使用IE Tester或者虚拟机. IE Tester的话,很多地方模拟的还 ...
- virtualbox 安装windows系统的一些问题
今天总结一下,使用virtualbox安装windows系统的一些问题. 安装的是Ghost的系统,正版系统也可以参考. 首先本人的机器原系统是ubuntu 16.04 LTS x64 1.win7或 ...
- Modem常用概念
真实设备的标识,即DEVICE_ID.比如,Android设备是手机,这个DEVICE_ID可以同通过TelephonyManager.getDeviceId()获取,它根据不同的手机设备返回IMEI ...