當前位置:首頁 » 安卓系統 » android服務與進程

android服務與進程

發布時間: 2023-03-03 12:50:58

❶ Android 如何進行進程保活

每一個 Android 應用啟動後至少對應一個進程,有的是多個進程,而且主流應用中多個

進程的應用比例較大

對於任何一個進程,我們都可以通過 adb shell ps|grep <package_name>的方式來查看

它的基本信息

Android 中的進程跟封建社會一樣,分了三流九等,Android 系統把進程的劃為了如下

幾種(重要性從高到低),網上多位大神都詳細總結過(備註:嚴格來說是劃分了 6 種)。

場景:

1.某個進程持有一個正在與用戶交互的 Activity 並且該 Activity 正處於 resume 的

狀態。

2.某個進程持有一個 Service,並且該 Service 與用戶正在交互的 Activity 綁定。

3.某個進程持有一個 Service,並且該 Service 調用 startForeground()方法使之位於前台運行。

4.某個進程持有一個 Service,並且該 Service 正在執行它的某個生命周期回調方法,比如 onCreate()、 onStart()或 onDestroy()。

5.某個進程持有一個 BroadcastReceiver,並且該 BroadcastReceiver 正在執行其onReceive()方法。用戶正在使用的程序,一般系統是不會殺死前台進程的,除非用戶強制停止應用或者系統內存不足等極端情況會殺死。

場景:

1.擁有不在前台、但仍對用戶可見的 Activity(已調用 onPause())。

2.擁有綁定到可見(或前台)Activity 的 Service

用戶正在使用,看得到,但是摸不著,沒有覆蓋到整個屏幕,只有屏幕的一部分可見進程

不包含任何前台組件,一般系統也是不會殺死可見進程的,除非要在資源吃緊的情況下,

要保持某個或多個前台進程存活

場景

1.某個進程中運行著一個 Service 且該 Service 是通過 startService()啟動的,與用戶看見的界面沒有直接關聯。

在內存不足以維持所有前台進程和可見進程同時運行的情況下,服務進程會被殺死

場景:

在用戶按了"back"或者"home"後,程序本身看不到了,但是其實還在運行的程序,

比如 Activity 調用了 onPause 方法系統可能隨時終止它們,回收內存

場景:

某個進程不包含任何活躍的組件時該進程就會被置為空進程,完全沒用,殺了它只有好處沒壞處,第一個干它!

上面是進程的分類,進程是怎麼被殺的呢?系統出於體驗和性能上的考慮,app 在退到

後台時系統並不會真正的 kill 掉這個進程,而是將其緩存起來。打開的應用越多,後台緩存的進程也越多。在系統內存不足的情況下,系統開始依據自身的一套進程回收機制

來判斷要 kill 掉哪些進程,以騰出內存來供給需要的 app, 這套殺進程回收內存的機制

就叫 Low Memory Killer。那這個不足怎麼來規定呢,那就是內存閾值,我們可以使用

cat /sys/mole/lowmemorykiller/parameters/minfree 來查看某個手機的內存閾值。

其實系統在進程回收跟內存回收類似也是有一套嚴格的策略,可以

自己去了解,大概是這個樣子的,oom_adj 越大,佔用物理內存越多會被最先 kill 掉,OK,那麼現在對於進程如何保活這個問題就轉化成,如何降低 oom_adj 的值,以及如

何使得我們應用占的內存最少。

據說這個是手 Q 的進程保活方案,基本思想,系統一般是不會殺死前台進程的。所以要

使得進程常駐,我們只需要在鎖屏的時候在本進程開啟一個 Activity,為了欺騙用戶,

讓這個 Activity 的大小是 1 像素,並且透明無切換動畫,在開屏幕的時候,把這個 Activity

關閉掉,所以這個就需要監聽系統鎖屏廣播,我試過了,的確好使,如下。

如果直接啟動一個 Activity,當我們按下 back 鍵返回桌面的時候,oom_adj 的值是 8,

上面已經提到過,這個進程在資源不夠的情況下是容易被回收的。現在造一個一個像素

的 Activity。

為了做的更隱藏,最好設置一下這個 Activity 的主題,當然也無所謂了

在屏幕關閉的時候把 LiveActivity 啟動起來,在開屏的時候把 LiveActivity 關閉掉,所以

要監聽系統鎖屏廣播,以介面的形式通知 MainActivity 啟動或者關閉 LiveActivity。

現在 MainActivity 改成如下

按下 back 之後,進行鎖屏,現在測試一下 oom_adj 的值

果然將進程的優先順序提高了。

但是還有一個問題,內存也是一個考慮的因素,內存越多會被最先 kill 掉,所以把上面

的業務邏輯放到 Service 中,而 Service 是在另外一個 進程中,在 MainActivity 開啟這

個服務就行了,這樣這個進程就更加的輕量,

OK,通過上面的操作,我們的應用就始終和前台進程是一樣的優先順序了,為了省電,

系統檢測到鎖屏事件後一段時間內會殺死後台進程,如果採取這種方案,就可以避免了

這個問題。但是還是有被殺掉的可能,所以我們還需要做雙進程守護,關於雙進程守護,

比較適合的就是 aidl 的那種方式,但是這個不是完全的靠譜,原理是 A 進程死的時候,

B 還在活著,B 可以將 A 進程拉起來,反之,B 進程死的時候,A 還活著,A 可以將 B

