安卓系统源码编译系列(七)——单独编译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"...

解决方案见“兼容性问题解决”部分。


如果大家觉得对自己有帮助的话,还希望能帮顶一下,谢谢:)
转载请注明出处,谢谢!

安卓系统源码编译系列(七)——单独编译WebView兼容性问题解决

上一篇:SQL知识点补充及SQL优化


下一篇:The type 'MySqlConnectionStringBuilder' exists in both 'MySql.Data, Version=8.0.21.0,' and 'MySqlConnector, Version=0.45.1.0, Culture=neutral'