一文帶你看懂Android Application啟動流程是怎樣的
基于Android11-API30
總覽
- 獲取applicationThread,AMS這兩個Binder2.attach時,將獲取applicationThread對象也傳遞到AMS進程,請求遠程調(diào)用通知AMS應用進程想要創(chuàng)建Application,此時AMS為服務端
- AMS收到消息,請求調(diào)用applicationThread的遠程接口,此時AMS為客戶端
- applicationThread收到AMS的請求,通過Handler發(fā)起創(chuàng)建Application的處理任務,后面就沒有遠程接口調(diào)用了
- 通過反射創(chuàng)建Application的實例,通過Instrumentation啟動Application的onCreate方法
詳細流程分析
從 ActivityThread.java 的main方法開始看;
public static void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(system=false, startSeq);//1
...
}
進入attach方法;
if(!system){
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);//1
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
非系統(tǒng)應用流程,根據(jù) getSeervice和捕獲的RemoteException可以斷定,此處在使用Binder進行遠程接口調(diào)用。
轉身看下mAppThread是什么?
final ApplicationThread mAppThread = new ApplicationThread();
private class ApplicationThread extends IApplicationThread.Stub {
//批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
public final void schedule*
//TODO 關鍵方法
public final void bindApplication(some args){}//1
//一堆dump方法,比如dumpMemory、dumpActivity等
}
可以看到,ApplicationThread是一個實現(xiàn)了遠程接口的Binder客戶端,內(nèi)部封裝實現(xiàn)了很多遠程接口。不過這個客戶端什么時候連接的服務器還未可知,沒有找到bindService關鍵字,反正此時應該已經(jīng)連接上對應的Service了。應該是在RuntimeInit.java類中進行應用進程啟動時啟動的。
回來看下前一步服務的實例IActivityManager.attachApplication()內(nèi)部的實現(xiàn)。
先獲取AMS的實例,此處獲取AMS實例代碼跟Activity啟動流程中一致
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
…獲取到AMS的Binder后,繼續(xù)查看ActivityManagerService.java中的attachApplication方法
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq); //1
Binder.restoreCallingIdentity(origId);
}
}
單例獲取AMS實例,AMS服務在系統(tǒng)啟動就已經(jīng)注冊到ServiceManager了,此處直接去獲取Binder實例就行,ServiceManager以Binder池的方式管理注冊的Server。
AMS的attachApplication方法中進入到attachApplicationLocked方法,撿能看懂的代碼看,跟著thread參數(shù)查看代碼。
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);//1
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
mProcessList.startProcessLocked(app,
new HostingRecord("link fail", processName),
ZYGOTE_POLICY_FLAG_EMPTY);
return false;
}
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (instr2 != null) {//2
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
} else {
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
}
}
先給ApplicationThread這個Binder上個死亡代理,根據(jù)這個死亡代理應該可以找到對應的Service是如何重新啟動的,感興趣可以繼續(xù)深入,咱們繼續(xù)往下走。
此處調(diào)用到thread.bindApplication接口,前面咱們查看ApplicationThread時有看到,直接切入。
private class ApplicationThread extends IApplicationThread.Stub {
//批量的schedule*接口,比如scheduleReceiver、scheduleCreateService等
public final void schedule*
//TODO 關鍵方法
public final void bindApplication(some args){
AppBindData data = new AppBindData();
...一堆參數(shù)
sendMessage(H.BIND_APPLICATION, data);//1
}
//一堆dump方法,比如dumpMemory、dumpActivity等
}
到達咱們Android開發(fā)工程師比較熟悉的點了,封裝了一堆參數(shù)后,通過H這個Handler對象發(fā)了一條BIND_APPLICATION消息,咱們看看這條消息去哪了,直接跟進BIND_APPLICATION這個消息的捕捉位置。
//消息分發(fā)
class H extends Handler{
public void handleMessage(Message msg){
swich(msg.what){
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);//1
break;
...省略
}
}
}
進入消息分發(fā)處理方法,這個方法比較長,注意閱讀能看懂的代碼,不求甚解,跟蹤data的處理。
private void handleBindApplication(AppBindData data) {
//各種初始化,比如進程名,應用名,AsyncTask線程池的配置,時區(qū),網(wǎng)絡發(fā)現(xiàn)
//Context的初始化
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)//1
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,//1
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
...
Application app;
app = data.info.makeApplication(data.restrictedBackupMode, null);//2
mInstrumentation.onCreate(data.instrumentationArgs);
mInstrumentation.callApplicationOnCreate(app);//3
}
通過反射實例化mInstrumentation對象,該對象為Android系統(tǒng)組件的管家,目前看可以控制Application和Activity的生命周期。
創(chuàng)建Application對象,進去看下創(chuàng)建的代碼
//LoadApk.java #makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation){
...
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);//1
appContext.setOuterContext(app);
...
}
//Instrumentation.java #newApplication
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);//2
app.attach(context);//首先回調(diào)attachBaseContext方法
return app;
}
//AppComponentFactory #instantiateApplication
public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
@NonNull String className)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Application) cl.loadClass(className).newInstance();//3
}
可以看出最后還是通過反射初始化了Application。
最后通過mInstrumentation對象完成Application類的onCreate方法的調(diào)用。
mInstrumentation.callApplicationOnCreate(app);//1
//Instrumentation.java #callApplicationOnCreate
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
到此這篇關于一文帶你看懂Android Application啟動流程是怎樣的的文章就介紹到這了,更多相關Android Application 啟動流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Flutter開發(fā)setState能否在build中直接調(diào)用詳解
這篇文章主要為大家介紹了Flutter開發(fā)setState能否在build中直接調(diào)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
Android從0到完整項目(1)使用Android studio 創(chuàng)建項目詳解
本篇文章主要介紹了Android從0到完整項目(1)使用Android studio 創(chuàng)建項目詳解,具有一定的參考價值,有興趣的可以了解一下2017-07-07
Android自定義View實現(xiàn)隨機數(shù)驗證碼
這篇文章主要為大家詳細介紹了Android如何利用自定義View實現(xiàn)隨機數(shù)驗證碼效果,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-06-06
Android用ListView顯示SDCard文件列表的小例子
本文簡單實現(xiàn)了用ListView顯示SDCard文件列表,目錄的回退等功能暫不討論,獲取文件列表,files即為所選擇目錄下的所有文件列表2013-11-11
Android BSearchEdit 搜索結果選擇框的實例代碼
EditText搜索結果下拉框、自動or回調(diào)模式、可diy、使用超簡便。這篇文章主要介紹了Android BSearchEdit 搜索結果選擇框的實例代碼,需要的朋友可以參考下2019-10-10
Android Retrofit文件下載進度顯示問題的解決方法
這篇文章主要為大家詳細介紹了Android Retrofit文件下載進度顯示問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01
輕松實現(xiàn)功能強大的Android刮獎效果控件(ScratchView)
這篇文章主要為大家詳細介紹了ScratchView如何一步步打造萬能的Android刮獎效果控件,,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09