拉起來。所以雙進程守護的前提是,系統殺進程只能一個個的去殺,如果一次性殺兩個,

這種方法也是不 OK 的。

事實上

那麼我們先來看看 Android5.0 以下的源碼,ActivityManagerService 是如何關閉在應用

退出後清理內存的

在應用退出後,ActivityManagerService 不僅把主進程給殺死,另外把主進程所屬的進

程組一並殺死,這樣一來,由於子進程和主進程在同一進程組,子進程在做的事情,也

就停止了。所以在 Android5.0 以後的手機應用在進程被殺死後,要採用其他方案。

這種大部分人都了解,據說這個微信也用過的進程保活方案,移步微信 Android 客戶端

後台保活經驗分享,這方案實際利用了 Android 前台 service 的漏洞。

原理如下

對於 API level < 18 :調用 startForeground(ID, new Notification()),發送空的

Notification ,圖標則不會顯示。

對於 API level >= 18:在需要提優先順序的 service A 啟動一個 InnerService,兩個服務

同時 startForeground,且綁定同樣的 ID。Stop 掉 InnerService ,這樣通知欄圖標即

被移除。

public class KeepLiveService extends Service{

public static final int NOTIFICATION_ID=0x11; 

public KeepLiveService() {

}

@Override

public IBinder onBind(Intent intent){

throw new UnsupportedOperationException("Not yet implemented");

 }

 @Override 

public void onCreate() {

 super.onCreate(); //API 18 以下,直 接發 送 Notification 並 將 其 置 為 前 台

if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN_MR2){

startForeground(NOTIFICATION_ID,new Notification()); 

} else { //API 18 以上,發送 Notification 並將其置為前台後,啟動 InnerService

Notification.Builder builder=new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);

startForeground(NOTIFICATION_ID, builder.build());

 startService(new Intent(this, InnerService.class));

 }

 }

 public class InnerService extends Service{

 @Override public IBinder onBind(Intent intent) {

 return null;

 } 

@Override public void onCreate() {

 super.onCreate(); //發送與 KeepLiveService中 ID 相同的 Notification,然後將其取消並取消自己的前台顯示

 Notification.Builder builder = new Notification.Builder(this);

builder.setSmallIcon(R.mipmap.ic_launcher);startForeground(NOTIFICATION_ID,

builder.build());

new Handler().postDelayed(new Runnable() { 

@Override public void run() { 

stopForeground(true);

 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

manager.cancel(NOTIFICATION_ID); 

stopSelf();

 }

 },

100);

 }

 }

 }

在沒有採取前台服務之前,啟動應用,oom_adj 值是 0,按下返回鍵之後,變成 9(不

同 ROM 可能不一樣)

相互喚醒的意思就是,假如你手機里裝了支付寶、淘寶、天貓、UC 等阿里系的 app,

那麼你打開任意一個阿里系的 app 後,有可能就順便把其他阿里系的 app 給喚醒了。

這個完全有可能的。此外,開機,網路切換、拍照、拍視頻時候,利用系統產生的廣播

也能喚醒 app,不過 Android N 已經將這三種廣播取消了。

如果應用想保活,要是 QQ,微信願意救你也行,有多少手機上沒有 QQ,微信呢?或

者像友盟,信鴿這種推送 SDK,也存在喚醒 app 的功能。

拉活方法

JobSheler是作為進程死後復活的一種手段,

native進程方式最大缺點是費電,Native

進程費電的原因是感知主進程是否存活有兩種實現方式,在 Native 進程中通過死循環

或定時器,輪訓判斷主進程是否存活,當主進程不存活時進行拉活。其次 5.0 以上系統

不支持。 但是 JobSheler 可以替代在 Android5.0 以上 native 進程方式,這種方式即

使用戶強制關閉,也能被拉起來,親測可行。

JobSheler@TargetApi(Build.VERSION_CODES.LOLLIPOP) 

public class MyJobService extends JobService {

 @Override

 public void onCreate() {

 super.onCreate();

 startJobSheler();

 }

public void startJobSheler() { 

try {

 JobInfo.Builder builder = new JobInfo.Builder(1,new ComponentName(getPackageName(), MyJobService.class.getName()));

builder.setPeriodic(5); builder.setPersisted(true); JobScheler jobScheler =(JobScheler)

this.getSystemService(Context.JOB_SCHEDULER_SERVICE);

jobScheler.schele(builder.build());

}

catch

(Exception ex)

{ ex.printStackTrace(); } }

 @Override 

public boolean onStartJob(JobParameters jobParameters) {

 return false; 

} @Override public boolean onStopJob(JobParameters jobParameters) { 

return false; 

}

 }

這個是系統自帶的,onStartCommand 方法必須具有一個整形的返回值,這個整形的返

回值用來告訴系統在服務啟動完畢後,如果被 Kill,系統將如何操作,這種方案雖然可

以,但是在某些情況 or 某些定製 ROM 上可能失效,我認為可以多做一種保保守方案。

1.START_STICKY

如果系統在 onStartCommand 返回後被銷毀,系統將會重新創建服務並依次調用

onCreate 和 onStartCommand(注意:根據測試 Android2.3.3 以下版本只會調用

onCreate 根本不會調用 onStartCommand,Android4.0 可以辦到),這種相當於服務

又重新啟動恢復到之前的狀態了)。

2.START_NOT_STICKY

如果系統在 onStartCommand 返回後被銷毀,如果返回該值,則在執行完

