You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

硬件加速下Android WebView转Bitmap的替代实现方案

核心问题

请问硬件加速开启场景下,如下WebView截帧代码的可用替代实现是什么?

myBitmap = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);

myWebView.layout(0, 0, 1280, 720);

myWebView.setDrawingCacheEnabled(true);
myWebView.buildDrawingCache();

canvas = new Canvas(myBitmap);
myWebView.draw(canvas);

问题详情

我正在实现将WebView渲染内容传输到Unity的功能,通过int数组完成像素数据传递,目前使用webView.draw方法已实现普通页面内容的捕获,无需关注onCreate函数的代码结构,已知其写法较为零散。

onCreate阶段核心代码如下:

protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        myWebView = new WebView(this);
        wcc = new WebChromeClient() {};
        myWebView.setWebChromeClient(wcc);
        //setContentView(myWebView);

        myWebView.getSettings().setJavaScriptEnabled(true);

        myWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        CookieManager.getInstance().setAcceptThirdPartyCookies(myWebView, true);

        myWebView.setBackgroundColor(Color.argb(1, 0, 1, 0));

        myWebView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    view.loadUrl(request.getUrl().toString());
                }
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public void onPageStarted(WebView webview, String url, Bitmap favicon) {
                super.onPageStarted(webview, url, favicon);
                webview.setVisibility(View.INVISIBLE);
            }

            @Override
            public void onPageFinished(WebView webview, String url) {

                webview.setVisibility(View.VISIBLE);
                super.onPageFinished(webview, url);

            }
        });
        myWebView.getSettings().setUserAgentString("Mozilla/5.0 (Linux; U; Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17");


        myWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null); //HARDWARE

        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); //HARDWARE

        myWebView.loadUrl("https://www.youtube.com/embed/QouNHuTnypQ");

        System.loadLibrary("NativeCameraPlugin");
        nativeInit();

        setContext(this);

        _renderScript = RenderScript.create(this);

        _handlerThread = new HandlerThread(TAG);
        _handlerThread.start();

        //startCamera();

    }

以下requestJavaRendering函数由Unity侧调用,改造自Unity安卓原生相机插件,用于在Unity渲染线程循环获取WebView图像并更新到OpenGL纹理:

private void requestJavaRendering(int texturePointer) {

        if (!_update) {
            return;
        }

        int[] imageBuffer = new int[0];

        if (myWebView != null) {
            imageBuffer = screenshot(myWebView); // 此处完成WebView到位图的转换
        }

        if (imageBuffer.length > 1) {
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texturePointer);

            GLES30.glTexSubImage2D(GLES30.GL_TEXTURE_2D, 0, 0, 0, 1280,
                    720, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE,
                    IntBuffer.wrap(imageBuffer));

        }
    }

当前故障现象

加载HTML5内容(如嵌入的YouTube视频)时,音频可正常播放,视频的暂停、静音、设置等控件也可正常显示,但视频画面为纯黑色。已尝试两种解决方案均未生效:

无法使用setLayerType(View.LAYER_TYPE_SOFTWARE, null)关闭硬件加速——关闭后即使调用setContentView(myWebView)将WebView添加到视图层级,也无法正常渲染视频内容。

尝试方案1:调用webView.draw截图

使用通用的View截图方法实现,但无法正常渲染视频画面,仅能捕获UI控件。经排查,基于Bitmap创建的Canvas不支持硬件渲染,已尝试在AndroidManifest的Activity、Application节点配置android:hardwareAccelerated="true",同时在Unity侧、代码中全局开启硬件加速,但调用canvas.isHardwareAccelerated()始终返回false。
对应截图实现代码:

public int[] screenshot(final WebView webView) {
        try {
            myBitmap = Bitmap.createBitmap(1280, 720, Bitmap.Config.ARGB_8888);

            myWebView.layout(0, 0, 1280, 720);

            myWebView.setDrawingCacheEnabled(true);
            myWebView.buildDrawingCache();

            canvas = new Canvas(myBitmap);
            myWebView.draw(canvas);

            IntBuffer intBuf = bitmapToRgba(myBitmap);
            int[] intArray = new int[intBuf.remaining()];
            intBuf.get(intArray);

            return intArray;
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

尝试方案2:基于VirtualDisplay实现

尝试使用虚拟显示方案捕获渲染内容,但始终获取到null图像,且不确定代码的正确调用位置,测试代码如下:

ir = ImageReader.newInstance(1280, 720, PixelFormat.RGBA_8888, 4);

        DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
        VirtualDisplay vd = dm.createVirtualDisplay("Test Display",
                1280, 720,
                DisplayMetrics.DENSITY_DEFAULT, ir.getSurface(), DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION);

        Presentation presentation = new Presentation(myWebView.getContext(), vd.getDisplay());
        presentation.show()

        Image img = ir.acquireLatestImage();
        Image.Plane[] planes = img.getPlanes();
        buff = planes[0].getBuffer().asIntBuffer();

已查阅Chromium官方WebView文档、StackOverflow相关问答、技术博客资料,但未找到可落地的实现步骤。


内容的提问来源于stack exchange,提问作者Warwlock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:51:16