谁能教我安卓5.0守护进程双进程守护?

安卓开发之使用双进程守护和进程提权来实现服务进程保活
安卓开发之使用双进程守护和进程提权来实现服务进程保活
Android学习
一、进程保活
这篇文章里总结了一些进程保活方法,下文以双进程守护和进程提权来保活我们的服务进程。
双进程守护:
主要设计AB两个不同服务进程,A进程的服务轮询检查B进程的服务是否存活,没存活的话将其拉起,同样B进程服务轮询检查A进程服务是否存活,没存活的话也将其拉起
主要设计中调用 startForeground方法将service置为“前台进程”,不过这样会显示我们发送的Notification。为了取消这个Notification通知栏,我们需要第三个服务C来进行取消通知栏的工作。
二、具体设计
一、设计三个服务
在AndroidMainfest中对三个服务进行注册,其中FirstService和SecondService运行在新开的两个进程中,以进行我们的双进程守护。ThirdService主要用来取消我们的通知栏,将其放在应用的原进程就好。
android:name=".FirstService"
android:enabled="true"
android:exported="true"
android:process=":first"/&
android:name=".SecondService"
android:enabled="true"
android:exported="true"
android:process=":secon"/&
android:name=".ThirdService"
android:enabled="true"
android:exported="true"/&
二、双进程守护
对FirstService与SecondService进行设计,使其相互守护,为了提醒对方自己已挂,在这里使用相互绑定对方服务的方法,当一方出现异常断开绑定时,则另一方在回调方法中拉起对方,并再进行相互绑定。
以下为FirstService的设计:
public class FirstService extends Service {
private MyB //绑定服务需要Binder进行交互
private MyC
public IBinder onBind(Intent intent) {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onCreate() {
super.onCreate();
binder = new MyBinder();
if(conn==null)
conn = new MyConn();
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// 与SecondSevice绑定
FirstService.this.bindService(new Intent(this,SecondService.class),conn, Context.BIND_IMPORTANT);
//使用aidl实现进程通信
class MyBinder extends ProcessService.Stub{
public String getServiceName() throws RemoteException {
return "I am FirstService";
//建立相互绑定时的连接
MyConn implements ServiceConnection {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("Info","与SecondService连接成功");
//在异常断开的回调方法进行拉起对方服务并绑定
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(FirstService.this,"SecondService被杀死",Toast.LENGTH_SHORT).show();
// 启动FirstService
FirstService.this.startService(new Intent(FirstService.this,SecondService.class));
//绑定FirstService
FirstService.this.bindService(new Intent(FirstService.this,SecondService.class),conn, Context.BIND_IMPORTANT);
服务进程提权
SecondService的设计和FirstService的设计差不多,都是在onStart中与对方相互绑定,在异常断开时重启对方并绑定。
SecondService多了一层服务进程提权设计(FirstService也可以加上这层设计):
public class SecondService extends Service {
private MyB
private MyC
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onCreate() {
super.onCreate();
binder = new MyBinder();
if(conn==null)
conn = new MyConn();
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//创建通知栏
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
//显示通知栏,服务进程提权为前台服务。
startForeground(250, builder.build());//使用id:250标记该通知栏
// 启动第三个服务ThirdService来消除通知栏
startService(new Intent(this,ThirdService.class));
SecondService.this.bindService(new Intent(this,FirstService.class),conn, Context.BIND_IMPORTANT);
class MyBinder extends ProcessService.Stub{
public String getServiceName() throws RemoteException {
return "I am SecondService";
MyConn implements ServiceConnection {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("Info","与FirtService连接成功"+SecondService.this.getApplicationInfo().processName);
public void onServiceDisconnected(ComponentName componentName) {
Toast.makeText(SecondService.this,"FirstService被杀死",Toast.LENGTH_SHORT).show();
// 启动FirstService
SecondService.this.startService(new Intent(SecondService.this,FirstService.class));
//绑定FirstService
SecondService.this.bindService(new Intent(SecondService.this,FirstService.class),conn, Context.BIND_IMPORTANT);
在ThirdService消除通知栏 :
public class ThirdService extends Service {
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public int onStartCommand(Intent intent, int flags, int startId) {
// 被启动后创建相互id的通知栏,并提权服务
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
startForeground(250, builder.build());
//开启新的线程消除通知栏
new Thread(new Runnable() {
public void run() {
SystemClock.sleep(1000);
stopForeground(true);//停止前台
NotificationManager manager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(250); // 消除通知栏
stopSelf(); // 停止服务
}).start();
return super.onStartCommand(intent, flags, startId);
最后在MainActivity或其他适当的地方启动FirstService和SecondService这两个服务:
this.startService(new Intent(this,FirstService.class));
this.startService(new Intent(this,SecondService.class));
服务进程保活效果
当应用处于后台时,双进程守护起很好的效果,但一方服务进程被杀掉时,另一方服务可即时地重启了被杀掉的服务进程。(也可以在设置-&应用-&正在运行中进行手动地杀死进程查看效果)
当FirstService和SecondService进行服务提权为前台服务时,可以躲过360卫士的手机加速的查杀。
(上述仅在vivo max5中测试过。下方为项目代码地址,可自行测试)
我的热门文章
即使是一小步也想与你分享Android实现双进程守护
做过开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论。这里先总结一下网上流传的各种解决方案,看看这些办法是不是真的可行。
1.提高优先级 这个办法对普通应用而言,应该只是降低了应用被杀死的概率,但是如果真的被系统回收了,还是无法让应用自动重新启动!
2.让service.onStartCommand返回START_STICKY
通过实验发现,如果在adb shell当中kill掉进程模拟应用被意外杀死的情况(或者用360手机卫士进行清理操作),如果服务的onStartCommand返回START_STICKY,在的进程管理器中会发现过一小会后被杀死的进程的确又会出现在任务管理器中,貌似这是一个可行的办法。但是如果在设置的App管理中选择强行关闭应用,这时候会发现即使onStartCommand返回了START_STICKY,应用还是没能重新启动起来!
3.android:persistent=&true&
网上还提出了设置这个属性的办法,通过实验发现即使设置了这个属性,应用程序被kill之后还是不能重新启动起来的!
4.让应用成为系统应用
实验发现即使成为系统应用,被杀死之后也不能自动重新启动。但是如果对一个系统应用设置了persistent=&true&,情况就不一样了。实验表明对一个设置了persistent属性的系统应用,即使kill掉会立刻重启。一个设置了persistent=&true&的系统应用,在中具有core service优先级,这种优先级的应用对系统的low memory killer是免疫的!
OK,说了半天,只有core service优先级的应用才能保证在被意外杀死之后做到立刻满血复活。而普通应用要想成为应用就必须要用目标机器的签名文件进行签名,但这样又造成了应用无法保证兼容所有不同厂商的产品。那么该怎么办呢?这里就来说一说双进程守护。网上也有人提到过双进程守护的办法,但是很少能搜索到类似的源码!如果从进程管理器重观察会发现新浪微博或者360卫视都有两个相关的进程,其中一个就是守护进程,由此可以猜到这些商业级的软件也采用了双进程守护的办法。
什么是双进程守护呢?顾名思义就是两个进程互相监视对方,发现对方挂掉就立刻重启!不知道应该把这样的一对进程是叫做相依为命呢还是难兄难弟好呢,但总之,双进程守护的确是一个解决问题的办法!相信说到这里,很多人已经迫切的想知道如何实现双进程守护了。这篇文章就介绍一个用NDK来实现双进程保护的办法,不过首先说明一点,下面要介绍的方法中,会损失不少的效率,反应到现实中就是会使手机的耗电量变大!但是这篇文章仅仅是抛砖引玉,相信看完之后会有更多高人指点出更妙的实现办法。
需要了解些什么?
这篇文章中实现双进程保护的方法基本上是纯的NDK开发,或者说全部是用C++来实现的,需要双进程保护的程序,只需要在程序的任何地方调用一下JAVA接口即可。下面几个知识点是需要了解的:
1.linux中多进程;
2.unix domain套接字实现跨进程通信;
3.linux的信号处理;Android 双进程守护尝试与分析
Android 双进程守护尝试与分析
&&&&&& 最近在做一个Android的项目,其包含一个消息推送的后台服务。由于该服务可能会有重要的信息推送,因此并不希望当APP程序退出、APP程序被一键清理、APP被强制停止等用户操作发生时,这个后台服务也随之被杀死。这个问题也就是所谓的“内存永驻”。关于这个问题,网上有很多说法,如调用startforehand函数以提高service的优先级、在service中创建一个不能被删掉的notification(或者产生一个其他的与用户界面交互的UI控件)、在service的onDestroy函数中重启这个服务、修改onstartcommand函数的返回值等等。这些方法,笔者都一一试过,但都没有效果。但是,我们可以看到市面上也确实存在一些App在一定的时间后可以自动重启,说明仍然是存在方法可以完成这项任务的。笔者在网上看到了这篇文章 http://94it.net/a/jingxuanboke/4671.html,觉得还是有些道理的。于是照着这个原理去做了。&&&&&& 这篇文章中介绍的方法涉及到Android的JNI编程,主要思想就是通过调用native函数创建一个子进程。父子进程相互监听,若子进程死去,父进程妥善处理后重新创建新的子进程;若父进程死去,子进程使用AM命令重启父进程。这种思想唯一的缺陷就是如何保证父子进程不被同时杀死的情况。子进程能不能被杀死,只能用实验来证明。&&&& 首先笔者按照文章介绍的,整理了代码,并将相关代码植入到自己的项目中。&&&& 步骤1)编写Watcher类。它为上面的Java程序调用提供必要的接口,声明需要native语言实现的的具体函数。native语言主要是指C/C++语言。上层的Java程序只需要创建一个Watcher类并调用它的createAppMonitor(String userId)函数即可。&public class Watcher {&& &private static final String PACKET = "com.example.dameonservice";&& &private String mMonitoredService = "com.example.mqtt.MQTTSubscribeService";&& &private volatile boolean bHeartBreak =&& &private Context mC&& &private boolean mRunning =&& &&& &public void createAppMonitor(String userId)&& &{&& &&& &if(!createWatcher(userId))&& &&& &{&& &&& &&& &Log.e("Watcher", "&&Monitor created failed&&");&& &&& &}&& &}&& &&& &public Watcher(Context context)&& &{&& &&& &mContext =&& &}&& && &/*创建一个监视子进程&& & *userId 当前进程的用户ID,子进程重启当前进程时需要用到当前进程的用户ID&& & *return& 若子进程创建成功返回TRUE,否则返回FALSE&& & */&& &private native boolean createWatcher(String userId);&& &&& &/* 让当前进程连接到监视进程&& & * return 连接成功返回TRUE,否则返回FALSE&& & */&& &private native boolean connectToMonitor();&& &&& &/*向监视进程发送任意信息&& & * msg 发给monitor的信息&& & * return 实际发送的字节数&& & */&& &private native int sendMsgToMonitor(String msg);&& &&& &static&& &{&& &&& &System.loadLibrary("monitor");&& //这里要和后面的Android.mk中模块名对应&& &}}2)编译上面的文件会在bin/classes 目录下生成相对应的Watcher.class文件,通过DOs界面进入该bin/classes 目录下,通过javah命令生成C/C++对应的头文件。“javah 包名+类名”&& 得到以下头文件:&#include &jni.h&/* Header for class com_example_dameonservice_Watcher */#ifndef _Included_com_example_dameonservice_Watcher#define _Included_com_example_dameonservice_Watcher#ifdef __cplusplusextern "C" {#endif/*&* Class:&&&& com_example_dameonservice_Watcher&* Method:&&& createWatcher&* Signature: (Ljava/lang/S)Z&*/JNIEXPORT jboolean JNICALL Java_com_example_dameonservice_Watcher_createWatcher& (JNIEnv *, jobject, jstring);/*&* Class:&&&& com_example_dameonservice_Watcher&* Method:&&& connectToMonitor&* Signature: ()Z&*/JNIEXPORT jboolean JNICALL Java_com_example_dameonservice_Watcher_connectToMonitor& (JNIEnv *, jobject);/*&* Class:&&&& com_example_dameonservice_Watcher&* Method:&&& sendMsgToMonitor&* Signature: (Ljava/lang/S)I&*/JNIEXPORT jint JNICALL Java_com_example_dameonservice_Watcher_sendMsgToMonitor& (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif3)创建JNI文件夹,将得到的头文件移到该文件夹下,继续在该文件夹下创建与上面得到的头文件同名的C/C++文件,然后实现头文件中提到的方法。(具体实现太多,这里就不再贴出来了)4)添加Android.mk文件。这个文件的格式基本是统一的。只需要修改LOCAL_MODULE和LOCAL_SRC_FILES两处即可。如果你还有添加Log打印函数,还要在这里添加 “LOCAL_LDLIBS := -lm -llog”。下面一张图来说明整体的文件结构分布:&其中com_example_dameonservice_Watcher.c和com_example_dameonservice_Watcher.cpp内容相同。process.cpp定义一些辅助类。实验结果:&&&&&& 这当然是大家最关心的。测试的手机选用的小米,感觉 小米在这一块的优化还是很不错的,所以用它来试试。最终的测试结果是:被杀死的服务概率性地可以重启成功,且失败的概率更大。通过Log分析,不能重启的时候是因为子进程也死掉了。截止到笔者写下这篇文章,还没有抓住其中的规律。一键清理和子进程的被杀死没有绝对的对应关系。而且即使是在App运行的时候,也会发现子进程会被杀死,然后又被父进程重启。子进程被杀死是重启失败的主要原因。但现在的现象无法确定子进程被杀死的确切原因,有一种可能是被系统杀死了,但这样的不确定性太大,对效果也不能有很好的保证。&&&&& 虽然没有完美解决问题,但至少比前面的办法强很多,至少它也重启成功过。这个方法感觉继续优化一下还是可以做好的。
发表评论:
TA的最新馆藏[转]&[转]&&&&&android双进程守护,进程很难被杀死demo
android双进程守护,进程很难被杀死demo
android双进程守护,进程很难被杀死
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
移动开发下载排行本文分为两个部分,第一部分为双Service守护,第二部分为双进程守护
第一部分:
一、Service简介:.lang.Object
&&?.content.Context
&&&&&&?android.content.ContextWrapper
&&&&&&&&&&?android.app.Service
Service是应用程序Application的一个组件(component)。它的作用有两点:1.用来提供一个长期在后台运行并且不与用户交互的操作,2.也可以为其他应用程序提供服务。Service必须和其他四大组件一样,使用&service&标签在AndroidManifest.xml中进行声明。启动service有两种方式Context.startService() 和 Context.bindService()。
注意,除了特别指定外,service并不是单独的进程,一般service在其宿主进程的主线程(UI Thread)中运行【当然也可以在新的线程中startService,这样Service就不是在MainThread了】。这意味着,如果您的服务要做任何 耗时(如 MP3 播放) 或阻塞 (比如网络) 操作,它应该产生它自己的线程,用来做那项工作。(service不是单独的进程也不是单独的线程)
Service提供了两大功能:Context.startService()用来在后台启动一个服务;Context.bindService()用来绑定其他服务,以此来获取其他service提供的服务;
本地服务 Local Service&用于应用程序内部
它可以启动并运行,直至有人停止了它或它自己停止。在这种方式下,它以调用Context.startService()启动,而以调用Context.stopService()结束。它可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。不论调用了多少次startService()方法,你只需要调用一次stopService()来停止服务。
【用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好】
远程服务 Remote Service&用于android系统内部的应用程序之间
它可以通过自己定义并暴露出来的接口进行程序操作。客户端建立一个到服务对象的连接,并通过那个连接来调用服务。连接以调用Context.bindService()方法建立,以调用 Context.unbindService()关闭。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
【可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可】
二、Service运行方式和生命周期图:
以startService()启动服务,系统将通过传入的Intent在底层搜索相关符合Intent里面信息的service。如果服务没有启动则先运行onCreate,然后运行onStartCommand (可在里面处理启动时传过来的Intent和其他参数),直到明显调用stopService或者stopSelf才将停止Service。无论运行startService多少次,只要调用一次stopService或者stopSelf,Service都会停止。使用stopSelf(int)方法可以保证在处理好intent后再停止。onStartCommand ,在2.0后被引入用于service的启动函数,2.0之前为public void onStart(Intent intent, int startId) 。
以bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。采用Context.bindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法。
(注意这个新老API的改变)
void onStart(Intent intent, int startId)This method was deprecated&&&&& in API level 5.&&& Implement onStartCommand(Intent, int, int) instead.
int onStartCommand(Intent intent, int flags, int startId)Called by the system every time a client explicitly starts the service by calling& startService(Intent), providing the arguments it supplied and a& unique integer token representing the start request.
三、Service的优先级
官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1. 如果service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以避免被killed。2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。5. 如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
四、保持service不被kill掉
START_STICKY is used for services that are explicitly started and stopped as needed, while START_NOT_STICKY or START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them
onStartCommand方法几个返回值简介:&1、START_STICKY&在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建&&&& service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。&2、START_NOT_STICKY&在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。&3、START_REDELIVER_INTENT&在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。
@Override&&
public&int&onStartCommand(Intent&intent,&int&flags,&int&startId)&{&&
&&&&flags&=&START_STICKY;&&
&&&&return&super.onStartCommand(intent,&flags,&startId);&&
【结论】 手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证任何情况下都被重建,比如进程被干掉了....
提升service优先级
&在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
&service&&
&&&&android:name="com.dbjtech.acbxt.waiqin.UploadService"&&
&&&&android:enabled="true"&&&&
&&&&&intent-filter&android:priority="1000"&&&&
&&&&&&&&&action&android:name="com.dbjtech.myservice"&/&&&
&&&&&/intent-filter&&&
&/service&&&
【结论】目前看来,priority这个属性貌似只适用于broadcast,对于Service来说可能无效
提升service进程优先级
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
&& 1.前台进程( FOREGROUND_APP)&& 2.可视进程(VISIBLE_APP )&& 3. 次要服务进程(SECONDARY_SERVER )&& 4.后台进程 (HIDDEN_APP)&& 5.内容供应节点(CONTENT_PROVIDER)&& 6.空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground将service放到前台状态。这样在低内存时被kill的几率会低一些。
在onStartCommand方法内添加如下代码:
Notification&notification&=&new&Notification(R.drawable.ic_launcher,getString(R.string.app_name),&System.currentTimeMillis());&&
PendingIntent&pendingintent&=&PendingIntent.getActivity(this,&0,new&Intent(this,&AppMain.class),&0);&&
notification.setLatestEventInfo(this,&"uploadservice",&"请保持程序在后台运行",&pendingintent);&&
&&&&&&&&&&&&&&startForeground(0x111,&notification);&&
注意在onDestroy里还需要stopForeground(true),运行时在下拉列表会看到自己的APP在:
【结论】如果在极度极度低内存的压力下,该service还是会被kill掉,并且不一定会restart&
保持Service不被Kill掉的方法--双Service守护,代码如下:
AndroidManifest.xml:
&activity&&
&&&&&&&&android:name=".MainActivity"&&
&&&&&&&&android:label="@string/app_name"&&&&
&&&&&&&&&intent-filter&&&
&&&&&&&&&&&&&action&android:name="android.intent.action.MAIN"&/&&&
&&&&&&&&&&&&&category&android:name="android.intent.category.LAUNCHER"&/&&&
&&&&&&&&&/intent-filter&&&
&&&&&/activity&&&
&&&&&service&&
&&&&&&&&android:name="ServiceOne"&&
&&&&&&&&android:process=":remote"&&&&
&&&&&&&&&intent-filter&&&
&&&&&&&&&&&&&action&android:name="com.example.servicedemo.ServiceOne"&/&&&
&&&&&&&&&/intent-filter&&&
&&&&&/service&&&
&&&&&service&&
&&&&&&&&android:name="ServiceTwo"&&
&&&&&&&&android:process=":remote"&&&&
&&&&&&&&&intent-filter&&&
&&&&&&&&&&&&&action&android:name="com.example.servicedemo.ServiceTwo"&/&&&
&&&&&&&&&/intent-filter&&&
&&&&&/service&&&
MainActivity.java:
package&com.example.&&
import&java.util.ArrayL&&
import&android.app.A&&
import&android.app.ActivityM&&
import&android.app.ActivityManager.RunningServiceI&&
import&android.content.C&&
import&android.content.I&&
import&android.os.B&&
public&class&MainActivity&extends&Activity&{&&
&&&&@Override&&
&&&&protected&void&onCreate(Bundle&savedInstanceState)&{&&
&&&&&&&&super.onCreate(savedInstanceState);&&
&&&&&&&&setContentView(R.layout.activity_main);&&
&&&&&&&&Intent&serviceOne&=&new&Intent();&&
&&&&&&&&serviceOne.setClass(MainActivity.this,&ServiceOne.class);&&
&&&&&&&&startService(serviceOne);&&
&&&&&&&&Intent&serviceTwo&=&new&Intent();&&
&&&&&&&&serviceTwo.setClass(MainActivity.this,&ServiceTwo.class);&&
&&&&&&&&startService(serviceTwo);&&
&&&&public&static&boolean&isServiceWorked(Context&context,&String&serviceName)&{&&
&&&&&&&&ActivityManager&myManager&=&(ActivityManager)&context.getSystemService(Context.ACTIVITY_SERVICE);&&
&&&&&&&&ArrayList&RunningServiceInfo&&runningService&=&(ArrayList&RunningServiceInfo&)&myManager.getRunningServices(Integer.MAX_VALUE);&&
&&&&&&&&for&(int&i&=&0;&i&&&runningService.size();&i++)&{&&
&&&&&&&&&&&&if&(runningService.get(i).service.getClassName().toString().equals(serviceName))&{&&
&&&&&&&&&&&&&&&&return&&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&&&&&return&&&
ServiceOne.java:
package&com.example.&&
import&java.util.T&&
import&java.util.TimerT&&
import&android.app.S&&
import&android.content.I&&
import&android.os.IB&&
import&android.util.L&&
public&class&ServiceOne&extends&Service&{&&
&&&&public&final&static&String&TAG&=&"com.example.servicedemo.ServiceOne";&&
&&&&@Override&&
&&&&public&int&onStartCommand(Intent&intent,&int&flags,&int&startId)&{&&
&&&&&&&&Log.e(TAG,&"onStartCommand");&&
&&&&&&&&&&
&&&&&&&&thread.start();&&
&&&&&&&&return&START_STICKY;&&
&&&&Thread&thread&=&new&Thread(new&Runnable()&{&&
&&&&&&&&&&
&&&&&&&&@Override&&
&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&Timer&timer&=&new&Timer();&&
&&&&&&&&&&&&TimerTask&task&=&new&TimerTask()&{&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&&&&&&&&&Log.e(TAG,&"ServiceOne&Run:&"+System.currentTimeMillis());&&
&&&&&&&&&&&&&&&&&&&&boolean&b&=&MainActivity.isServiceWorked(ServiceOne.this,&"com.example.servicedemo.ServiceTwo");&&
&&&&&&&&&&&&&&&&&&&&if(!b)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&Intent&service&=&new&Intent(ServiceOne.this,&ServiceTwo.class);&&
&&&&&&&&&&&&&&&&&&&&&&&&startService(service);&&
&&&&&&&&&&&&&&&&&&&&&&&&Log.e(TAG,&"Start&ServiceTwo");&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&};&&
&&&&&&&&&&&&timer.schedule(task,&0,&1000);&&
&&&&&&&&}&&
&&&&@Override&&
&&&&public&IBinder&onBind(Intent&arg0)&{&&
&&&&&&&&return&&&
ServiceTwo.java:
package&com.example.&&
import&java.util.T&&
import&java.util.TimerT&&
import&android.app.S&&
import&android.content.I&&
import&android.os.IB&&
import&android.util.L&&
public&class&ServiceTwo&extends&Service&{&&
&&&&public&final&static&String&TAG&=&"com.example.servicedemo.ServiceTwo";&&
&&&&@Override&&
&&&&public&int&onStartCommand(Intent&intent,&int&flags,&int&startId)&{&&
&&&&&&&&Log.e(TAG,&"onStartCommand");&&
&&&&&&&&thread.start();&&
&&&&&&&&return&START_REDELIVER_INTENT;&&
&&&&Thread&thread&=&new&Thread(new&Runnable()&{&&
&&&&&&&&@Override&&
&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&Timer&timer&=&new&Timer();&&
&&&&&&&&&&&&TimerTask&task&=&new&TimerTask()&{&&
&&&&&&&&&&&&&&&&@Override&&
&&&&&&&&&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&&&&&&&&&Log.e(TAG,&"ServiceTwo&Run:&"&+&System.currentTimeMillis());&&
&&&&&&&&&&&&&&&&&&&&boolean&b&=&MainActivity.isServiceWorked(ServiceTwo.this,&"com.example.servicedemo.ServiceOne");&&
&&&&&&&&&&&&&&&&&&&&if(!b)&{&&
&&&&&&&&&&&&&&&&&&&&&&&&Intent&service&=&new&Intent(ServiceTwo.this,&ServiceOne.class);&&
&&&&&&&&&&&&&&&&&&&&&&&&startService(service);&&
&&&&&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&};&&
&&&&&&&&&&&&timer.schedule(task,&0,&1000);&&
&&&&&&&&}&&
&&&&@Override&&
&&&&public&IBinder&onBind(Intent&arg0)&{&&
&&&&&&&&return&&&
第二部分:
做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论。这里先总结一下网上流传的各种解决方案,看看这些办法是不是真的可行。1.提高优先级这个办法对普通应用而言,应该只是降低了应用被杀死的概率,但是如果真的被系统回收了,还是无法让应用自动重新启动!&&&&2.让service.onStartCommand返回START_STICKY通过实验发现,如果在adb shell当中kill掉进程模拟应用被意外杀死的情况(或者用360手机卫士进行清理操作),如果服务的onStartCommand返回START_STICKY,在eclipse的进程管理器中会发现过一小会后被杀死的进程的确又会出现在任务管理器中,貌似这是一个可行的办法。但是如果在系统设置的App管理中选择强行关闭应用,这时候会发现即使onStartCommand返回了START_STICKY,应用还是没能重新启动起来!
3.android:persistent="true"网上还提出了设置这个属性的办法,通过实验发现即使设置了这个属性,应用程序被kill之后还是不能重新启动起来的!
4.让应用成为系统应用实验发现即使成为系统应用,被杀死之后也不能自动重新启动。但是如果对一个系统应用设置了persistent="true",情况就不一样了。实验表明对一个设置了persistent属性的系统应用,即使kill掉会立刻重启。一个设置了persistent="true"的系统应用,在android中具有core service优先级,这种优先级的应用对系统的low memory killer是免疫的!
OK,说了半天,只有core service优先级的应用才能保证在被意外杀死之后做到立刻满血复活。而普通应用要想成为系统应用就必须要用目标机器的签名文件进行签名,但这样又造成了应用无法保证兼容所有不同厂商的产品。那么该怎么办呢?这里就来说一说双进程守护。网上也有人提到过双进程守护的办法,但是很少能搜索到类似的源码!如果从进程管理器重观察会发现新浪微博或者360卫视都有两个相关的进程,其中一个就是守护进程,由此可以猜到这些商业级的软件也采用了双进程守护的办法。
什么是双进程守护呢?顾名思义就是两个进程互相监视对方,发现对方挂掉就立刻重启!不知道应该把这样的一对进程是叫做相依为命呢还是难兄难弟好呢,但总之,双进程守护的确是一个解决问题的办法!相信说到这里,很多人已经迫切的想知道如何实现双进程守护了。这篇文章就介绍一个用NDK来实现双进程保护的办法,不过首先说明一点,下面要介绍的方法中,会损失不少的效率,反应到现实中就是会使手机的耗电量变大!但是这篇文章仅仅是抛砖引玉,相信看完之后会有更多高人指点出更妙的实现办法。
需要了解些什么?这篇文章中实现双进程保护的方法基本上是纯的NDK开发,或者说全部是用C++来实现的,需要双进程保护的程序,只需要在程序的任何地方调用一下JAVA接口即可。下面几个知识点是需要了解的:1.linux中多进程;2.unix domain套接字实现跨进程通信;3.linux的信号处理;4.exec函数族的用法;
其实这些东西本身并不是多复杂的技术,只是我们把他们组合起来实现了一个双进程守护而已,没有想象中那么神秘!在正式贴出代码之前,先来说说几个实现双进程守护时的关键点:1.父进程如何监视到子进程(监视进程)的死亡?很简单,在linux中,子进程被终止时,会向父进程发送SIG_CHLD信号,于是我们可以安装信号处理函数,并在此信号处理函数中重新启动创建监视进程;2.子进程(监视进程)如何监视到父进程死亡?当父进程死亡以后,子进程就成为了孤儿进程由Init进程领养,于是我们可以在一个循环中读取子进程的父进程PID,当变为1就说明其父进程已经死亡,于是可以重启父进程。这里因为采用了循环,所以就引出了之前提到的耗电量的问题。3.父子进程间的通信有一种办法是父子进程间建立通信通道,然后通过监视此通道来感知对方的存在,这样不会存在之前提到的耗电量的问题,在本文的实现中,为了简单,还是采用了轮询父进程PID的办法,但是还是留出了父子进程的通信通道,虽然暂时没有用到,但可备不时之需!
腾讯的面试官问我:应用程序死了如何恢复?确实,双进程守护只能做到进程被杀死后重新启动,但是重启后如何恢复到之前的状态这是一个问题。因为进程被意外杀死的情况,onSaveInstance是来不及执行的,所以程序的状态没法保存!对于双进程守护来说,不知道是不是可以再父进程进入后台以后(onStop),把数据收集起来保存到子进程中,然后父进程重启以后从子进程中取出这些信息呢?这是一个办法,但是上面说明的双进程守护程序的实现中还做不到,因为父进程重启以后,子进程也挂掉重新建立了,要想实现优雅的恢复,还得在做出点改进才是!只能实时保存数据到等。
Android实现双进程守护 - 天山折梅 - 博客频道 - CSDN.NET
阅读(...) 评论()

我要回帖

更多关于 c 守护进程 的文章

 

随机推荐