Android 應用五大核心塊 — Service後臺服務
概念:
Service:後臺服務,用於將一些計算或常用系統通用功能放在一個獨立的進程中進行處理,這樣主進程可以全力並快速處理界面響應,提高用戶體驗效果。
下面以 packages\apps\Phone 應用舉例說明:
編寫應用時定義:AndroidManifest.xml
<!– CDMA Emergency Callback Mode –>
<service android:name="EmergencyCallbackModeService">
</service>
EmergencyCallbackModeService.java 中如此定義:
public class EmergencyCallbackModeService extends Service
繼承於 android.app.Service 類,重載其父類函數,此Service啟動點:
PhoneAppBroadcastReceiver @ PhoneApp.java
// Start Emergency Callback Mode service
if (intent.getBooleanExtra("phoneinECMState", false)) {
context.startService(new Intent(context,
EmergencyCallbackModeService.class));
}
ok, 表時Servie服務是利用 startService 函數而利用 Intent 類啟動的。
幾個類的關系如下:
public abstract class Context
public class ContextImpl extends Context
public class ContextWrapper extends Context
public class ContextThemeWrapper extends ContextWrapper
public class Activity extends ContextThemeWrapper
即Activity繼承瞭ContextWrapper類,而在ContextWrapper類中,實現瞭startService函數。在ContextWrapper類中,有一個成員變量mBase,它是一個ContextImpl實例,而ContextImpl類和ContextWrapper類一樣繼承於Context類,ContextWrapper類的startService函數最終過調用ContextImpl類的startService函數來實現。
既然理清楚瞭這幾者關系,下面開始按照代碼走一下完整的流程:
=========================主進程調用到ActivityManagerService進程中,完成新進程的創建============
startService @ ContextImpl.java
public ComponentName startService(Intent service) {
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
}
這裡利用Binder進行通訊:
startService @ ActivityManagerNative.java
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
這裡是利用 Binder 驅動程序發送請求給報務端,即此時的 mRemote(Binder對象)就是 ActivityManagerService
而ActivityManagerService這邊就是等待Client的請求:
startService @ ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) {
// 利用 Binder 對象獲取到 pid,uid 等參數
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = startServiceLocked(caller, service,
resolvedType, callingPid, callingUid);
}
caller、service和resolvedType分別對應ActivityManagerProxy.startService傳進來的三個參數
–>
這裡簡單看一下調用邏輯:
startServiceLocked() –> bringUpServiceLocked() –> startProcessLocked:
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
….
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
…
}
start @ Process.java
public static final int start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags,
String[] zygoteArgs)
{
if (supportsProcesses()) {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, zygoteArgs);
}else {
// Running in single-process mode
Process.invokeStaticMain(processClass);
}
}
這裡通過函數 openZygoteSocketIfNeeded 與 Zygote Socket 之間進行通訊,fork出一個新的
進程,然後導入 android.app.ActivityThread 線程,執行其main函數。
=========新進程調用到ActivityManagerService進程中,獲取要在新進程啟動的服務的相關信息=======
main @ ActivityThread.java
public static final void main(String[] args) {
// 這裡設定 Activity 的主 Looper
Looper.prepareMainLooper();
// 創建 ActivityThread 線程實例www.aiwalls.com
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
}
這裡在新的進程中運行瞭,這裡就是用來啟動服務的。在Android應用程序中,每一個進程對應一個ActivityThread實例,所以,這個函數會創建一個thread實例,然後調用ActivityThread.attach函數進一步處理。
attach @ ActivityThread.java
private final void attach(boolean system){
…
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
}
喲,,這裡又要調用 ActivityManagerNative ,嗯,根據前面的分析大傢應該知道瞭吧:)
attachApplication @ ActivityManagerNative.java
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
利用 Binder 對象調用到服務端:
attachApplication @ ActivityManagerService.java
attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find any services that should be running in this process…
if (!badApp && mPendingServices.size() > 0) {
realStartServiceLocked(sr, app);
}
}
–>
這裡開始時利用mPidsSelfLocked變量將進程的一些信息存入瞭ServiceRecord類
app.thread.scheduleCreateService(r, r.serviceInfo);
scheduleCreateService @ ApplicationThreadNative.java
public final void scheduleCreateService(IBinder token, ServiceInfo info){
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
}
通過Binder驅動程序回到新進程的ApplicationThread對象中去執行scheduleCreateService函數
============== 從ActivityManagerService進程又回到新進程中,最終將服務啟動起來 =============
scheduleCreateService @ ActivityThread.java
public final void scheduleCreateService(IBinder token,
ServiceInfo info) {
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
queueOrSendMessage(H.CREATE_SERVICE, s);
}
通過 Handler 發送消息,在此文件中的 main 函數中調用 Looper.prepareMainLooper(); 表明這是一個Activity 主線程,使用 main looper ,由 Looper.java 中的 loop 進行循環消息處理。
處理消息函數:
handleMessage @ ActivityThread.java
public void handleMessage(Message msg) {
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
…
}
–>
private final void handleCreateService(CreateServiceData data) {
Service service = null;
// 通過強制類型轉換得到一個Service類實例
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
…
service.onCreate();
}
根據最前面講的,自己的服務類必須要繼承於Service類,那麼將運行自已Service的onCreate()函數.
public class EmergencyCallbackModeService extends Service {
@Override
public void onCreate() {
// Check if it is CDMA phone
…
}
總結如下:
如此Android系統在新進程中啟動服務的過程就分析完成,主要經歷如下幾個主要過程:
1、主進程調用到ActivityManagerService進程中,完成新進程的創建
2、新進程調用到ActivityManagerService進程中,獲取要在新進程啟動的服務的相關信息
3、從ActivityManagerService進程又回到新進程中,最終將服務啟動起來
其中上面通過三次Binder進程間通訊完成啟動過程。
最後以一個簡圖說明一下:
摘自 andyhuabing的專欄