onStartCommand 方法後如果 Service 被殺掉系統將不會重啟該服務

3.START_REDELIVER_INTENT

START_STICKY 的兼容版本,不同的是其不保證服務被殺後一定能重啟。

4.相比與粘性服務與系統服務捆綁更厲害一點,這個來自愛哥的研究,這里說的系統服務

很好理解,比如 NotificationListenerService,NotificationListenerService 就是一個監聽

通知的服務,只要手機收到了通知,NotificationListenerService 都能監聽到,即時用戶

把進程殺死,也能重啟,所以說要是把這個服務放到我們的進程之中,那麼就可以呵呵



所以你的應用要是有消息推送的話,那麼可以用這種方式去欺騙用戶。

❷ 請問android系統中的進程,任務,服務三者的區別和聯系

進程是總稱,包括第三方應用和系統應用以及系統底層模塊。任務是你安裝的第三方應用進程。而服務是系統模塊進程。

❸ Android 之 Service(一)啟動,綁定服務

Service(服務)一個運行在後台執行長時間運行的操作組件,它不提供任何用戶界面,作為與Activity同級的組件,它依舊是運行在主線程中。
其它組件可以啟動一個Service,當這個Service啟動之後便會在後台執行,這里需要注意,由於是在主線程中,所以我們需要另外開啟一個線程來執行我們的耗時操作。
此外,一個組件還可以與一個Service進行綁定來實現組件之間的交互,甚至可以執行IPC(Inter-Process Communication)進程間通信。
Service可以在後台執行很多任務,比如處理網路事務,播放音樂,文件讀寫或者與一個內容提供者交互,等等。

本地服務(Local)
該服務依附在主進程上而不是獨立的進程,這樣在一定程度上節約了資源,另外本地服務因為是在同一進程因此不需要IPC,也不需要AIDL。相應bindService會方便很多,當主進程被Kill後,服務便會終止。一般使用在音樂播放器播放等不需要常駐的服務。

遠程服務(Remote Service)
該服務是獨立的進程,對應進程名格式為所在包名加上你指定的android:process字元串。一般定義方式 android:process=":service" 由於是獨立的進程,因此在Activity所在進程被Kill的時候,該服務依然在運行,不受其他進程影響,有利於為多個進程提供服務具有較高的靈活性。由於是獨立的進程,會佔用一定資源,並且使用AIDL進行IPC比較麻煩。一般用於系統的Service,這種Service是常駐的。

startService啟動的服務
用於啟動一個服務執行後台任務,不與組件進行通信,停止服務使用stopService。 當一個應用組件比如activity通過調用startService()來啟動一個服務的時候,服務便處於啟動狀態。一旦啟動,服務可以在後台無限期地運行下去,即使當啟動它的組件已經銷毀。通常情況下,一個啟動的service執行一個單一的操作並且不會返回任何結果給調用者。

bindService啟動的服務
用於啟動的服務需要進行通信。停止服務使用unbindService。 當一個應用組件通過調用bindService()來與一個服務綁定時,服務便處於綁定狀態。一個綁定的服務提供了一個客戶端-伺服器端介面來允許組件與服務進行交互,發送請求,得到結果甚至通過IPC進程間通信來完成操作。只有當其它組件與服務進行綁定時,服務才會處於綁定狀態。多個組件可以同時與服務綁定,但是當他們全部都解除綁定時,服務就會銷毀。

2.BindService:
如果一個Service在某個Activity中被調用bindService方法啟動,不論bindService被調用幾次,Service的 onCreate 方法只會執行一次,同時 onStartCommand 方法始終不會調用。當建立連接後,Service會一直運行,除非調用unbindService來接觸綁定、斷開連接或調用該Service的Context不存在了(如Activity被Finish——即通過bindService啟動的Service的生命周期依附於啟動它的Context),系統在這時會自動停止該Service。

