android双进程守护耗电,Android实现双进程守护
做過(guò)android開(kāi)發(fā)的人應(yīng)該都知道應(yīng)用會(huì)在系統(tǒng)資源匱乏的情況下被系統(tǒng)殺死!當(dāng)后臺(tái)的應(yīng)用被系統(tǒng)回收之后,如何重新恢復(fù)它呢?網(wǎng)上對(duì)此問(wèn)題有很多的討論。這里先總結(jié)一下網(wǎng)上流傳的各種解決方案,看看這些辦法是不是真的可行。
1.提高優(yōu)先級(jí)
這個(gè)辦法對(duì)普通應(yīng)用而言,應(yīng)該只是降低了應(yīng)用被殺死的概率,但是如果真的被系統(tǒng)回收了,還是無(wú)法讓應(yīng)用自動(dòng)重新啟動(dòng)!
2.讓service.onStartCommand返回START_STICKY
通過(guò)實(shí)驗(yàn)發(fā)現(xiàn),如果在adb shell當(dāng)中kill掉進(jìn)程模擬應(yīng)用被意外殺死的情況(或者用360手機(jī)衛(wèi)士進(jìn)行清理操作),如果服務(wù)的onStartCommand返回START_STICKY,在eclipse的進(jìn)程管理器中會(huì)發(fā)現(xiàn)過(guò)一小會(huì)后被殺死的進(jìn)程的確又會(huì)出現(xiàn)在任務(wù)管理器中,貌似這是一個(gè)可行的辦法。但是如果在系統(tǒng)設(shè)置的App管理中選擇強(qiáng)行關(guān)閉應(yīng)用,這時(shí)候會(huì)發(fā)現(xiàn)即使onStartCommand返回了START_STICKY,應(yīng)用還是沒(méi)能重新啟動(dòng)起來(lái)!
3.android:persistent=”true”
網(wǎng)上還提出了設(shè)置這個(gè)屬性的辦法,通過(guò)實(shí)驗(yàn)發(fā)現(xiàn)即使設(shè)置了這個(gè)屬性,應(yīng)用程序被kill之后還是不能重新啟動(dòng)起來(lái)的!
4.讓應(yīng)用成為系統(tǒng)應(yīng)用
實(shí)驗(yàn)發(fā)現(xiàn)即使成為系統(tǒng)應(yīng)用,被殺死之后也不能自動(dòng)重新啟動(dòng)。但是如果對(duì)一個(gè)系統(tǒng)應(yīng)用設(shè)置了persistent=”true”,情況就不一樣了。實(shí)驗(yàn)表明對(duì)一個(gè)設(shè)置了persistent屬性的系統(tǒng)應(yīng)用,即使kill掉會(huì)立刻重啟。一個(gè)設(shè)置了persistent=”true”的系統(tǒng)應(yīng)用,在android中具有core service優(yōu)先級(jí),這種優(yōu)先級(jí)的應(yīng)用對(duì)系統(tǒng)的low memory killer是免疫的!
OK,說(shuō)了半天,只有core service優(yōu)先級(jí)的應(yīng)用才能保證在被意外殺死之后做到立刻滿血復(fù)活。而普通應(yīng)用要想成為系統(tǒng)應(yīng)用就必須要用目標(biāo)機(jī)器的簽名文件進(jìn)行簽名,但這樣又造成了應(yīng)用無(wú)法保證兼容所有不同廠商的產(chǎn)品。那么該怎么辦呢?這里就來(lái)說(shuō)一說(shuō)雙進(jìn)程守護(hù)。網(wǎng)上也有人提到過(guò)雙進(jìn)程守護(hù)的辦法,但是很少能搜索到類似的源碼!如果從進(jìn)程管理器重觀察會(huì)發(fā)現(xiàn)新浪微博或者360衛(wèi)視都有兩個(gè)相關(guān)的進(jìn)程,其中一個(gè)就是守護(hù)進(jìn)程,由此可以猜到這些商業(yè)級(jí)的軟件也采用了雙進(jìn)程守護(hù)的辦法。
什么是雙進(jìn)程守護(hù)呢?顧名思義就是兩個(gè)進(jìn)程互相監(jiān)視對(duì)方,發(fā)現(xiàn)對(duì)方掛掉就立刻重啟!不知道應(yīng)該把這樣的一對(duì)進(jìn)程是叫做相依為命呢還是難兄難弟好呢,但總之,雙進(jìn)程守護(hù)的確是一個(gè)解決問(wèn)題的辦法!相信說(shuō)到這里,很多人已經(jīng)迫切的想知道如何實(shí)現(xiàn)雙進(jìn)程守護(hù)了。這篇文章就介紹一個(gè)用NDK來(lái)實(shí)現(xiàn)雙進(jìn)程保護(hù)的辦法,不過(guò)首先說(shuō)明一點(diǎn),下面要介紹的方法中,會(huì)損失不少的效率,反應(yīng)到現(xiàn)實(shí)中就是會(huì)使手機(jī)的耗電量變大!但是這篇文章僅僅是拋磚引玉,相信看完之后會(huì)有更多高人指點(diǎn)出更妙的實(shí)現(xiàn)辦法。
需要了解些什么?
這篇文章中實(shí)現(xiàn)雙進(jìn)程保護(hù)的方法基本上是純的NDK開(kāi)發(fā),或者說(shuō)全部是用C++來(lái)實(shí)現(xiàn)的,需要雙進(jìn)程保護(hù)的程序,只需要在程序的任何地方調(diào)用一下JAVA接口即可。下面幾個(gè)知識(shí)點(diǎn)是需要了解的:
1.linux中多進(jìn)程;
2.unix domain套接字實(shí)現(xiàn)跨進(jìn)程通信;
3.linux的信號(hào)處理;
4.exec函數(shù)族的用法;
其實(shí)這些東西本身并不是多復(fù)雜的技術(shù),只是我們把他們組合起來(lái)實(shí)現(xiàn)了一個(gè)雙進(jìn)程守護(hù)而已,沒(méi)有想象中那么神秘!在正式貼出代碼之前,先來(lái)說(shuō)說(shuō)幾個(gè)實(shí)現(xiàn)雙進(jìn)程守護(hù)時(shí)的關(guān)鍵點(diǎn):
1.父進(jìn)程如何監(jiān)視到子進(jìn)程(監(jiān)視進(jìn)程)的死亡?
很簡(jiǎn)單,在linux中,子進(jìn)程被終止時(shí),會(huì)向父進(jìn)程發(fā)送SIG_CHLD信號(hào),于是我們可以安裝信號(hào)處理函數(shù),并在此信號(hào)處理函數(shù)中重新啟動(dòng)創(chuàng)建監(jiān)視進(jìn)程;
2.子進(jìn)程(監(jiān)視進(jìn)程)如何監(jiān)視到父進(jìn)程死亡?
當(dāng)父進(jìn)程死亡以后,子進(jìn)程就成為了孤兒進(jìn)程由Init進(jìn)程領(lǐng)養(yǎng),于是我們可以在一個(gè)循環(huán)中讀取子進(jìn)程的父進(jìn)程PID,當(dāng)變?yōu)?就說(shuō)明其父進(jìn)程已經(jīng)死亡,于是可以重啟父進(jìn)程。這里因?yàn)椴捎昧搜h(huán),所以就引出了之前提到的耗電量的問(wèn)題。
3.父子進(jìn)程間的通信
有一種辦法是父子進(jìn)程間建立通信通道,然后通過(guò)監(jiān)視此通道來(lái)感知對(duì)方的存在,這樣不會(huì)存在之前提到的耗電量的問(wèn)題,在本文的實(shí)現(xiàn)中,為了簡(jiǎn)單,還是采用了輪詢父進(jìn)程PID的辦法,但是還是留出了父子進(jìn)程的通信通道,雖然暫時(shí)沒(méi)有用到,但可備不時(shí)之需!
OK, 下面就貼上代碼!首先是Java部分,這一部分太過(guò)簡(jiǎn)單,只是一個(gè)類,提供了給外部調(diào)用的API接口用于創(chuàng)建守護(hù)進(jìn)程,所有的實(shí)現(xiàn)都通過(guò)native方法在C++中完成!
package com.example.dameonservice;
import?java.util.ArrayList;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import?android.util.Log;
/**
*?監(jiān)視器類,構(gòu)造時(shí)將會(huì)在Native創(chuàng)建子進(jìn)程來(lái)監(jiān)視當(dāng)前進(jìn)程,
*@authorwangqiang
* @date 2014-04-24
*/
public class Watcher
{
//TODO Fix this according to your service
private static final String PACKAGE = “com.example.dameonservice/”;
private String mMonitoredService = “”;
private volatile boolean bHeartBreak = false;
private Context mContext;
private boolean mRunning = true;
public void createAppMonitor(String userId)
{
if( !createWatcher(userId) )
{
Log.e(“Watcher”, “<>”);
}
}
public Watcher( Context context)
{
mContext = context;
}
private int isServiceRunning()
{
ActivityManager am=(ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList runningService = (ArrayList)am.getRunningServices(1024);
for( int i = 0; i < runningService.size(); ++i )
{
if( mMonitoredService.equals(runningService.get(i).service.getClassName().toString() ))
{
return 1;
}
}
return 0;
}
/**
* Native方法,創(chuàng)建一個(gè)監(jiān)視子進(jìn)程.
*@paramuserId 當(dāng)前進(jìn)程的用戶ID,子進(jìn)程重啟當(dāng)前進(jìn)程時(shí)需要用到當(dāng)前進(jìn)程的用戶ID.
*@return如果子進(jìn)程創(chuàng)建成功返回true,否則返回false
*/
private native boolean createWatcher(String userId);
/**
* Native方法,讓當(dāng)前進(jìn)程連接到監(jiān)視進(jìn)程.
*@return連接成功返回true,否則返回false
*/
private native boolean connectToMonitor();
/**
* Native方法,向監(jiān)視進(jìn)程發(fā)送任意信息
* @param 發(fā)給monitor的信息
* @return 實(shí)際發(fā)送的字節(jié)
*/
private native int sendMsgToMonitor(String msg);
static
{
System.loadLibrary(“monitor”);
}
}
代碼中很多屬性都是測(cè)試時(shí)用的,懶得去掉,其實(shí)有些都沒(méi)用到。只需要關(guān)心createAppMonitor這個(gè)對(duì)外接口就可以了,它要求傳入一個(gè)當(dāng)前進(jìn)程的用戶ID,然后會(huì)調(diào)用createWatcher本地方法來(lái)創(chuàng)建守護(hù)進(jìn)程。還有兩個(gè)方法connectToMonitor用于創(chuàng)建和監(jiān)視進(jìn)程的socket通道,sendMsgToMonitor用于通過(guò)socket向子進(jìn)程發(fā)送數(shù)據(jù)。由于暫時(shí)不需要和子進(jìn)程進(jìn)行數(shù)據(jù)交互,所以這兩個(gè)方法就沒(méi)有添加對(duì)外的JAVA接口,但是要添加簡(jiǎn)直是輕而易舉的事!
Ok,JAVA只是個(gè)殼,內(nèi)部的實(shí)現(xiàn)還得是C++,為了讓程序更加的面向?qū)ο?#xff0c;在實(shí)現(xiàn)native時(shí),我們用一個(gè)ProcessBase基類來(lái)對(duì)父子進(jìn)程進(jìn)行一個(gè)抽象,把父子進(jìn)程都會(huì)有的行為抽象出來(lái),而父子進(jìn)程可以根據(jù)需要用自己的方式去實(shí)現(xiàn)其中的接口,先來(lái)看看這個(gè)抽象了父子進(jìn)程共同行為的ProcessBase基類:
#ifndef _PROCESS_H
#define _PROCESS_H
#include
#include
#include
總結(jié)
以上是生活随笔為你收集整理的android双进程守护耗电,Android实现双进程守护的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: uygurqa输入法android,uy
- 下一篇: unity3d能和java系统整合吗_A