一、概述
Service是Android的四大組件之一,我們可以利用它開啟一個后台服務,Service的優先級比較高,一旦其在后台運行即使App處於后台則Service運行的任務也不容易被殺死。了解Service的工作原來除了可以加深對底層的Service機制的理解以外還可以為當前比較流行的熱更新做服務(即Service的插件化)
Service分為兩種狀態一種一種是啟動狀態,可以做一些后台的任務計算。一種是綁定狀態,幫助Service和用戶進行交互。
1.啟動狀態的聲明周期為:onCreate——onStartCommon——onDestory
2.綁定狀態的生命周期為:onCreate——onBind——onUnBind——onDestroy
在啟動狀態下原理分為兩部分:1.Service和目標App不在同一個進程。2.Service和App在同一個進程
綁定狀態下的原理分析也分為兩個部分:1.Service和App不再同一個進程。2.Service和App在同一個進程
其實不管是啟動狀態還是綁定狀態的原理都和之前介紹的Activity的啟動原理非常的相似,其實都是反反復復的和AMS交互(握手)的過程,然后利用PMS加載包信息,獲取ClassLoader,並利用ClassLoader加載類並通過反射實例化的過程。
二、原理分析
先說下啟動狀態下App和Service不在同一個進程中的情況。這個過程分為五部,先說下原理然后再介紹調用棧。
1.App通知AMS要啟動一個Service,並把啟動信息發送給Service
2.AMS收到消息后保存信息,並檢查service所在的進程是否已經啟動了,如果已經啟動了就直接打開,如果沒有啟動就啟動一個新的進程
3.App進程啟動好以后通知AMS已經啟動好了
4.AMS收到App啟動好的消息后就翻出保存在ServiceRecord中的信息,並把其發送給App
5.App收到啟動信息后啟動Service即可
上面所說的是一個大概的步驟,下面將詳細說一下這五步的具體實現
1.App調用context.startService方法,在Context.startService方法內部又會調用ActivityManagerNative.getDefault().startService方法,ActivityManagerNative.getDefault()返回的是一個IActivityManager接口,里面存儲了四大組件的所有生命周期函數,而ActiivtyManagerProxy是AMS在App的代理對象,其也集成了IActivityManger接口。所以最終會是ActivityManagerProxy.startService把Service的信息發送給AMS
2.AMS通過跨進程通信的方式收到Service的信息后會保存在ServiceRecord中,然后檢查Service是否在AndroidManifest.xml中注冊,如果沒有注冊則報錯。檢查service進程是否已經啟動了,如果沒有啟動則會調用Process.start(android.app.ActivityThread)方法啟動一個新的進程。
3.App進程啟動是會實例化ActivityThread對象並調用其中的main方法來開啟進程,進程啟動后會通過ActivityManagerProxy代理對象把ActivityThread對象發送給AMS
4.AMS接收到ActivityThread對象后會把ActivityThread對象包裝成為ApplicationThreadProxy對象(app的代理對象),並從ServiceRecord中翻出在第二步中保存的service信息,並通過ApplicationThreadProxy.scheduleCreateService將信息發送給App進程
5.App進程通過ApplicationThread接收消息,並調用ActiivtyThread的sendMessage方法向H發送消息,在H的handleMessage方法會接收消息,之后會調用ActivityThead的handleCreateService方法通過packageinfo拿到加載類的classloader並通過反射創建Service對象,創建完service對象后會緊接着調用其onCreate函數來完成Service的啟動。
Service和App在同一個進程中的情況分為三步:
1.app調用Context.startService方法,startService方法又會調用ActivityManagerProxy.startSerivce方法把intent消息發送給AMS
2.AMS檢查service是否在AndroidManifest.xml中注冊,如果沒有注冊就拋異常,AMS檢查Service所在的進程是否已經啟動,如果啟動了則將Service啟動信息通過ApplicationThreadProxy.scheduleCreateService發送給App進程
3.App進程通過ApplicationThread接收消息並通過ActivityThread.sendMessage發送消息,之后的過程就和上面的第5步是一樣的。
綁定過程原理描述:
1.App通過Context.bindService發起綁定,最終會通過ActivityManagerProxy.bindService把service的Intent信息放給AMS
2.AMS檢查Service是否在AndroidManifest.xml中進行了注冊,如果沒有則拋異常。AMS會保存App進程傳遞過來的信息到ServiceRecord。AMS檢查Service所在的進程是否存在,如果不存在就就調用Process.start(android.app.ActivityThread)創建一個新的進程。
3.實例化ActivityThread對象並執行其中的main方法,並對主線程Looper進行初始化。App進程啟動后會將ActivityThread通過ActivityManagerProxy發送給AMS
4.AMS接收到ActivityThread后會將ActivityThread包裝秤ApplicationThreadProxy,然后通過ApplicationThreadProxy.scheduleBindService向App進程發送消息
5.App進程通過ApplicationThread接收到消息后會調用ActivityThread.sendMessage方法向H發送消息,H通過handleMessage接收到消息后會調用handleBindService對Service進行實例化並調用其onCreate函數。之后會調用Service的onBind函數把Binder發送給AMS