3.StartService AND BindService:
當一個Service在被啟動(startService 的同時又被綁定(bindService ),該Service將會一直在後台運行,並且不管調用幾次, onCreate 方法始終只會調用一次, onStartCommand 的調用次數與startService 調用的次數一致(使用bindService 方法不會調用 onStartCommand )。同時,調用unBindService 將不會停止Service,必須調用stopService 或Service自身的stopSelf 來停止服務。

4.停止Service:
當一個服務被終止(stopService 、stopSelf 、unbindService )時, onDestory 方法將會被調用——所以我們需要在該方法中清除一些工作(依附該Service生命周期上的,比如:停止在Service中創建並運行的線程)。

1.創建服務

如果你才用的是 startService的方式那麼 onBind方法可以忽略
2.注冊服務

3.開啟服務
start:

bind

綁定服務,一般涉及到組件或進程之間的通信,既然需要通信,那麼我們肯定需要一個連接,這里ServiceConnection就是我們所需要的連接,通過Ibinder的傳遞,我們可以獲取到Service的Ibinder對象,從而進行相關操作。

關於粘性服務,這里需要提到 Service的onStartCommand返回值

andorid:name

adroid:exported

android:enabled

android:label

android:process

android:icon

android:permission

關於服務,當我們在應用開發中,如果需要長時間的在後台運行,獨立完成某一些事情的情況下,請使用Service!

此文綜合: http://www.jianshu.com/p/1e49e93c3ec8 以及自己的一些問題看法,用作學習,回顧之用。

Service 前台服務
請參看 紫豪 http://www.jianshu.com/p/5505390503fa

❹ Android後台進程保活方案

思想: 使用 Linux 中的 fork 機制創建 Native 進程,在 Native 進程中監控主進程的存活,當主進程掛掉後,在 Native 進程中立即對主進程進行拉活。

原理: 在 Android 中所有進程和系統組件的生命周期受 ActivityManagerService 的統一管理。Android5.0以下通過 Linux 的 fork 機制創建的進程為純 Linux 進程,其生命周期不受 Android 的管理。

該方案主要適用於 Android5.0 以下版本手機。

該方案不受 forceclose 影響,被強制停止的應用依然可以被拉活,在 Android5.0 以下版本拉活效果非常好。
詳情

對於 Android5.0 以上手機,系統雖然會將native進程內的所有進程都殺死,這里其實就是系統「依次」殺死進程時間與拉活邏輯執行時間賽跑的問題,如果可以跑的比系統邏輯快,依然可以有效拉起。在 某些 Android 5.0 以上機型有效。
詳情

https://github.com/Marswin/MarsDaemon

作者5.0以下系統用一個java進程和一個fork出來的純native進程雙管道互鎖監聽對方的狀態,無論哪個被殺後都拉起第三個進程,第三個進程來拉活常駐進程,實現拉活。
5.0以上同一進程組的進程會被同時殺死,所以5.0以上使用雙java進程在native層互鎖文件實現監聽,但任務管理器會在短時間內殺死所有進程,只能用反射提前初始化pacel,在進程被殺的時候和系統搶那幾十毫秒的時間發送一個拉活的廣播。用4個文件來讓兩個進程實現互鎖來做監聽,但實際效果很一般,測試了幾個5.0以上的國產機型都不行,效果是根本監聽不到進程被殺,目測原因是當任務管理器查殺進程的時候將所有的進程都掛起了,隨後全部殺掉,並在一段時間內禁止進程啟動。

PersistedJobService.java

BootReceiver.java靜態注冊BroadcastReceiver

注冊,開機,網路切換、拍照、拍視頻時候,利用系統產生的廣播也能喚醒app,不過Android N已經將這三種廣播取消了

常用的拉活許可權

BackgroundService.java
WakeLock

作為前台應用運行,提高應用存活幾率

service被關掉後自動啟動

START_STICKY
如果系統在onStartCommand返回後被銷毀,系統將會重新創建服務並依次調用onCreate和onStartCommand(注意:根據測試Android2.3.3以下版本只會調用onCreate根本不會調用onStartCommand,Android4.0可以辦到),這種相當於服務又重新啟動恢復到之前的狀態了)。

START_NOT_STICKY
如果系統在onStartCommand返回後被銷毀,如果返回該值,則在執行完onStartCommand方法後如果Service被殺掉系統將不會重啟該服務。

START_REDELIVER_INTENT
START_STICKY的兼容版本,不同的是其不保證服務被殺後一定能重啟。

service注冊,許可權設置為高優先順序

KeepAliveService.java
注冊,在新的獨立進程內啟動,適用5.0以下的原生系統,5.0以上同樣會被殺死

他的局限性在於:
第一,用戶會在系統設置的賬戶列表裡面看到一個不認識的賬戶;
第二,同步的事件間隔是有限制的,最短1分鍾,見源碼,如果小雨60秒,置為60秒。而且各種國產機怎麼改的源碼我們未可知,是不是都能用仍然未可知;
第三,很致命,某些手機比如note3需要手動設置賬戶,你如何騙你的用戶給你手動設置賬戶完了之後不卸載你;
第四,也很致命,必須聯網!google提供這個組件是讓你同步賬戶信息,不聯網你同步個鬼,我們要保活,可以不聯網不做事,但是不能不聯網就死

集成三方推送平台sdk,友盟極光等

❺ android服務和進程的區別

他們之間的區別:Service很大程度上充當了應用程序後台線程管理器的角色。(如果Activity中新開啟一個線程,當該Acitivyt關閉後,該線程依然在工作,但是與開啟它的Activity失去聯系。也就是說此時的這個線程處於失去管理的狀態。但是使用Service,則可以對後台運行的線程有效地管理。)
一個服務不是一個單獨的進程。服務對象本身並不意味著它是在自己的進程中運行,除非另有規定,否則它與運行程序是同在一個進程中。
一個服務不是一個單獨的線程。Service和其他組件一樣,默認情況下,Service中的所有代碼都是運行在主線程中。
在android中,為什麼不使用後台線程而使用Service? 有3大要點:
1、Service可以放在獨立的進程中,所以更安全;

2、使用Service可以依賴現有的binder機制,不需要在應用層面上處理線程同步的繁雜工作;

3、系統可以重新啟動異常死去的Service。

說明:進程是由若干線程組成。(線程是進程中的一部分,進程包含多個線程在運行。)

❻ Android提升服務進程優先順序

在android應用開發時,我們經常會在後台開一個service,來處理一些業務操作。最近公司的一個項目就是,通過service不斷地和硬體設備交互,獲取數據,在頁面長時間停留在一個頁面時,手機的屏幕會出項鎖屏的狀況,這時,我們的應用的優先順序就會下降,很多次,等打開屏幕的瞬間,我發現原來的原來的進程被殺死了,應用又回到了首頁,尤其是在Android高版本的系統中尤為突出。所以下面我們通過提成優先順序的方式,來進行進程保活

