android 2.3 webkit

來源:互聯網
上載者:User

1.      前言

    大家對WebView應該不陌生, 它是Android裡面用來顯示網頁的控制項, 用它顯示網頁只需要幾行代碼, 如下:

public class WebViewDemoActivity extendsActivity {

   @Override

   public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.main);  

       mWebView = (WebView) findViewById(R.id.webview);

       mWebView.loadUrl("http://www.bkjia.com");   

    }

}

       這樣在WebViewDemoActivity啟動時就會顯示出google的首頁, 我們還可以在裡面輸入關鍵字進行搜尋。究竟WebView的loadUrl函數裡面究竟做了哪些事情呢?我們帶著好奇心走進android的Webkit世界。

2.      載入網頁過程的UML順序圖表

       這裡先給出loadUrl整個過程的uml順序圖表, 然後再慢慢分析。 。

3.      WebKit介紹 
       前面提到了Webkit,那究竟Webkit是什麼呢?它和我們所熟悉的WebView是什麼關係呢?這裡引用網上的解釋:“WebKit是一個開源的瀏覽器網頁排版引擎,包含WebCore排版引擎和JSCore引擎。WebCore和JSCore引擎來自於KDE項目的KHTML和KJS開源項目。Android平台的Web引擎架構採用了WebKit項目中的WebCore和JSCore部分,上層由Java語言封裝,並且作為API提供給Android應用開發人員,而底層使用WebKit核心庫(WebCore和JSCore)進行網頁排版。”可見,WebView就屬於Android的Webkit提供給應用開發人員用的上層API部分。
        很多偉大的軟體都是可移植的,Webkit也不例外。目前Webkit支援Qt,Gtk,Android等等。大家都知道移植是有條件的,比如要將linux系統移植到某個硬體平台,那麼這個硬體平台至少要有個硬體定時器來進行進程調度,要有mmu來支援虛擬記憶體管理,另外對系統ram和flash的空間也是有一定底線要求的。移植Webkit所要求的條件是什麼呢?先分析Webkit載入網頁的這樣一個過程:
l        從網路上把url地址上的html檔案下載到本地
l        詞法分析和文法分析
l        繪製
       很明顯,Webkit需要依賴平台相關的網路介面和圖形介面,如所示:

    可移植的軟體都可以分為兩部分:平台相關代碼和平台無關代碼。這兩部分之間的互動是通過固定介面來完成的,當然Webkit也不例外。對於Android Webkit,我們把它簡單看為兩部分:Android和WebCore。 Android到Webcore方向當然是直接調用的關係, 而WebCore有時也需要回調Android部分的代碼, 這就需要通過WebCore定義的一套固定的介面來完成。如所示, ResourceHandle是WebCore擷取網路資源的介面, Android平台對這個介面的實現是調用了Android API中的android.net.*包裡面的類實現的。 GraphicContext是WebCore繪製頁面的介面, Android平台對這個介面的實現是通過調用Android平台的2D繪圖引擎Skia實現的。
 
 
 
4.      載入網頁過程分析
    有一個很重要的概念需要解釋一下,Frame,翻譯成中文是“幀”,一個html頁面構成如,即一個html頁麵包含一個MainFrame,MainFrame中又可以包含0到n個子Frame。一個Frame對應一個Url,在MainFrame裡包含子Frame就意味著把子Frame的內容嵌入到MainFrame的一塊空間裡面。
      
        在WebKit裡面有個結構體WebCore::Frame,這個資料結構就包含了,一個網頁解析後的全部資料。下面就是從一個Url到產生一個MainFrame的過程。

       接下來就是要將Main frame裡面的資料顯示出來,這部分代碼是每個平台的實現都是不同的,我們以Android為例。首先需要說明的是,Android Webkit載入網頁是通過三個線程協作完成的:
l        UI線程:Android圖形系統派發事件的線程,WebView的onDraw函數和onTouchEvent函數就是運行在這個線程。UI線程只做一些輕量級的工作,會將耗時的工作轉給Webcore線程進行處理。
l        WebCore線程:在andriod.webkit.WebViewCore類中建立,負責html檔案解析等任務。
l        下載線程:在android.webkit.WebViewWorker中建立,負責下載從指定url下載html。
      
       當調用WebView.loadUrl時線程共同作業圖表如下,UI線程向WebCore線程發送訊息,WebCore線程接到訊息會把下載任務交給下載線程,下載線程下載完畢後通知WebCore線程進行html的解析,WebCore線程解析完html後通知UI線程重新整理介面。

       回顧一下這個圖:

       Webcore線程就是通過ResourceHandleAndroid來啟動下載線程下載html的,然後WebCore線程進行html解析,最後產生能夠描述整個html頁面的Main  frame,再通知UI線程繪製頁面。假設UI線程在onDraw函數裡需要通過分析Mainframe來繪圖,那麼很可能給人不流暢的感覺。所以WebCore線程在產生Frame結構體之後,又做了一個工作,就是解析Main frame並繪製到一塊記憶體上面,而UI線程在onDraw時只需把這塊記憶體上的內容繪製到螢幕上即可,這塊記憶體叫PictureSet。Picture是一個圖片集合,Main frame是Frame的集合,PictureSet裡面的Picture和Main frame裡面得Frame都是一一對應的關係。    
       還記得以前提到的代碼層次嗎?PictureSet是屬於Webkit的Andriod移植層的,而Frame是屬於WebCore層的,也就是說WebCore產生Frame後任務就完成了,然後會通過固定的介面通知Android移植層,Android移植層隨後分析Frame來產生PictureSet。在PictureSet產生後才會通知UI線程更新介面,WebView.onDraw中便會將PictureSet繪製到畫布上。
       最後需要補充說明的是,Android的Webkit移植層比其它平台相比多了jni部分,通過閱讀代碼你會發現WebView,WebViewCore等類在Java和C++部分都存在,它們是通過Java和c++一起實現的。
 
 

