How to capture a webview to bitmap in Android?
Asked Answered
M

3

10

I have a webview, and I need to scroll down to view all the content. Now, I want to capture the entire of the webview to a bitmap.

I looked for many times. People suggested me use the function capturePicture(). However, this function is deprecated. So, what other methods I can use to do to reach my goal?

Thanks all.

Matronize answered 3/1, 2014 at 9:17 Comment(0)
M
3

I found out the solution. Take a look of this.

I used the onDraw to replace the capturePicture functon which is deprecated in API 19. If you have any better solutions, please tell me and I appreciate that. Thanks!

Which can replace capturePicture function

Matronize answered 7/1, 2014 at 2:55 Comment(0)
A
14

Android L, you need to call WebView.enableSlowWholeDocumentDraw() before creating any WebViews. That is, if you have any WebViews in your layout, make sure you call this method before calling setContentView() in your onCreate().
linked Mikhail Naganov:https://mcmap.net/q/57758/-webview-draw-not-properly-working-on-latest-android-system-webview-update

@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        WebView.enableSlowWholeDocumentDraw();
    }
    ...
    setContentView(layout);
    ...
    ...
}

then:

/**
 * WevView screenshot
 * 
 * @param webView
 * @return
 */
public static Bitmap screenshot(WebView webView, float scale11) {
    try {
        float scale = webView.getScale();
        int height = (int) (webView.getContentHeight() * scale + 0.5);
        Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        webView.draw(canvas);
        return bitmap;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

if you don't use webView.getScale(), also:

public static Bitmap screenshot2(WebView webView) {
    webView.measure(MeasureSpec.makeMeasureSpec(
                    MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
    webView.setDrawingCacheEnabled(true);
    webView.buildDrawingCache();
    Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(),
            webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    Paint paint = new Paint();
    int iHeight = bitmap.getHeight();
    canvas.drawBitmap(bitmap, 0, iHeight, paint);
    webView.draw(canvas);
    return bitmap;
}
Adalbert answered 12/3, 2016 at 15:4 Comment(3)
Hi, Thanks for ur help. when I debug, 'webView.draw(canvas);' this line takes 3 seconds. Is there no way to use this line?? When I remove this line, I got a blank page.Gay
sorry, I hava no idea. :-( The page is too large?Adalbert
I'm using this answer successfully, without having to call enableSlowWholeDocumentDraw, on my Pixel 3a with Android 11.. thanks!!Wilford
M
3

I found out the solution. Take a look of this.

I used the onDraw to replace the capturePicture functon which is deprecated in API 19. If you have any better solutions, please tell me and I appreciate that. Thanks!

Which can replace capturePicture function

Matronize answered 7/1, 2014 at 2:55 Comment(0)
D
0

webView.draw() draws elements with software rendering, so it fails to draw <canvas> and probably some other elements, that sometimes are crucial for a website (f.ex. a game).

Since Android 8.0, it is possible to create an offscreen Surface and draw view (including webView) using hardware acceleration, which also would draw <canvas> elements.

Here is the code of doing that:

final View view = webView;
final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    final SurfaceTexture surfaceTexture = new SurfaceTexture(false);
    surfaceTexture.setDefaultBufferSize(view.getWidth(), view.getHeight());
    final Surface surface = new Surface(surfaceTexture);

    final Canvas hwCanvas = surface.lockHardwareCanvas();
    view.draw(hwCanvas);
    surface.unlockCanvasAndPost(hwCanvas);

    PixelCopy.request(surface, bitmap, new PixelCopy.OnPixelCopyFinishedListener() {
        @Override
        public void onPixelCopyFinished(int copyResult) {
            if (copyResult != PixelCopy.SUCCESS) {
                // failed to pixelcopy, fallback to software draw
                view.draw(new Canvas(bitmap));
            }
            surface.release();
            surfaceTexture.release();

            // use your bitmap here
            onBitmapDone.run(bitmap);
        }
    }, new Handler());
} else {
    view.draw(new Canvas(bitmap));
    onBitmapDone.run(bitmap);
}

This way enableSlowWholeDocumentDraw or setDrawingCacheEnabled(true) is not needed.

Dakota answered 28/6, 2024 at 1:16 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.