2.在程序開始的地方注冊這個廣播接收者

4.定義這個activity的style屬性 value - style.xml 文件

5.Androidmanifest文件中注冊這個activity

大功告成!
經過測試,本人的華為榮耀9i,原來存在的問題被解決了,希望大家能互相交流經驗。

❼ android進程管理機制

Android系統與其他操作系統有個很不一樣的地方,就是其他操作系統盡可能移除不再活動的進程,從而盡可能保證多的內存空間,而Android系統卻是反其道而行之,盡可能保留進程。Android這樣設計有什麼優勢呢?又是通過怎樣的方法來管理這些被保留的進程的呢?Android用戶又該如何正確使用手機從而更好發揮Android系統所特有的優勢呢?本文將一一為您解開這些謎團。

      本文的主要內容如下:

一、Android進程管理的特殊設計

       Linux系統對進程的管理方式是一旦進程活動停止,系統就會結束該進程。盡管Android基於Linux Kernel,但在進程管理上,卻採取了另外一種獨特的設計:當進程活動停止時,系統並不會立刻結束它,而是會盡可能地將該進程保存在內存中,在以後的某個時間,一旦需要該進程,系統就會立即打開它,而不用再做一些初始化操作。只有當剩餘內存不夠用了,為了維持新開啟的進程或者比較重要的進程的正常運行,系統才會選擇性地殺掉一些不重要的內存,騰出內存空間來,所以Android系統永遠不會有內存不足的提示。

二、Android獨特進程管理設計的好處

      Android這種獨特的設計,也正是Android標榜的優勢之一,這有兩個好處:

  1、最大限度地提高內存的使用率。

       比如,你的內存是8G,如果每次使用完某個進程就殺掉,那麼被使用的內存基本上會始終保持在某個值,比如4G以內,那麼內存的使用率就總是保存在50%以內,剩餘的4G內存形同虛設,發揮用處的機會非常少。而Android的這種設計,就可以做到有多少內存就用多少內存,盡可能大地提高內存使用率。同樣比如有8G內存,使用完的進程仍保留在內存中,累積下來,被使用的內存就盡可能地會接近8G。

  2、提高再次啟動時的啟動速度

       被駐留在內存中不再活動的進程(後台進程或空進程,後面會再講到),很多是經常需要使用的,當再次使用該進程的時候,系統立即打開它,而不需要再重新初始化。例如,我們常用的瀏覽器,當暫時不再使用時,按下Home鍵或Back鍵,瀏覽器進程就變成了不再活動的進程。如果下次又要使用了,點擊多任務鍵,在最近使用應用列表中點擊瀏覽器即可,瀏覽器界面仍然保持著退出前的界面。但如果退出時把該進程移除了,那麼再次使用時,就需要重新初始化,然後進入該應用,這往往會花費不少的時間。

