chromium34与39截图实现方式的差异

        从浏览器内核chromium34的代码移植到39的时候,发现之前做的截图接口不好用了,仔细分析,发现两个截图实现的机制不一样,又去分析了一下39的相关代码,现在把34和39的截图的实现方式和大家分享一下。这期间的版本,到底是哪个版本进行了修改,就不去一一查看了。

        众所周知,chromium展示网页是通过一个surfaceView不断刷新来展示的网页的。那么截图就成为一个问题,按照传统的截图方式不可以,baidu搜索onDraw方法中进行处理。chromium34在java层的代码中就是使用这种方法进行处理的,下面分别说下chromium34和39在实现截图功能上的方式。

        chromium34:

        在ContentViewRenderView中创建一个surfaceView,重写onDraw方法,在onDraw方法中调用nativeCompositeToBitmap(mNativeContentViewRenderView, bitmap),将createbitmap后的bitmap对象传进去,然后再调用canvas.drawBitmap(bitmap, 0, 0, null);就得到了webview网页的截图。(此webView并非系统webkit包下的webview,系统webView的截图方式并非如此,大家可以直接在eclipse里面F3查看源码就可以了)

        chromium39:

        ContentReadbackHandler中有一个方法:

        @CalledByNative
    private void notifyGetBitmapFinished(int readbackId, Bitmap bitmap) {
        GetBitmapCallback callback = mGetBitmapRequests.get(readbackId);
        if (callback != null) {
            mGetBitmapRequests.delete(readbackId);
            callback.onFinishGetBitmap(bitmap);
        } else {
            // readback Id is unregistered.
            assert false : "Readback finished for unregistered Id: " + readbackId;
        }
    }

        很明显这是一个c++层调用java层的回调函数,我明确的告诉你,传回来的bitmap就是截图。

        我们在需要的类中自己写一个函数,传入一个callBack,需要截图的时候发送一个消息,就可以从回调中拿到bitmap对象啦

public void getWebViewBitmap(float scale, Rect srcRect, final WebView.GetBitmapCallback callback) {
        if (null == mContentViewRenderView || null == mContentViewCore) {
            callback.onFinishGetBitmap(null);
            return;
        }
        ContentReadbackHandler.GetBitmapCallback content_read_callback = new ContentReadbackHandler.GetBitmapCallback() {
            public void onFinishGetBitmap(Bitmap bitmap) {
               if (null == callback) return;
               callback.onFinishGetBitmap(bitmap);
            }
        };
        ContentReadbackHandler handler = mContentViewRenderView.getContentReadbackHandler();
        handler.getContentBitmapAsync(scale, srcRect, mContentViewCore, content_read_callback);
    }

        另外:

        关于chromium34的更多详细的讲解,以及详细的代码,可以查看下面的博客文章:

        http://blog.csdn.net/u011882998/article/details/32708811

        至于从哪个版本修改的底层实现方式,我也不再去查了。小伙伴们可以看一下ContentViewRenderView这个类对应的c ++文件 content_view_render_view.cc中是否有下面的方法:jboolean ContentViewRenderView::CompositeToBitmap(JNIEnv* env, jobject obj,
                                                  jobject java_bitmap) {
  gfx::JavaBitmap bitmap(java_bitmap);
  if (!compositor_ || bitmap.format() != ANDROID_BITMAP_FORMAT_RGBA_8888)
    return false;
  return compositor_->CompositeAndReadback(bitmap.pixels(),
                                           gfx::Rect(bitmap.size()));
}

        关于bitmap图片保存成文件的代码实现(java和c++),大家可以看下下面的博客文章:

        http://blog.csdn.net/fingding/article/details/44242687

        最后,说下在完成这个功能来的感悟吧。在从chromium34迁移代码到39的时候,发现原来chromium实现截图的native方法不见了,怎么办呢?把native方法移植过来吗?仔细查了一圈,代码量太庞大,牵扯太多不靠谱。在c++代码中实现截图,回调给java层,当然没问题。但是我们小看了谷歌,我们竟然没有发现上面的接口,后来回想起来,也觉得自己傻傻的,有很多东西,我们根本不需要自己去实现,人家都已经弄好了的代码,直接用就行了。

        在修改chromium源码的时候,我们很多时候都不是代码的创造者,而是代码的搬运工。我们甚至很清楚的知道,不管是上层还是底层,java代码还是c++代码,更多的改动或者新增就意味可能带来更多的问题或者潜伏着的地雷,说不定哪天带来灾难性的后果。

        用有限的资源、简单的方式实现可靠的功能,才是王道!

你可能感兴趣的:(chromium)