標籤:
原文 http://blog.csdn.net/zhaoxy_thu/article/details/18883015
本文主要對從安卓系統源碼中抽取出WebView相關源碼進行單獨編譯的流程進行說明。
編譯流程說明
由於WebView包含兩個部分,一部分是上層的Java代碼,包括若干Java類,用於對外提供介面;另一部分是下層的C++代碼,包括兩個so庫(libwebcore.so和libchromium_net.so),用於網頁的解析和渲染。兩個部分之間通過JNI進行互動。
因此,編譯WebView也需要分成兩部分,一部分是編譯Java代碼,另一部分是將C++代碼編譯成so庫。另外,由於WebView的Java代碼中會使用到很多系統的隱藏API,所以我們還需要編譯安卓系統,並從中擷取幾個jar包。
編譯Java代碼
首先,我們需要下載並編譯任意一個版本的安卓系統源碼,具體步驟可以參見《安卓系統源碼下載及編譯教程》。
完成編譯後,我們可以使用Eclipse(不能使用Intellij IDEA,因為之後添加library的時候無法設定為system library)建立一個Android工程,在src目錄下建立一個 android.webkit2 的包。然後將源碼目錄下的 frameworks/base/core/java/android/webkit 目錄下的所有檔案拷貝到新建立的包中。
由於其中有一個類是編譯之後產生的,所以我們還需要從編譯完的源碼目錄 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/webkit 中將EventLogTags.java類也拷貝到建立的包中。
接下來,我們需要在工程中加入包含系統隱藏API的jar包,將以下三個jar包重新命名(名稱隨意)後拷貝到工程的libs目錄下:
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jarout/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jarout/target/common/obj/JAVA_LIBRARIES/bouncycastle_intermediates/classes.jar
在Eclipse中開啟工程的Properties->Java Build Path->Libraries->Add Library->User Library,點擊下一步,選擇User Libraries...,選擇New,隨便輸入一個名字,將System library選上(重要),選擇OK。選中剛剛建立的User Library,選擇Add JARs,在工程目錄中選擇新加入的三個jar包,選擇OK。
添加完Library之後,切換到Order and Export選項卡,將剛剛建立的User library調整到最前面,確保隱藏API不會被系統API覆蓋(由於包名相同),選擇OK。另外,還要把Android Private Libraries庫前的勾取消掉,否則之後運行會報錯。
最後,由於我們的java檔案都放到了android.webkit2包下,避免與系統的包重名,我們需要將所有java檔案中的android.webkit都替換成android.webkit2。使用菜單中的Search命令批量替換即可。完成替換後,重新整理一下工程,會發現所有的錯誤都沒了。(有可能還會提示minSdkVersion版本太低,直接按要求修改AndroidManifest.xml檔案即可)
編譯so庫
此時我們的Eclipse工程已經可以編譯運行了,但是啟動的時候會閃退,因為我們還沒有加入so庫。下面我們就來編譯so庫。再回到虛擬機器中,進入到安卓源碼的external/chromium目錄下,在終端執行以下命令:
$ sudo sed -i "s#android/webkit#android/webkit2#g" `grep android/webkit -rl *`
可以將源碼中的android/webkit都替換成android/webkit2,確保與我們的java程式碼封裝名相同。
再開啟external/chromium目錄下的Android.mk檔案,將其中的libchromium_net都替換成libchromium_net2,同時增加一行LOCAL_MODULE_TAGS := optional,修改部分如下:
LOCAL_MODULE := libchromium_net2LOCAL_MODULE_CLASS := SHARED_LIBRARIESLOCAL_MODULE_TAGS := optionalINTERMEDIATES := $(call local-intermediates-dir)
再回到安卓源碼根目錄,運行以下命令:
$ source build/envsetup.sh$ mmm external/chromium
編譯成功後可以在 out/target/product/generic/obj/lib 目錄下找到libchromium_net2.so檔案。
接下來進入到安卓源碼的external/webkit/Source/WebKit/android目錄下,在終端執行以下命令:
$ sudo sed -i "s#android/webkit#android/webkit2#g" `grep android/webkit -rl *`
同樣可以將源碼中的android/webkit都替換成android/webkit2,確保與我們的java程式碼封裝名相同。
再開啟external/webkit目錄下的Android.mk檔案,將其中的libwebcore都替換成libwebcore2(三個地方),並且增加一行LOCAL_MODULE_TAGS := optional,另外還要將LOCAL_SHARED_LIBRARIES裡面的libchromium_net改成libchromium_net2。修改部分如下:
# Define our module and find the intermediates directoryLOCAL_MODULE := libwebcore2LOCAL_MODULE_CLASS := STATIC_LIBRARIESLOCAL_MODULE_TAGS := optionalbase_intermediates := $(call local-intermediates-dir)...LOCAL_SHARED_LIBRARIES := libEGL libGLESv2 libandroid libandroidfw libandroid_runtime libchromium_net2 libcrypto ...LOCAL_PRELINK_MODULE := falseLOCAL_MODULE := libwebcore2LOCAL_MODULE_TAGS := optionalLOCAL_LDLIBS := $(WEBKIT_LDLIBS)LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)LOCAL_STATIC_LIBRARIES := libwebcore2 $(WEBKIT_STATIC_LIBRARIES)LOCAL_LDFLAGS := -fvisibility=hidden
同樣再回到安卓源碼根目錄,運行以下命令:
$ source build/envsetup.sh$ mmm external/webkit
編譯成功後可以在 out/target/product/generic/obj/lib 目錄下找到libwebcore2.so檔案。
完成編譯並運行測試代碼
下面我們將以上編譯產生的兩個so檔案(libchromium_net2.so和libwebcore2.so)放到我們工程的 libs/armeabi 目錄下。再修改工程android.webkit2包下的JniUtil.java和WebViewCore.java檔案,將其中的
static { System.loadLibrary("webcore"); System.loadLibrary("chromium_net");}
改為(注意,順序也顛倒了)
static { System.loadLibrary("chromium_net2"); System.loadLibrary("webcore2");}
到此為止,與WebView相關的操作都完成了,我們可以開始加入測試代碼。在測試的Activity.java的onCreate方法中加入:
WebView webView = (WebView)findViewById(R.id.webview);webView.getSettings().setJavaScriptEnabled(true);webView.loadUrl("http://www.baidu.com");對應的xml layout中加入:
<android.webkit2.WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" />
最後在AndroidManifest.xml中加入:
<uses-permission android:name="android.permission.INTERNET"/>
現在我們就可以在模擬器上運行工程了,運行效果如下:
注意:
- 如果出現黑屏,可以嘗試將最後加入的INTERNET許可權去掉後重試。
- 只能在編譯時間對應版本的模擬器上運行,如果提示函數找不到,可以切換相應模擬器的版本後重試。
真機運行
在模擬器上運行成功之後可以在真機上運行,效果如下:
但是一旦用手指滑動WebView,應用就會閃退,原因是缺少一些資源,下面我們來將它們加上:
首先我們需要將安卓源碼目錄下的 frameworks/base/core/res/res/values/styles.xml 中的
<style name="ZoomControls"> <item name="android:gravity">bottom</item> <item name="android:paddingLeft">15dip</item> <item name="android:paddingRight">15dip</item></style>
粘貼到我們工程目錄下的 res/values/styles.xml 中。
然後再將 frameworks/base/core/res/res/layout/zoom_magnify.xml 檔案複製到我們工程目錄下的 res/layout 中。
接著將 frameworks/base/core/res/res/drawable/btn_zoom_page.xml 檔案複製到我們工程目錄下的 res/drawable 中。
最後將 frameworks/base/core/res/res 下的 drawable-ldpi 、 drawable-mdpi 、 drawable-hdpi 、 drawable-xhdpi 目錄下的 btn_zoom_page_normal.png 和 btn_zoom_page_press.png 檔案複製到我們工程目錄 res 下的相應檔案夾中。
再次運行,即可任意滑動WebView了。
參考資料
《 Android 4.1 - 將系統瀏覽器編譯成獨立應用 》
《 搭建自訂android Browser環境 》
如果大家覺得對自己有協助的話,還希望能幫頂一下,謝謝:)
安卓系統源碼編譯系列(六)——單獨編譯內建瀏覽器WebView教程