三、Android進程的五個等級

        Android系統將盡量長時間地保持應用進程,但為了新建進程或運行更重要的進程,最終需要移除舊進程來回收內存。為了確定保留或終止哪些進程,系統會根據進程中正在運行的組件以及這些組件的狀態,將每個進程放入「重要性層次結構」中。必要時,系統會首先消除重要性最低的進程,然後是重要性略遜的進程,以此類推,以回收系統資源。該「重要性層級結構」將進程分為了五個等級:

  1、前台進程(foreground)

       前台進程是指那些有組件正和用戶進行交互的應用程序的進程,也稱為Active進程。這些都是Android嘗試通過回收其他應用程序來使其保持相應的進程。這些進程的數量非常少,只有等到最後關頭才會終止這些進程,是用戶最不希望終止的進程。例如:而當你運行瀏覽器這類應用時,它們的界面就會顯示在前台,它們就屬於前台進程,當你按home鍵回到主界面,他們就變成了後台程序。

       如果一個進程滿足以下任一條件,即視為前台進程:

     (1)託管處於活動狀態的Activity,也就是說,它們位於前台並對用戶事件進行響應,此時的情形為響應了Activity中的onResume()生命周期方法,但沒有響應onPause()。

     (2)託管正在執行onReceive()方法處理事件程序的BroadcastReceiver。

     (3)託管正在執行onStart()、onCreate()或onDestroy()事件處理程序的Service。

     (4)託管正在運行且被標記為在前台運行的Service,即調用了該Service的startForeground()方法。

     (5)託管某個Service,且該Service正綁定在用戶正在交互的Activity的Service,即該Activity正處於活動狀態。

  2、可見進程(visible)

        沒有任何前台組件、但仍然會影響用戶在屏幕上所見內容的進程。如果一個進程滿足以下任一條件,即視為可見進程:

    (1)託管不在前台、但仍對用戶可見的Activity(已調用其onPause()方法)。例如:如果前台Acitivty啟動了一個對話框,或者啟動了一個非全屏,亦或是一個透明的Activity,允許在其後顯示上一個Activity,則可能會發生這種情況,這類Activity不在前台運行,也不能對用戶事件作出反應。

    (2)託管綁定到可見Activity的Service。(官網上說是綁定到可見或前台Activity,但筆者有一點疑問,這個和「前台進程」中第(5)點相矛盾嗎,綁定到前台Activity,那就是前台進程了)

        可見進程被視為是極其重要的進程,這類進程的數量也很少,只有在資源極度匱乏的環境下,為保證前台進程繼續執行時才會終止。

  3、服務進程(Service)

        正在運行已使用startService()方法啟動的Serice且不屬於上述兩個更高類別進程的進程。盡管服務進程與用戶所見內容沒有直接關聯,但是它們通常在執行一些用戶關心的操作。因此,除非內存不足以維持所有前台進程和可見進程同時運行,否則系統會讓服務進程保持運行狀態。

       有些資料上面也稱這種進程為次要服務(Secondary Service),而屬於上述兩個更高類別的進程則被稱為主要服務,主要服務往往屬於系統進程,如撥號進程等,不可能被進程管理輕易終止。這里我們以Android開發者官網的稱呼為標准,稱為服務進程。

  4、後台進程(hidden)

       包含目前對用戶不可見的Activity,即該Activity調用了onStop()方法。這些進程對用戶體驗沒有直接影響,系統可能隨時終止它們,以回收內存供上述三個更高級別的進程使用。通常會有很多後台進程在運行,它們會保存在LRU(Least Recently Used,最近最少使用)列表中,以確保包含用戶最近查看的Activity的進程最後一個被終止。如果某個Activity正確實現了生命周期方法,並保存了其當前狀態,則終止其進程不會對用戶體驗產生明顯影響,因為當用戶導航回該Activity時,Activity會恢復其所有可見狀態。

       這里讀者可以做個試驗,先開啟微信,進入到朋友圈界面, 然後點擊手機屏幕下方的導航欄中的Home按鍵進入到後台,再點擊最近使用應用列表顯示按鈕(不同的手機位置不一樣,有的在Home鍵左邊,有的則在Home鍵右邊),在顯示的最近使用應用的列表中清理掉微信應用,最後再點擊桌面的微信圖標啟動微信,會發現顯示的界面仍然是朋友圈界面。

       後台進程,我們可以簡單理解為,應用(只考慮只有Activity組件的情況)啟動後按Home鍵後被切換到後台的進程。如瀏覽器、閱讀器等,當程序顯示在屏幕上時,它們所運行的進程即為前台進程(foreground),一旦按home鍵(注意不是back鍵)返回到桌面,程序就停留在後台,成為後台進程。

  5、空進程(empty)

       不含任何活動應用組件的進程。保留這種進程的唯一目的是用作緩存,以縮短下次再其中運行組件所需要的啟動時間。一般來說,當應用按back按鍵退出後應用後,就變成了一個空進程。比如BTE,在程序退出後,依然會在進程中駐留一個空進程,這個進程里沒有任何數據在運行,作用往往是提高該程序下次的啟動速度或者記錄程序的一些歷史信息。當系統內存不夠用時,無疑,該進程是應該最先終止的。在最近使用應用列表中,可以看到按back鍵退出的應用。

       根據進程中當前活動組件的重要程度,Android會將進程評定為它可能達到的最高級別。通俗地說,就是如果一個進程同時擁有多個對應上述不同等級進程的組件時,會以最高的那個等級作為該進程的等級。例如,如果某進程託管著服務和可見Activity,則會將此進程評定為可見進程,而不是服務進程。

       此外,一個進程的級別可能會因為其他進程對它的依賴而有所提高,即服務於另一進程的進程其級別永遠不會低於其所服務的進程。例如,如果進程A中的內容提供程序為進程B中的客戶端提供服務,或者如果進程A中的服務綁定到進程B中的組件,則進程A始終被視為至少與進程B同樣重要。

       由於運行服務的進程其級別高於託管後台Activity的進程,因此啟動長時間運行操作的Activity最好為該操作啟動Service,而不是簡單地創建工作線程,當操作有可能比Activity更加持久時更應該如此。例如,正在將圖片上傳到網站的Activity應該啟動服務來執行上傳,這樣一來,即使用戶退出Activity,仍可在後台繼續執行上傳操作。使用服務可以保證,無論Activity發生什麼情況,該操作至少具備「服務進程」優先順序。如果某個Activity開啟了線程執行耗時操作,當Activity退出時,該Activity的實例將不會釋放內存資源,直到線程執行完,這樣容易導致內存泄漏。同理,廣播接收器也應該使用服務,而不是簡單地將耗時冗長的操作放入線程中。

四、進程移除順序的依據——閾(yu,第四聲)值

        前面講到,內存不夠用時,會根據進程的等級來決定優先回收哪類進程。那麼系統是根據什麼來判斷需要移除這些進程的時機的呢?答案是閾值。

  1、查看閾值

        我們可以採用如下方法查看手機中各個等級進程的閾值(需要root許可權),如第二排數據所示(其單位為頁):

       以第一個數據44032為例,計算方法為:

       1page=4KB=4*1024B=4096B

       44032page* 4048B/page =  180355072B

       180355072B/1024/1024 = 172M

       即第一個等級的進程的閾值為172M。依次類推,閾值依次為:172M,190M,208M,226M,316M,415M。

       有必要說明一下,在Android開發者官方文檔中,是將Android應用進程分為了5個等級,但很多資料卻是分的6個等級,在後台進程和空進程之間還有一個「內容提供節點(content provider)進程」。內容提供節點,沒有實體程序,僅提供內容供別的程序去用 ,比如日歷供應節點,郵件供應節點等,在終止進程時,這類進程有比較高的優先權。手機中應該是採用的6個等級的方式,如上六個數據,正好對應著六個等級的進程,等級越高,閾值越低,即前台進程閾值為172M,空進程為415M。當系統的剩餘內存只剩餘不到415M的時候,系統首先會回收空進程,依次類推,只有剩餘內存不到172M了,才會去回收前台進程,這樣就起到了優化保護重要進程的作用。

