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