精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

瀏覽器為什么能喚起App的Activity?

系統(tǒng) 瀏覽器
我們沒有主動聲明Activity的class,那么系統(tǒng)是怎么為我們找到對應(yīng)的Activity的呢?其實這里和正常的Activity啟動流程是一樣的,無非是if / else的實現(xiàn)不同而已。

[[425568]]

本文轉(zhuǎn)載自微信公眾號「咸魚正翻身」,作者MDove。轉(zhuǎn)載本文請聯(lián)系咸魚正翻身公眾號。

疑問的開端

大家有沒有想過一個問題:在瀏覽器里打開某個網(wǎng)頁,網(wǎng)頁上有一個按鈕點擊可以喚起App。

這樣的效果是怎么實現(xiàn)的呢?瀏覽器是一個app;為什么一個app可以調(diào)起其他app的頁面?

說到跨app的頁面調(diào)用,大家是不是能夠想到一個機制:Activity的隱式調(diào)用?

隱式啟動原理

當我們有需要調(diào)起其他app的頁面時,使用的API就是隱式調(diào)用。

比如我們有一個app聲明了這樣的Activity:

  1. <activity android:name=".OtherActivity" 
  2.     android:screenOrientation="portrait"
  3.     <intent-filter> 
  4.         <action android:name="mdove"/> 
  5.         <category android:name="android.intent.category.DEFAULT"/> 
  6.     </intent-filter> 
  7. </activity> 

其他App想啟動上邊這個Activity如下的調(diào)用就好:

  1. val intent = Intent() 
  2. intent.action = "mdove" 
  3. startActivity(intent) 

我們沒有主動聲明Activity的class,那么系統(tǒng)是怎么為我們找到對應(yīng)的Activity的呢?其實這里和正常的Activity啟動流程是一樣的,無非是if / else的實現(xiàn)不同而已。

接下來咱們就回顧一下Activity的啟動流程,為了避免陷入細節(jié),這里只展開和大家相對“耳熟能詳”的類和調(diào)用棧,以串流程為主。

跨進程

首先我們必須明確一點:無論是隱式啟動還是顯示啟動;無論是啟動App內(nèi)Activity還是啟動App外的Activity都是跨進程的。比如我們上述的例子,一個App想要啟動另一個App的頁面,至少涉及3個進程。

注意沒有root的手機,是看不到系統(tǒng)孵化出來的進程的。也就是我們常見的為什么有些代碼打不上斷點。

追過startActivity()的同學(xué),應(yīng)該很熟悉下邊這個調(diào)用流程,跟進幾個方法之后就發(fā)現(xiàn)進到了一個叫做ActivityTread的類里邊。

ActivityTread這個類有什么特點?有main函數(shù),就是我們的主線程。

很快我們能看到一個比較常見類的調(diào)用:Instrumentation:

  1. // Activity.java 
  2. public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { 
  3.     mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); 
  4.     // 省略 

注意mInstrumentation#execStartActivity()有一個標黃的入?yún)ⅲ茿ctivityThread中的內(nèi)部類ApplicationThread。

ApplicationThread這個類有什么特點,它實現(xiàn)了IApplicationThread.Stub,也就是aidl的“跨進程調(diào)用的客戶端回調(diào)”。