五、Home鍵、Back鍵和多任務鍵

       Home鍵、Back鍵和多任務鍵,在手機屏幕的下方,這三個按鍵一般稱為導航欄,中間的按鈕為Home鍵,多任務鍵和Back鍵分別在其左右,一般根據手機品牌不同,左右位置也有所差異。

       在運行App的時候,如果按一下Home鍵或者Back鍵,都可以退到桌面,那麼這兩者有什麼區別呢?

Home鍵。按Home鍵的時候,App如果沒有Service開啟,會從一個前台進程轉變為一個後台進程;如果有前台service運行,就仍然是前台進程,比如QQ音樂播放器等;如果是只有普通service運行,那麼就轉變為服務進程(參照前文中講的Android進程的5個級別)。

Back鍵。按Back鍵的時候,App如果沒有Service開啟,會從一個前台進程轉變為一個空進程;對於有Service運行的情況,和按Home鍵一樣。

        後台進程和空進程,都是駐留在後台,處於暫停狀態,也都是除了佔用一部分內存外,不佔用其他如cpu等資源的,那麼問題來了,為什麼要設計後台進程和空進程這兩種空進程呢?它們的區別到底在哪裡呢?我們在前文講Android進程的5個等級的時候講到過,當剩餘內存不足的時候,系統會按照等級順序,優先移除不太重要進程,以收回內存供更重要的進程運行。那麼,它們的區別就是,在剩餘內存不足時,會優先移除空進程,再不足,才會移除空進程。所以,如果確實要退出某個應用一段時間內不大使用了,如果這款應用有退出按鈕,就用應用自帶的退出功能;如果沒有,則最好按系統的Back鍵,這樣可以變成空進程,當系統要回收內存時,就會優先被回收,從而釋放的所佔的資源。如果只是暫時退出去做點別的,過一會還要切換回來,或者對這款應用使用比較頻繁,那就使用Home鍵,因為相比於按Back鍵,這樣可以盡可能保住後台進程,方便下次使用的時候快速啟動。

       當然,按Home鍵或Back鍵,對用戶來說,其實感覺不到差異,使用起來沒什麼兩樣,但是,對於Android開發者來說,卻有必要作為常識來了解其中的道理和差異。無論是按Home鍵還是按Back鍵,在按多任務鍵的時候,都可以看到這些進程,如下圖所示。最下面的按鍵為清理按鍵,點擊後可以清除掉這些進程,回收內存了,當然,前面也講了很多遍了,不建議這樣做。

  2、修改閾值。

       可以採用命令:echo "44032,48640,53248,57856,80896,106241" > /sys/mole/lowmemorykiller/parameters/minfree來修改閾值,如下所示:

       重啟後,會恢復為原來的值。至於如何永久性修改該閾值,這里不深入探討,有興趣的童鞋可以自行研究,一般來說,就按照系統給定的默認值使用就可以了,沒特殊用途的話,沒必要修改。

       對於這一節閾值的內容,暫時先講到這里,如果要更深入,可以自行多研究研究。筆者也沒有看到比較好的更深入的文章,所以也不好推薦,如果讀者看到比較好的,可以推薦給筆者,感激不盡。

六、開發者選項中的進程管理功能

        Android手機都帶有開發者選項,隱藏了很多功能,顧名思義,這些功能主要用於輔助開發者調試程序用的。其中有一些就是關於進程管理功能的,筆者這里簡單介紹一下其中兩款,如下圖紅框部分所示:

不保留活動。用戶離開以後即銷毀每個活動(Activity),這樣做使得後台進程都被銷毀了。筆者試驗過幾款app,比如微信,瀏覽器,開啟/關閉「不保留活動」前後,按Home鍵後,再打開應用,有明顯的差別。當然,也試用了簡訊,DD打車,就沒看出起了什麼作用。讀者若是感興趣可以深入研究研究,到時候在指導指導筆者!

後台進程限制。如下圖所示,給出了後台進程個數限制的選項。

七、進程管理軟體的使用

       Windows操作系統用戶往往總想著保留更多的內存,在使用Android手機的時候,喜歡經常清理後台進程或空進程,而且清理完後,心裡有一種特別爽的感覺,就像給家裡做了一次大掃除一樣,筆者最初使用Android手機的時候也是這樣的心態-_-!基於這樣的心態,一些進程清理軟體,很受普通用戶的青睞。其實這樣做卻正好抹殺了Android系統所標榜的優勢,如前文所講到的。

       那麼進程管理軟體有無必要呢?當然有的,只是需要注意使用場合。當需要運行大型程序的時候,可以手動關閉掉一些進程,騰出足夠的空間供大型程序使用,這樣就可以有效避免系統調用進程調度策略而引起的卡頓,這一點,第八大點第3小節中會有說明。而且由於開發者的原因,可能是程序寫得太爛,或程序容易出錯,或做不該做的動作,或是惡意程序,對於這類程序進程,手動移除也是有好處的。

       但如果是運行一些小程序,就完全沒有必要去預先殺進程了,完全可以交給系統自己管理。讀者可能會疑惑,因為小程序啟動的時候,也有可能會因為內存不足而導致需要移除部分進程的情況。筆者認為,即便是內存不足,小程序運行引起的調用進程調度策略測的次數非常少,要移除的進程也非常少,產生的影響不大。同時,我們也要意識到另外一點就是,無論是手動殺死進程還是自動殺進程,都需要cpu去執行這些任務,所以也會拖慢手機和消耗電量。所以從這一點看,頻繁殺進程,也是一個不好的習慣。

