zoukankan      html  css  js  c++  java
  • 安卓系统源码编译系列(六)——单独编译内置浏览器WebView教程

     

                      

    本文主要对从安卓系统源码中抽取出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.jar
    out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar
    out/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_net2
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_TAGS := optional
    INTERMEDIATES := $(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 directory
    LOCAL_MODULE := libwebcore2
    LOCAL_MODULE_CLASS := STATIC_LIBRARIES
    LOCAL_MODULE_TAGS := optional
    base_intermediates := $(call local-intermediates-dir)
    ...
    LOCAL_SHARED_LIBRARIES := 
    libEGL 
    libGLESv2 
    libandroid 
    libandroidfw 
    libandroid_runtime 
    libchromium_net2 
    libcrypto 
    ...
    LOCAL_PRELINK_MODULE := false
    LOCAL_MODULE := libwebcore2
    LOCAL_MODULE_TAGS := optional
    LOCAL_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"/>

    现在我们就可以在模拟器上运行工程了,运行效果如下: 

      

    注意:

    1. 如果出现黑屏,可以尝试将最后加入的INTERNET权限去掉后重试。
    2. 只能在编译时对应版本的模拟器上运行,如果提示函数找不到,可以切换相应模拟器的版本后重试。

    真机运行  

    在模拟器上运行成功之后可以在真机上运行,效果如下: 

      

    但是一旦用手指滑动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环境    》 

    如果大家觉得对自己有帮助的话,还希望能帮顶一下,谢谢:)

  • 相关阅读:
    如何:为 Silverlight 客户端生成双工服务
    Microsoft Sync Framework 2.1 软件开发包 (SDK)
    Windows 下的安装phpMoAdmin
    asp.net安全检测工具 Padding Oracle 检测
    HTTP Basic Authentication for RESTFul Service
    Windows系统性能分析
    Windows Server AppFabric Management Pack for Operations Manager 2007
    Mongo Database 性能优化
    服务器未能识别 HTTP 标头 SOAPAction 的值
    TCP WAIT状态及其对繁忙的服务器的影响
  • 原文地址:https://www.cnblogs.com/bigben0123/p/4521512.html
Copyright © 2011-2022 走看看