Android原始碼解析 Intent實現原理

2021-08-15 17:19:40 字數 3936 閱讀 3353

(一)intent查詢與匹配

android使用intent進行元件,程序之間的通訊和跳轉。intent具有隱式intent和顯式intent兩種,android系統通過packagemanagerservice來進行系統元件的維護。

packagemanagerservice的建構函式大概有700多行,它載入了系統已安裝的各類apk,並載入了framework資源和核心庫。載入了資源和核心庫之後才開始對掃瞄的指定目錄下的apk檔案進行解析。實現這一操作的**是scandirli函式。

private void scandirli(file dir, final int parseflags, int scanflags, long currenttime) 

if (debug_package_scanning)

for (file file : files)

try catch (packagemanagerexception e) }}

}

其中scanpackagetracedli實現了包掃瞄

private packageparser.package scanpackagetracedli(file scanfile, final int parseflags,

int scanflags, long currenttime, userhandle user) throws packagemanagerexception finally

}

private packageparser.package scanpackageli(file scanfile, int parseflags, int scanflags,

long currenttime, userhandle user) throws packagemanagerexception

trace.tracebegin(trace_tag_package_manager, "parsepackage");

final packageparser.package pkg;

try catch (packageparserexception e) finally

return scanpackageli(pkg, scanfile, parseflags, scanflags, currenttime, user);

}

在scanpackageli方法中,系統會構建乙個packageparser(包解析器),並呼叫這個包解析器的parsepackage方法進行檔案解析。

public package parsepackage(file packagefile, int flags) throws packageparserexception  else 

}

這個方法會根據是否只有乙個apk,分別呼叫不同的方法進行解析。

無論是parseclusterpackage還是parsemonolithicpackage方法,其中都呼叫到了parsebaseapk方法。這個方法才具體實現了解析乙個androidmanifest.xml檔案的流程。

private package parsebaseapk(resources res, xmlresourceparser parser, int flags,

string outerror) throws xmlpullparserexception, ioexception

} catch (packageparserexception e)

final package pkg = new package(pkgname);

typedarray sa = res.obtainattributes(parser,

com.android.internal.r.styleable.androidmanifest);

com.android.internal.r.styleable.androidmanifest_versioncode, 0);

pkg.baserevisioncode = sa.getinteger(

com.android.internal.r.styleable.androidmanifest_revisioncode, 0);

pkg.mversionname = sa.getnonconfigurationstring(

com.android.internal.r.styleable.androidmanifest_versionname, 0);

if (pkg.mversionname != null)

sa.recycle();

return parsebaseapkcommon(pkg, null, res, parser, flags, outerror);

}

可以清晰地看到它解析了apk的versionname,versioncode,baseversioncode。那麼apk的各個元件是在**解析的呢?

xmlresourceparser parser, int flags, string outerror)

owner.activities.add(a);

} else if (tagname.equals("receiver"))

owner.receivers.add(a);

} else if (tagname.equals("service"))

owner.services.add(s);

} else if (tagname.equals("provider"))

owner.providers.add(p);

}// **省略

}顯而易見,這裡系統將應用的各個元件解析出來,並且存入到了各個集合當中。

至此,整個資訊樹構建完畢,系統已經儲存好了這個應用的元件資訊。

(二)資訊匹配

我們看一下呼叫intent的具體方法,一般情況下,我們都是使用startactivity這個方法的。我們跟進去看一下。

@override

public void startactivity(intent intent, @nullable bundle options) else

}

然後我們在看一下startactivityforresult方法。

//省略**

options = transferspringboardactivityoptions(options);

instrumentation.activityresult ar =

minstrumentation.execstartactivity(

intent, requestcode, options);

if (ar != null)

//省略**

其中核心**是execstartactivity這個方法。

這個方法經過一系列呼叫,最終呼叫了resolveactivityinfo方法

public activityinfo resolveactivityinfo(@nonnull packagemanager pm,

@packagemanager.componentinfoflags int flags) catch (packagemanager.namenotfoundexception e)

} else

}return ai;

}

這個方法會根據傳進來的flags在pms所儲存的元件列表中挑選最合適的系統元件,進行回傳。

因此整個流程就是:

在系統啟動時,packagemanagerservice就會啟動,pms將解析所有已安裝的應用資訊,構建資訊表,當使用者通過intent跳轉到某個元件時,會根據intent中包含的資訊到pms中查詢對應的元件列表,最後跳轉到目標元件當中。

Fabric 原始碼解析 原始碼目錄解析

這裡對重要的一些目錄進行說明 bccsp 與密碼學 加密 簽名 證書等等 相關的加密服務 將fabric中用到的密碼學相關的函式抽象成了一組介面,便於拓展。bddtests 一種新型的軟體開發模式 行為驅動開 需求 開發 common 一些公共庫 錯誤處理 日誌處理 賬本儲存 策略以及各種工具等等 ...

Spring原始碼解析之 Aop原始碼解析(2)

spring aop 更多的是oop開發模式的乙個補充,幫助oop以更好的方式來解決對於需要解決業務功能模組之上統一管理 的功能 以一副圖來做為aop功能的說明更直觀些。對於類似系統的安全檢查,系統日誌,事務管理等相關功能,物件導向的開發方法並沒有更好的解決方法 aop引入了一些概念。更多的是spr...

weex原始碼解析(四) android引入sdk

上一章,我們簡單說明了下js檔案的生成。那本篇文章,會先簡單使用下這個sdk,將上一章生成的js檔案,進行載入,以便頁面展示手機端上。compile com.android.support recyclerview v7 23.1.1 compile com.android.support supp...