八、答疑解惑

        在以前沒有專門去了解Android進程管理機制的時候,甚至是在研究的過程中,筆者心裡都經常存在很多疑惑,以下整理了其中5個,不知道讀者您是否有也類似的困惑呢?

  1、這么多駐留在內存的進程,不會耗電嗎?

       大多數用慣了Windows操作系統的童鞋,看到Android系統盡可能保留不在活動的進程的設計,可能第一反應就是質疑,難道這樣不會增加耗電量嗎?其實,但一個程序按home鍵變成後台進程或者按back鍵退出變成空進程後,其實已經被暫停了,只保留了運行狀態,不會消耗cpu,一個程序會耗電,是因為它需要調用cpu來運算,現在不消耗cpu了,當然就不會耗電了。當然,開了service的應用就另當別論了,比如QQ音樂播放器,當按home鍵或back鍵後,音樂仍然播放,是因為它開啟了服務,而且是一個前台服務,在後面我們會繼續講到,此時它是一個前台進程,而不是後台進程或空進程。

  2、為什麼一個不太app,運行時會佔用很大的內存呢?

我們經常會碰到這樣一種現象,一個只有20M的App,運行起來的時候,卻會耗掉100M以上的內存。一方面是,程序運行時為對象分配內存,另一方面,是Android虛擬機的原因。Android中的應用啟動的時候,系統都會給它開啟一個獨立的虛擬機,這樣做的好處是可以避免虛擬機崩潰導致整個系統崩潰,代價就是耗用更多的內存。

  3、為什麼內存少的時候,運行大型程序會卡頓呢?

        當剩餘內存不多時,打開大型程序,系統會觸發自身的進程調度策略,去移除一些等級比較低的進程來回收內存,以供大型程序運行。而這個進程調度策略在決定哪些進程需要被移除的過程,是一個十分消耗資源的操作,特別是一個程序頻繁像系統申內存的時候,這樣就導致了系統的卡頓。

 4、應用開得太多了,手機變慢,是因為內存被佔用太多嗎?

        其實手機變慢的根本原因是cpu被耗用太多,而不是內存佔用太多,因為真正執行程序所要完成的任務的最終執行者是CPU,而不是內存(RAM)。在內存足夠的情況下,如果系統中佔用cpu的進程太多,那無疑cpu總有忙不過來的時候,那肯定就會變慢了。這就好比,在一條道路上駕車,道路就像內存,車的引擎就像cpu,如果車的引擎的動力不夠,或者承載的貨物太多,車都跑不快,即便是道路上一路暢通無阻,也無濟於事。所以,內存佔用多少並不重要,只要道路提供給車輛前行的空間是足夠的,手機變慢的責任,就和內存無關了。這個比喻用來解釋第三點也很恰當,道路提供的車輛前進的空間無法滿足車輛所必需的空間時,就需要交通機制花時間來調節交通,給這輛車提供足夠的空間,而在此期間,這輛車只能乖乖候著。

  5、Android手機越用越慢,是什麼原因呢?

Android手機常常是越用越慢,即使是恢復出廠設置,也無法改變這個現象。手機越用越慢,主要由如下幾個原因:(1)虛擬機機制問題。這一點在上一個問題中也提到了,在Android4.4以前的系統,使用的是Dalvik虛擬機,它的設計機制有缺陷,就是越用越慢;在Android4.4系統中有切換按鈕,可以在Art虛擬機和Dalvik虛擬機之間切換;在Android4.4以後的系統就徹底拋棄了Dalvik而全面使用Art。(2)開啟了太多的服務,導致耗用太多的CPU。隨著手機開機使用時間的增長,應用使用越來越多,很多應用看似退出了,而其實後台可能開了不少的服務,而他們可能還沒有關閉。這些服務正在執行一些操作,會消耗CPU,而CPU才是手機變慢的根本原因。 而且Android app比較開放的,有很多不良應用充斥其中,可能對服務處理不當,濫用服務等,增加系統中的服務。(3)系統頻繁調用自身的進程調度演算法。這一點在前面已經說明了,這里不再贅述。(4)手機硬體的自然老化

熱點內容
javajdk區別 發布:2025-05-11 18:45:21 瀏覽:35
如何防止apk被反編譯 發布:2025-05-11 18:45:16 瀏覽:152
安卓什麼功能好 發布:2025-05-11 18:21:31 瀏覽:354
我的世界2b2t伺服器中國版 發布:2025-05-11 18:16:35 瀏覽:693
萌將風雲腳本 發布:2025-05-11 18:07:14 瀏覽:745
密碼鎖aid代表什麼 發布:2025-05-11 18:00:01 瀏覽:757
編程的組成 發布:2025-05-11 17:58:34 瀏覽:808
火山易語言apk反編譯 發布:2025-05-11 17:52:01 瀏覽:814
鋼琴密碼鎖本的密碼該在哪裡看 發布:2025-05-11 17:49:44 瀏覽:469
in運演算法則 發布:2025-05-11 17:41:32 瀏覽:407