上一篇文章中,说明了单独编译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_LIBRARIES和LOCAL_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库前的勾取消掉,再次运行即可
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"...
解决方案见“兼容性问题解决”部分。