5.        Android Webkit外掛程式

5.1.     本章的目的

       引導讀者理解Android Webkit的外掛程式架構, 通過介紹本人研究過程閱讀過並認為有價值的文章,並對Android Framework源碼中的SampleBrowserPlugin裡難懂的地方進行解釋, 希望能夠清除讀者對怎樣寫Android Webkit外掛程式的疑惑。 SampleBrowserPlugin 是Android Webkit外掛程式的常式, 位於源碼中的development/samples/BrowserPlugin目錄下, 先看一下裡面的README檔案吧。

5.2.     推薦先看幾篇文章

l        https://developer.mozilla.org/en/Gecko_Plugin_API_Reference:雖然firefox是gecko的引擎,但是gecko和webkit的外掛程式同樣遵循NPAPI的標準, 這篇看完後就會弄如下幾個問題:
(1)什麼是Webkit外掛程式, 有什麼作用
(2)NPAPI一些函數和結構的作用。

l        http://www.bkjia.com/kf/201203/123782.html:這篇文章會協助你對Android Webkit外掛程式有個簡單的瞭解。

l       http://www.bkjia.com/kf/201203/123783.html:這篇文章提到了Android Webkit外掛程式的兩種模式。

5.3.      架構

外掛程式是用來擴充webkit的, 是webkit的智囊團。 例如有一種新類型的資料嵌在網頁裡,如所示, webkit不知如何處理, 此時webkit就會問他的外掛程式們如何處理"application/x-shockwave-flash”類型的資料。


 
<embed src="http://player.youku.com/player.php/Type/Folder/Fid/13005645/Ob/1/Pt/0/sid/XMzAxNDEwMTY4/v.swf"
quality="high"
width="480"
height="400"
align="middle"
allowScriptAccess="always"
allowFullScreen="true"
mode="transparent"
type="application/x-shockwave-flash">
</embed>
 
webkit寫在先,外掛程式產生再後。Webkit的設計者寫基類,外掛程式編寫者寫子類來實現基類的虛函數。同時,webkit也提供api供外掛程式的子類調用。這樣解釋來看,架構和Android Framework的思想一致,外掛程式系統的控制點在webkit (framework)。

的NPPluginFuncs是外掛程式必須要實現的介面,而如果你的外掛程式要擴充瀏覽器規定的介面,向通過網頁中的javascript指令碼調用到外掛程式的函數,就需要繼承NPClass來做擴充。下面代碼示範如何在網頁中調用外掛程式的擴充介面:
1.                 <embed type="application/plugin-mimetype">  
2.                 <script>  
3.                   var embed = document.embeds[0];   
4.                   embed.nativeMethod();   
5.                   alert(embed.nativeProperty);   
6.                   embed.nativeProperty.anotherNativeMethod();   
7.                 </script>
 

5.14.  編譯安裝SampleBrowserPlugin

l        進入android源碼頂層目錄運行:make SampleBrowserPlugin

       會產生out/target/product/generic/data/app/SampleBrowserPlugin.apk

l        開啟模擬器(模擬器建立時需要添加sdcard支援)

l        運行adb install “path to SampleBrowserPlugin.apk”

5.15.  運行常式

l        寫個s.html檔案內容如下:

<objecttype="application/x-testbrowserplugin" height=50 width=250>

    <param name="DrawingModel"value="Surface" />

    <param name="PluginType"value="Background" />

</object>

l        運行adb push “path to s.html” /mnt/sdcard

l        在模擬器中啟動Browser程式, 在地址欄輸入:file:///mnt/sdcard/s.html或file:///sdcard/s.html,結果如說明瀏覽器正確載入運行了外掛程式。



5.16. SampleBrowserPlugin.apk裡麵包含了什麼

l        libsampleplugin.so: NPAPI中plugin方的實現, 會安裝到/data/data/com.android.sampleplugin/lib目錄下。

l        一些配合libsampleplugin.so工作的java class。

l        一個“莫名其妙”的Service。

              為什麼說它“莫名其妙”?讓我們看看SamplePlugin.java的內容:

public class SamplePluginextends Service {

    @Override

    public IBinder onBind(Intentintent) {

        // TODO Auto-generated method stub

        return null;

    }

}

 

    初看覺得寫代碼的人是在開玩笑吧, 這樣的Service能有什麼用呢? 再看這個Service在AndroidManifest.xml裡的描述:

       <service android:name=".SamplePlugin">

            <intent-filter>

                <action android:name="android.webkit.PLUGIN" />

            </intent-filter>

            <meta-data android:name="type" android:value="native"/>

        </service>

    不過沒有這個Service, 現在有點啟發了嗎?試想一下Webkit是怎樣知道這個外掛程式的存在的呢?

Webkit是通過PackageManager查詢系統中能夠響應android.webkit.PLUGIN的Service來得到外掛程式安裝的路徑的。

5.17.  對Surface模式和Bitmap模式的理解

l        Surface模式:如果plugin要繪製的內容是動態就需要在單獨的surface上繪圖。

l        Bitmap模式:Webkit為Plugin提供繪圖的Bitmap, Plugin在上面繪圖後Webkit再把Bitmap         的內容繪製到WebView所在的Surface上面。

5.18. 具體分析

       百聞不如一見, 去看SampleBrowserPlugin的代碼吧, 結合上面提到的文檔, 條理就會很清晰。

摘自 愚蠢概念

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.