此外mInstrumentation#execStartActivity()中又會看到一個大名鼎鼎的調(diào)用:

  1. public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { 
  2.     // 省略... 
  3.     ActivityManager.getService() 
  4.         .startActivity(whoThread, who.getBasePackageName(), intent, 
  5.                 intent.resolveTypeIfNeeded(who.getContentResolver()), 
  6.                 token, target != null ? target.mEmbeddedID : null
  7.                 requestCode, 0, null, options); 
  8.     return null

我們點擊去getService()會看到一個標紅的IActivityManager的類。

它并不是一個.java文件,而是aidl文件。

所以ActivityManager.getService()本質(zhì)返回的是“進程的服務(wù)端”接口實例,也就是:

ActivityManagerService

public class ActivityManagerService extends IActivityManager.Stub

所以執(zhí)行到這就轉(zhuǎn)到了系統(tǒng)進程(system_process進程)。省略一下代碼細節(jié),看一下調(diào)用棧:

從上述debug截圖,看一看到此時已經(jīng)拿到了我們的目標Activitiy的相關(guān)信息。

這里簡化一些獲取目標類的源碼,直接引入結(jié)論:

PackageManagerService

這里類相當于解析手機內(nèi)的所有apk,將其信息構(gòu)造到內(nèi)存之中,比如下圖這樣:

小tips:手機目錄中/data/system/packages.xml,可以看到所有apk的path、進程名、權(quán)限等信息。

啟動新進程

打開目標Activity的前提是:目標Activity的進程啟動了。所以第一次想要打開目標Activity,就意味著要啟動進程。

啟動進程的代碼就在啟動Activity的方法中:

resumeTopActivityInnerLocked->startProcessLocked。

這里便引入了另一個另一個大名鼎鼎的類:ZygoteInit。這里簡單來說會通過ZygoteInit來進行App進程啟動的。

ApplicationThread

進程啟動后,繼續(xù)回到目標Activity的啟動流程。這里依舊是一系列的system_process進行的轉(zhuǎn)來轉(zhuǎn)去,然后IApplicationThread進入目標進程。

注意看,在這里再次通過IApplicationThread回調(diào)到ActivityThread。

  1. class H extends Handler { 
  2.     // 省略 
  3.     public void handleMessage(Message msg) { 
  4.         switch (msg.what) { 
  5.             case EXECUTE_TRANSACTION: 
  6.                 final ClientTransaction transaction = (ClientTransaction) msg.obj; 
  7.                 mTransactionExecutor.execute(transaction); 
  8.                 // 省略 
  9.                 break; 
  10.             case RELAUNCH_ACTIVITY: 
  11.                 handleRelaunchActivityLocally((IBinder) msg.obj); 
  12.                 break; 
  13.         } 
  14.         // 省略... 
  15.     } 
  16.  
  17. // 執(zhí)行Callback 
  18. public void execute(ClientTransaction transaction) { 
  19.     final IBinder token = transaction.getActivityToken(); 
  20.     executeCallbacks(transaction); 

這里所謂的CallBack的實現(xiàn)是LaunchActivityItem#execute(),對應(yīng)的實現(xiàn):

  1. public void execute(ClientTransactionHandler client, IBinder token, 
  2.         PendingTransactionActions pendingActions) { 
  3.     ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo, 
  4.             mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, 
  5.             mPendingResults, mPendingNewIntents, mIsForward, 
  6.             mProfilerInfo, client); 
  7.     client.handleLaunchActivity(r, pendingActions, null); 

此時就轉(zhuǎn)到了ActivityThread#handleLaunchActivity(),也就轉(zhuǎn)到了咱們?nèi)粘5纳芷诶镞叄{(diào)用棧如下:

上述截圖的調(diào)用鏈中暗含了Activity實例化的過程(反射):

  1. public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { 
  2.  
  3.     return (Activity) cl.loadClass(className).newInstance(); 
  4.  

瀏覽器啟動原理

Helo站內(nèi)的回流頁就是一個標準的,瀏覽器喚起另一個App的實例。

交互流程

html標簽有一個屬性href,比如:。

我們常見的一種用法:。也就是點擊之后跳轉(zhuǎn)到百度。

因為這個是前端的標簽,依托于瀏覽器及其內(nèi)核的實現(xiàn),跳轉(zhuǎn)到一個網(wǎng)頁似乎很“順其自然”(不然叫什么瀏覽器)。

當然這里和android交互的流程基本一致:用隱式調(diào)用的方式,聲明需要啟動的Activity;然后傳入對應(yīng)的協(xié)議(scheme)即可。比如:

前端頁面:

  1. <head> 
  2.   <meta charset="UTF-8"
  3.   <meta name="viewport" content="width=device-width, initial-scale=1.0"
  4. </head> 
  5. <body> 
  6. <a href="mdove1://haha"> 啟動OtherActivity </a> 
  7. </body> 

android聲明:

  1. <activity 
  2.     android:name=".OtherActivity" 
  3.     android:screenOrientation="portrait"
  4.     <intent-filter> 
  5.         <data 
  6.             android:host="haha" 
  7.             android:scheme="mdove1" /> 
  8.         <action android:name="android.intent.action.VIEW" /> 
  9.         <category android:name="android.intent.category.BROWSABLE" /> 
  10.         <category android:name="android.intent.category.DEFAULT" /> 
  11.     </intent-filter> 
  12. </activity> 

推理實現(xiàn)

瀏覽器能夠加載scheme,可以理解為是瀏覽器內(nèi)核做了封裝。那么想要讓android也能支持對scheme的解析,難道是由瀏覽器內(nèi)核做處理嗎?

很明顯不可能,做了一套移動端的操作系統(tǒng),然后讓瀏覽器過來實現(xiàn),是不是有點殺人誅心。

所以大概率能猜測出來,應(yīng)該是手機中的瀏覽器app做的處理。我們就基于這個猜想去看一看瀏覽器.apk的實現(xiàn)。

瀏覽器實現(xiàn)

基于上邊說的/data/system/packages.xml文件,我們可以pull出來瀏覽器的.apk。

然后jadx反編譯一下Browser.apk中WebView相關(guān)的源碼:

我們可以發(fā)現(xiàn)對href的處理來自于隱式跳轉(zhuǎn),所以一切就和上邊的流程串了起來。

尾聲

 

結(jié)尾留個小問題:如果我自己寫個WebView去load一個前端頁面,能隱式跳轉(zhuǎn)嗎?

 

責(zé)任編輯:武曉燕 來源: 咸魚正翻身
相關(guān)推薦

2017-07-20 14:13:38

前端瀏覽器Native App

2012-06-04 10:35:55

FirefoxChrome瀏覽器

2011-02-22 09:50:21

2024-04-10 09:05:37

2019-02-13 23:03:06

IE瀏覽器微軟

2022-02-28 21:15:42

火狐火狐瀏覽器瀏覽器

2021-08-30 09:57:40

2009-06-15 08:37:08

微軟Windows 7操作系統(tǒng)

2016-08-18 14:29:21

瀏覽器Vendor Prefvendor-pref

2021-08-06 10:10:47

Safari開發(fā)者瀏覽器

2013-01-11 09:51:03

瀏覽器

2009-03-23 08:52:51

2022-01-04 21:36:33

JS瀏覽器設(shè)計

2010-04-05 21:57:14

Netscape瀏覽器

2009-03-04 11:16:03

RABSoft瀏覽器控制電腦

2017-01-05 18:57:19

2012-03-20 11:31:58

移動瀏覽器

2012-03-20 11:41:18

海豚瀏覽器

2012-03-19 17:25:22

2012-03-20 11:07:08

點贊
收藏

51CTO技術(shù)棧公眾號

麻豆天美蜜桃91| 日韩欧美三级电影| 国产小视频在线看| 日韩中文字幕视频网| 亚洲精品欧美二区三区中文字幕| 国产欧美一区二区三区在线| 人妻少妇精品一区二区三区| 国产精品18hdxxxⅹ在线| 懂色av一区二区三区| 日韩av在线电影观看| 国产精品国产一区二区三区四区| 国产精品观看| 亚洲人成五月天| 中文av字幕在线观看| 午夜av在线播放| av网站一区二区三区| 国产精品电影久久久久电影网| 色www亚洲国产阿娇yao| 88久久精品| 色综合天天综合狠狠| 国产又粗又爽又黄的视频| 成人av免费播放| 国产精品色网| 久久av中文字幕| 永久免费看mv网站入口78| 伊人国产精品| 色94色欧美sute亚洲线路二 | 欧美freesex8一10精品| 欧美无人高清视频在线观看| 91蜜桃免费观看视频| 欧美中文字幕在线播放| 国产午夜手机精彩视频| 你懂的视频欧美| 日韩精品一区二| 天天天干夜夜夜操| 国内精彩免费自拍视频在线观看网址| 国产精品不卡视频| 日韩av一区二区三区在线| 国产91久久久| 国产精品白丝av| 国产精品久久久久999| 日韩美女视频网站| 一区二区影院| 日韩中文字幕在线视频播放| 亚洲第一香蕉网| 国产精品qvod| 欧美一二三四在线| www.色就是色.com| 日本电影久久久| 欧美在线啊v一区| 成人观看免费完整观看| 免费在线小视频| 亚洲国产婷婷综合在线精品| 成人性做爰片免费视频| 欧美jizzhd69巨大| 欧美激情资源网| 奇米视频888战线精品播放| 亚洲欧美丝袜中文综合| 不卡视频免费播放| 成人免费看片网址| 性一交一乱一透一a级| 国产综合色精品一区二区三区| 国产女人精品视频| 一级黄色片在线播放| 久久99久久精品| 成人av电影天堂| 一级黄色片在线| 久久国产生活片100| 国产精品一区二区3区| 无码久久精品国产亚洲av影片| 久久久久综合| 国产精品久久久久久影视| 波多野结衣一区二区在线| 日本不卡一区二区三区| 国产精品人成电影在线观看| 伊人久久国产精品| 精品一区二区在线免费观看| 91九色单男在线观看| 国产绳艺sm调教室论坛| 国产一区二区精品久久91| 97免费资源站| 特黄视频在线观看| 久久久三级国产网站| 亚洲第一导航| 成人短视频在线| 亚洲亚洲精品在线观看| 免费看的黄色大片| 日韩国产网站| 欧美一区二区三区爱爱| www.555国产精品免费| 欧美三级午夜理伦三级小说| 国产亚洲福利一区| 日韩欧美国产成人精品免费| 亚洲国内欧美| 国产精品国产三级国产aⅴ9色| 国产又粗又猛又爽又黄的视频一| 国产成人综合网| 蜜桃狠狠色伊人亚洲综合网站| 在线免费观看的av网站| 亚洲国产sm捆绑调教视频 | 一级黄色性视频| 亚洲精彩视频| 日本不卡视频在线播放| 国产精品久久久久久久一区二区| 成人av综合在线| 色噜噜狠狠一区二区三区| av网址在线免费观看| 都市激情亚洲色图| 手机精品视频在线| 性欧美lx╳lx╳| 久久天堂电影网| 国产精品suv一区| 国产福利一区二区| 少妇免费毛片久久久久久久久 | 97在线免费视频| 亚洲第一网站在线观看| 国产精品一区二区你懂的| 久久草.com| 在线日本中文字幕| 亚洲国产日韩a在线播放| 美女少妇一区二区| 超碰成人在线免费| 色偷偷av亚洲男人的天堂| 久一区二区三区| 日韩成人一区二区| 粉嫩精品一区二区三区在线观看 | 亚洲6080在线| 国产精品天天av精麻传媒| 日韩精品视频中文字幕| 亚洲免费高清视频| 亚洲天堂日韩av| 免费高清在线一区| 精品国产一区二区三区日日嗨| 五月婷婷在线观看| 疯狂做受xxxx欧美肥白少妇| √天堂资源在线| 自拍自偷一区二区三区| 欧美激情中文网| 一本一道精品欧美中文字幕| 99久久伊人网影院| 天天操天天干天天玩| 亚洲1234区| 亚洲国产精彩中文乱码av| 国产中文字幕久久| 久久精品免费观看| 欧美日韩免费精品| heyzo一区| 日韩一卡二卡三卡四卡| 国产日韩精品中文字无码| 欧美一级播放| 国产高清精品一区二区| 天堂av资源在线观看| 欧美精品三级在线观看| 少妇无套高潮一二三区| 国产日韩亚洲欧美精品| 国产98在线|日韩| av超碰免费在线| 欧美日韩一区中文字幕| 国产91丝袜美女在线播放| 国产视频一区免费看| 国产精品视频在线免费观看| 天天色天天射天天综合网| 欧美一区二区久久久| 国产一二三四视频| 国产一区二区三区免费在线观看| 日韩三级电影免费观看| 台湾佬中文娱乐久久久| 日韩av影视在线| 91香蕉在线视频| 成人美女视频在线观看| 女人床在线观看| 国产精品久久久久av蜜臀| 久久久久久久香蕉网| 亚洲经典一区二区三区| 亚洲一二三四久久| 黄色网址在线视频| 国产一区导航| 亚洲综合av一区| 四虎成人精品一区二区免费网站| 一区二区三区四区视频| 中文字幕av网站| 中文字幕欧美三区| 蜜臀一区二区三区精品免费视频| 伊人色**天天综合婷婷| 亚洲专区在线视频| 中文在线免费| 亚洲国产精品yw在线观看| 日韩黄色a级片| 久久久九九九九| 亚洲精品国产一区二区三区| 欧美激情亚洲| 精品日本一区二区三区在线观看| 中文在线免费二区三区| 亚洲毛片在线观看| 在线观看中文字幕av| 国产精品网站在线播放| 6080国产精品| 激情另类综合| 欧美在线视频一区二区三区| www.26天天久久天堂| 色婷婷av一区二区三区久久| 中文字幕一区二区三区免费看| 一区二区三区精品视频在线| 国产chinese中国hdxxxx| 亚洲深夜福利| 亚洲国产精品一区在线观看不卡| 麻豆国产一区| 97av在线视频免费播放| 国产黄色小视频在线| 亚洲第一免费网站| 亚洲中文字幕无码爆乳av| 亚洲色图欧洲色图婷婷| 美女又爽又黄免费| 美女视频黄a大片欧美| 少妇高潮毛片色欲ava片| 欧美色就是色| 成人看片视频| 国产第一精品| 韩国v欧美v日本v亚洲| 成人在线免费公开观看视频| 亚洲国产高清福利视频| 中文字幕观看视频| 亚洲成人自拍一区| 青青青视频在线免费观看| 成人黄色小视频在线观看| 日本免费观看网站| 国产一区视频在线观看免费| 亚洲一区免费看| 欧亚精品一区| 91嫩草在线| 91天天综合| 久久久久中文字幕| 肉体视频在线| 伊人久久久久久久久久久久久 | 在线激情免费视频| 亚洲精品720p| 国产精品无码免费播放| 色噜噜久久综合| 国产无遮挡又黄又爽在线观看| 国产精品少妇自拍| 卡一卡二卡三在线观看| 成人精品国产一区二区4080| 亚洲图色中文字幕| 久久一区精品| 九色在线视频观看| 国产主播精品| 99久久久无码国产精品性色戒| av亚洲免费| 免费成人av网站| 国产在线播放精品| 444亚洲人体| 亚洲三级电影| 国产精品成人播放| 91精品xxx在线观看| 久久久免费av| 日本大胆在线观看| 欧美成人激情视频免费观看| 成人在线app| www.亚洲成人| 日本免费视频在线观看| 色系列之999| av中文在线| 最新69国产成人精品视频免费| 番号集在线观看| 亚洲视频在线免费观看| 九一国产在线| 精品视频偷偷看在线观看 | 亚洲人av在线影院| 四虎在线免费观看| 日韩精品中文在线观看| 天堂av电影在线观看| 精品国产髙清在线看国产毛片| 欧美一区二区三区成人片在线| 精品日韩一区二区三区| 亚洲成人中文字幕在线| 欧美成人精品福利| 亚洲精品一区二区三区蜜桃 | 久久久久久国产精品久久| 免费av不卡在线观看| 性欧美办公室18xxxxhd| 性xxxxfreexxxxx欧美丶| 2019亚洲日韩新视频| 欧美久久天堂| 国产精品国语对白| 24小时成人在线视频| 国产精品一区久久久| 国产成人免费av一区二区午夜| 国产精品自产拍在线观看| 警花av一区二区三区| 国产精品日韩一区二区免费视频| 开心激情综合| 日韩免费电影一区二区三区| 亚州av乱码久久精品蜜桃| 欧美 亚洲 视频| 日韩一区二区久久| 欧美激情精品久久久久久小说| 美女视频网站久久| jizz日本免费| 欧美国产乱子伦| 一区二区成人免费视频| 亚洲高清免费视频| 波多野结衣黄色网址| 日韩精品一区二区三区在线| 日本福利片高清在线观看| 在线视频亚洲欧美| 后进极品白嫩翘臀在线播放| 国产精品久久视频| 日韩免费精品| 日韩av一区二区三区在线| 一区二区三区在线| 热久久精品国产| 丁香啪啪综合成人亚洲小说| 中国黄色a级片| 国产精品理伦片| 国产无遮挡又黄又爽| 欧美一级片免费看| 日韩在线免费播放| 久久资源免费视频| 自拍一区在线观看| 国产精品视频久久| 亚洲97av| 欧美日韩dvd| 青青草精品视频| 日韩免费高清一区二区| 亚洲欧美电影院| 欧美成人一区二区三区四区| 日韩一区二区中文字幕| 国产小视频在线观看| 久久福利网址导航| 4438五月综合| 日韩精品一区二区三区外面 | 99精品热视频| 日韩激情综合网| 日本精品视频一区二区| 欧美一区二区黄片| 欧美老妇交乱视频| 成人精品国产亚洲| 久久精品中文字幕一区二区三区 | 婷婷亚洲一区二区三区| 欧美成人小视频| 成人在线免费| 欧美亚洲另类久久综合| 国产精品一卡| 在线精品视频播放| 亚洲欧美韩国综合色| 91九色蝌蚪91por成人| 亚洲精品视频网上网址在线观看| 国产伦子伦对白在线播放观看| 91久热免费在线视频| 日本不卡免费一区| www.日本xxxx| 国产蜜臀av在线一区二区三区| 影音先锋亚洲天堂| 精品久久久久久久久久久久久久久久久 | 日韩久久久久久久久久久| 欧美激情资源网| 亚洲精品国产无码| 亚洲色图色老头| 成人短视频app| 日韩av高清| 日本中文字幕一区二区视频| 亚洲蜜桃精久久久久久久久久久久| 亚洲综合一区在线| 五月激情婷婷综合| 97国产精品视频| 久久香蕉网站| 男人日女人逼逼| 久久蜜桃av一区精品变态类天堂| 日本一级一片免费视频| 亚洲黄色av女优在线观看 | 久久成人18免费网站| 深夜福利亚洲| 黄色小视频大全| 国产精品一色哟哟哟| 精品无码久久久久久久| 亚洲精品一区二区久| 希岛爱理一区二区三区av高清| 日本一区二区免费看| 日本不卡一区二区| www.97视频| 欧美一区二区在线视频| 先锋影音在线资源站91| 国产麻豆一区二区三区在线观看| 母乳一区在线观看| 免费看黄色三级| 欧美一区二区精品在线| 99re6在线精品视频免费播放| 日本一区二区视频| 精品一区免费av| 久久久国产精品人人片| 亚洲第一免费播放区| 成人毛片免费| www婷婷av久久久影片| 91在线视频18| 影音先锋黄色网址| 久久久久中文字幕2018| 国内精品久久久久久99蜜桃| 亚洲一级片av| 一区二区成人在线| 川上优的av在线一区二区|