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

求助:Android Java WebView截图普通内容正常但视频内容空白

解决WebView中视频内容截图空白的问题

问题根源

WebView加载的视频(尤其是HTML5视频)通常通过SurfaceView或TextureView渲染,这类视图的内容直接绘制到硬件缓冲区,不属于View树的常规绘制流程。因此你使用的View.draw()或已废弃的getDrawingCache()方法,无法捕获到视频帧内容,只会得到空白或背景画面。

解决方案

方案1:使用MediaProjection系统级截图(推荐,支持所有视频类型)

MediaProjection是Android提供的系统级屏幕捕获API,可以捕获所有显示内容(包括SurfaceView/TextureView渲染的视频),但需要用户授权。

步骤1:申请屏幕捕获权限

private static final int REQUEST_MEDIA_PROJECTION = 1;
private MediaProjection mediaProjection;
private VirtualDisplay virtualDisplay;
private ImageReader imageReader;

// 触发系统权限请求
private void requestScreenCapturePermission() {
    MediaProjectionManager manager = 
        (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    Intent intent = manager.createScreenCaptureIntent();
    startActivityForResult(intent, REQUEST_MEDIA_PROJECTION);
}

步骤2:处理权限回调并捕获屏幕

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_MEDIA_PROJECTION && resultCode == RESULT_OK) {
        mediaProjection = 
            ((MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE))
            .getMediaProjection(resultCode, data);
        startScreenCapture();
    }
}

private void startScreenCapture() {
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int width = metrics.widthPixels;
    int height = metrics.heightPixels;
    int density = metrics.densityDpi;

    // 创建ImageReader用于接收屏幕帧
    imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 1);
    
    // 创建虚拟显示器,镜像屏幕内容到ImageReader的Surface
    virtualDisplay = mediaProjection.createVirtualDisplay(
        "WebViewVideoCapture",
        width, height, density,
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
        imageReader.getSurface(),
        null, null);

    // 监听图像可用事件,处理截图
    imageReader.setOnImageAvailableListener(reader -> {
        try (Image image = reader.acquireLatestImage()) {
            if (image == null) return;

            Image.Plane[] planes = image.getPlanes();
            ByteBuffer buffer = planes[0].getBuffer();
            int pixelStride = planes[0].getPixelStride();
            int rowStride = planes[0].getRowStride();
            int rowPadding = rowStride - pixelStride * width;

            // 转换为Bitmap
            Bitmap bitmap = Bitmap.createBitmap(
                width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
            bitmap.copyPixelsFromBuffer(buffer);
            
            // 裁剪掉空白区域(如果只需要WebView部分,可替换为WebView的坐标计算)
            Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
            
            // 复用你原有的上传逻辑
            processAndUploadBitmap(croppedBitmap);

            // 释放资源
            bitmap.recycle();
            croppedBitmap.recycle();
            virtualDisplay.release();
            mediaProjection.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }, new Handler(Looper.getMainLooper()));
}

步骤3:复用原有上传逻辑

把你原有的截图上传代码封装成processAndUploadBitmap方法,直接传入捕获到的Bitmap即可。


方案2:通过JavaScript捕获HTML5视频帧(无需系统权限)

如果WebView中的视频是标准HTML5 <video>元素,可以通过注入JS代码获取当前帧,转换为Base64后传递给原生代码。

webView.evaluateJavascript("(function() { " +
    "var video = document.querySelector('video'); " +
    "if (!video) return ''; " +
    "var canvas = document.createElement('canvas'); " +
    "canvas.width = video.videoWidth; " +
    "canvas.height = video.videoHeight; " +
    "var ctx = canvas.getContext('2d'); " +
    "ctx.drawImage(video, 0, 0); " +
    "return canvas.toDataURL('image/png'); " +
    "})();", new ValueCallback<String>() {
    @Override
    public void onReceiveValue(String base64Image) {
        if (TextUtils.isEmpty(base64Image) || !base64Image.startsWith("data:image/png;base64,")) {
            return;
        }
        // 解析Base64为Bitmap
        String pureBase64 = base64Image.substring("data:image/png;base64,".length());
        byte[] imageBytes = Base64.decode(pureBase64, Base64.DEFAULT);
        Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
        
        // 上传截图
        processAndUploadBitmap(bitmap);
    }
});

方案对比

方案优点缺点
MediaProjection支持所有视频类型,能捕获整个屏幕内容需要用户授权系统权限
JavaScript注入无需系统权限,仅捕获WebView内视频仅支持HTML5 <video>元素,依赖WebView启用JS

内容的提问来源于stack exchange,提问作者Vimukthi Shohan Jayawardana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:05:04