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

Android中使用Media Projection API投射的画面无法显示在SurfaceView悬浮窗上

Android中使用Media Projection API投射的画面无法显示在SurfaceView悬浮窗上

看起来你已经把基础的权限、前台服务配置都做了,但投射画面就是不显示,这种没报错的问题确实挺头疼的。我结合你的代码梳理几个可能的关键点,你可以逐一排查试试:

1. Surface与MediaProjection的初始化时机不匹配

你的代码里,在onStartCommand拿到MediaProjection后,会直接检查mSurface != null就启动录屏,但windowManager.addView(view, params)是异步执行的,SurfaceHolder的surfaceCreated回调可能还没触发——这时候你拿到的mSurface其实是未初始化的空对象,自然无法渲染画面。

调整方案:

  • 新增一个布尔变量mSurfaceReady标记Surface是否准备完成
  • 在surfaceCreated回调里标记Surface就绪,同时检查MediaProjection是否已拿到,若已拿到则启动录屏:
private boolean mSurfaceReady = false;

// 在setupOverlay的SurfaceHolder.Callback中
@Override
public void surfaceCreated(SurfaceHolder holder) {
    mSurface = holder.getSurface();
    mSurfaceReady = true;
    if (mMediaProjection != null) {
        startScreenCapture();
    }
}
  • 在onStartCommand拿到MediaProjection后,检查Surface是否就绪,再启动录屏:
mMediaProjection = mediaProjectionManager.getMediaProjection(rc, d);
if (mMediaProjection != null && mSurfaceReady) {
    startScreenCapture();
}

2. VirtualDisplay的参数可能存在问题

你创建VirtualDisplay时用了DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,这个标记在某些场景下可能会导致投射逻辑异常;另外固定的900x500尺寸要确保和SurfaceView的实际显示尺寸完全匹配。

调整方案:
把标记换成DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,同时确认尺寸参数和悬浮窗一致:

mVirtualDisplay = mMediaProjection.createVirtualDisplay(
    "ScreenCapture",
    900,
    500,
    getResources().getDisplayMetrics().densityDpi,
    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC, // 替换为这个标记
    mSurface,
    null,
    null
);

3. SurfaceView的像素格式可能不兼容

你设置的PixelFormat.OPAQUE可能会和MediaProjection的渲染格式冲突,导致画面无法显示。

调整方案:
修改悬浮窗LayoutParams的像素格式为PixelFormat.RGBA_8888:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    900,
    500,
    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
    PixelFormat.RGBA_8888 // 更换像素格式
);

4. 新增日志排查VirtualDisplay创建状态

虽然没有报错日志,但可以手动添加日志确认VirtualDisplay是否成功创建:

public void startScreenCapture() {
    // ... 原有代码
    mVirtualDisplay = mMediaProjection.createVirtualDisplay(...);
    if (mVirtualDisplay == null) {
        Log.e("ScreenCapture", "VirtualDisplay创建失败!");
    } else {
        Log.d("ScreenCapture", "VirtualDisplay创建成功");
    }
}

关于TextureView的补充尝试

你之前换TextureView没效果,可能是因为TextureView的使用逻辑和SurfaceView不同,需要设置SurfaceTextureListener来获取Surface:

// 假设screenMirror是TextureView
screenMirror.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
        mSurface = new Surface(surfaceTexture);
        mSurfaceReady = true;
        if (mMediaProjection != null) {
            startScreenCapture();
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) {}

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        mSurface.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}
});

你可以先从「时机匹配」这个点入手调整,这是这类问题最常见的原因。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:48:00