1. 程式人生 > >安卓系統原始碼編譯系列(七)——單獨編譯WebView相容性問題解決

安卓系統原始碼編譯系列(七)——單獨編譯WebView相容性問題解決

上一篇文章中,說明了單獨編譯WebView的流程,但是我們最後編譯出來的版本只能在對應系統版本的模擬器或者真機才能執行,下面我們就需要解決各個版本的相容問題。仔細分析不同版本執行時報的錯誤。

相容性問題解決

10-20 14:56:29.132: E/AndroidRuntime(523): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1285]:    36 cannot locate 'ucnv_setFromUCallBack_48'...

可以知道這是由於我們編譯出來的4.3版本的so庫載入了其他版本的so庫引起的,那麼我們只要將其中有問題的so庫改為靜態編譯即可。

將報錯的函式在原始碼目錄中搜索可知,這個函式位於external/icu4c/common目錄下的一個檔案中,檢視Android.mk檔案可知,這個檔案在庫libicuuc中。現在我們就將libicuuc庫靜態編譯為.a檔案。

external/icu4c/common/Android.mk檔案中,local_ldlibs := -lpthread -lm這行之後,加入以下內容:

#
# Static Build
#

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(src_files)
LOCAL_C_INCLUDES := $(c_includes) \
                abi/cpp/include
LOCAL_CFLAGS := $(local_cflags) -DPIC -fPIC
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES += libgabi++
LOCAL_LDLIBS += $(local_ldlibs)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libicuuc
include $(BUILD_STATIC_LIBRARY)

在終端中開啟原始碼根目錄,輸入以下命令編譯icu4c模組:

mmm external/icu4c

核心數夠的話,可以再加上-j4,編譯速度會快很多。編譯完成之後,可以在out/target/product/maguro/obj/STATIC_LIBRARIES/libicuuc_intermediates/libicuuc.a目錄下找到編譯出來的靜態庫。

除了libicuuc庫外,libicui18n庫也需要進行靜態編譯。在external/icu4c/i18n/Android.mk檔案中,同樣在local_ldlibs := -lpthread -lm這行之後加入以下內容:

#
# Static Build
#

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(src_files)
LOCAL_C_INCLUDES := $(c_includes) \
                abi/cpp/include
LOCAL_CFLAGS := $(local_cflags) -DPIC -fPIC
LOCAL_RTTI_FLAG := -frtti
LOCAL_SHARED_LIBRARIES += libicuuc libgabi++
LOCAL_LDLIBS += $(local_ldlibs)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libicui18n
include $(BUILD_STATIC_LIBRARY)

編譯完成之後,同樣可以在out/target/product/maguro/obj/STATIC_LIBRARIES/libicui18n_intermediates/libicui18n.a目錄下找到編譯出來的靜態庫。

下面我們將編譯出來的靜態庫靜態連結到libchromium_net2.so和libwebcore2.so中。先開啟external/chromium目錄下的Android.mk檔案,增加一行LOCAL_STATIC_LIBRARIES := libicui18n libicuuc(注意順序不能顛倒,否則會導致libicuuc中的部分函式找不到),同時在LOCAL_SHARED_LIBRARIES中將libicui18n libicuuc刪除,並加上libgabi++。修改完的內容如下:

LOCAL_WHOLE_STATIC_LIBRARIES += libevent modp_b64 dmg_fp libcutils
LOCAL_STATIC_LIBRARIES := libicui18n libicuuc
LOCAL_SHARED_LIBRARIES := libstlport libexpat libcrypto libssl libz     libsqlite libcutils libdl libgabi++

接下來我們還需要對libicui18n、libskia、libft2、libgui、libmedia、libicuuc、libui、libutils這幾個庫採用類似的方法進行靜態編譯。編譯完成之後,修改external/webkit下的Android.mk檔案中的LOCAL_SHARED_LIBRARIESLOCAL_STATIC_LIBRARIES如下:

LOCAL_SHARED_LIBRARIES := \
    libEGL \
    libGLESv2 \
    libandroid \
    libandroidfw \
    libandroid_runtime \
    libchromium_net2 \
    libcrypto \
    libdl \
    libmedia_native \
    libnativehelper \
    libsqlite \
    libssl \
    libstlport \
    libz \
    libgabi++ \
    libemoji \
    libbinder \
    libhardware \
    libhardware_legacy \
    liblog \
    libcorkscrew \
    libsonivox \
    libcamera_client \
    libstagefright_foundation \
    libaudioutils \
    libexpat
LOCAL_STATIC_LIBRARIES := libxml2 libxslt libhyphenation libskiagpu libv8 libicui18n libskia libft2 libgui libmedia libicuuc libui libutils

同時,由於AUTOFILL可能會在其他系統版本上出現空指標錯誤,我們需要將它禁掉。

ENABLE_AUTOFILL = false

禁掉之後,編譯有可能會出錯,external/webkit/Source/WebKit/android/jni/WebCoreFrameBridge.cpp該檔案會提示幾個函式找不到,加入相應的引入即可。

#include "base/memory/scoped_vector.h"

最後,如果執行時提示

java.lang.NoSuchMethodError: android.app.ActivityManager.isHighEndGfx

是由於雖然我們引入了系統編譯出來的jar包,但是載入的時候還是載入當前系統的jar包,導致找不到這個隱藏的方法。可以將該函式改為反射呼叫即可。

其他問題

1. 執行的時候提示:

 Dx 1 error; aborting
Conversion to Dalvik format failed with error 1

將Order and Export選項卡中的Android Private Libraries庫前的勾取消掉,再次執行即可

2. 編譯真機上執行的libchromium_net2.so或libwebcore2.so庫時,提示錯誤:
 make: *** No rule to make target `out/target/product/generic/obj/SHARED_LIBRARIES/libc_intermediates/export_includes', needed by `out/target/product/generic/obj/STATIC_LIBRARIES/libevent_intermediates/import_includes'.  Stop.
由於未指定target引起的,先執行以下命令再繼續編譯即可:
$ lunch full_maguro-eng

3. Eclipse中執行報錯:

 Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1891]:   172 could not load needed library 'libchromium_net2.so' for 'libwebcore2.so' (load_library[1093]: Library 'libchromium_net2.so' not found)
將chromium_net2和webcore2的載入順序顛倒即可:
 static {
    System.loadLibrary("chromium_net2");
    System.loadLibrary("webcore2");
}

4. 在不同版本的模擬器或裝置上執行程式報錯:
 Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1306]:   172 cannot locate 'u_charDirection_50'...

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN6icu_488Collator14createInstanceER10UErrorCode" referenced by "libchromium_net2.so"...

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN6icu_4814MessagePattern5clearEv" referenced by "libchromium_net2.so"...
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "usearch_open_48" referenced by "libwebcore2.so"...

java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libmedia_native.so" needed by "libwebcore2.so"; caused by library "libmedia_native.so" not found

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_Z19SkCreateRLEPixelRefRK8SkBitmap" referenced by "libwebcore2.so"...

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN7android21SurfaceComposerClient14getDisplayInfoEiPNS_11DisplayInfoE" referenced by "libwebcore2.so"...
lib庫路徑:frameworks/native/libs/gui

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN7android6Tracer4initEv" referenced by "libwebcore2.so"...
lib庫路徑:frameworks/native/libs/utils

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZNK7android10AudioTrack7latencyEv" referenced by "libwebcore2.so"...

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZNK7android6Region5writeEPvj" referenced by "libwebcore2.so"...

解決方案見“相容性問題解決”部分。

如果大家覺得對自己有幫助的話,還希望能幫頂一下,謝謝:)