OH_AVScreenCapture 无法采集输入法悬浮窗?窗口排除与采集范围实战

前言

屏幕采集(OH_AVScreenCapture)在做录屏、直播、协同标注类应用时是刚需。开发者常遇到一个困惑:「我采集了整个屏幕,为什么软键盘的候选词/悬浮窗不在画面里?能不能把它也采进去?」这涉及 HarmonyOS 的窗口采集范围与隐私窗口排除策略。本文给出配置代码,并讲清哪些窗口能采、哪些被系统强制排除。

问题描述

  • 调用 OH_AVScreenCapture 录屏,回放时发现输入法(IME)候选词悬浮窗、键盘悬浮窗完全没出现
  • OH_AVScreenCapture_SetWindowSelection 指定窗口后,普通应用窗口能精准采集,但 IME 窗口依旧缺席;
  • 怀疑是自己 captureMode / dataType 配错,反复改 OH_AVScreenCapture_Config 无效;
  • 想「只录某个窗口」,结果录出来是整个屏幕。

根因不在你的配置,而在系统的隐私窗口排除规则 + 采集模式选择。

细节解析

  1. 两类采集模式

    • OH_Screen_Capture_Surface / INTRA 模式:采集整屏或指定显示,输出到 SurfaceVirtualScreen
    • 是否包含某些系统窗口由 windowSelection 控制。
  2. 隐私窗口默认被排除:出于安全,系统对以下窗口默认不采集:输入法窗口(含候选词、键盘悬浮窗)、系统状态栏/导航栏、密码输入框、锁屏、以及标记为 PRIVACY 的窗口。这是平台级策略,不是配置能绕过的

  3. OH_AVScreenCapture_SetWindowSelection 控制的是「要采集哪些可见窗口」:它用 WindowSelection(选择模式 + 窗口 ID 列表)决定采集范围。可以「采集全部可见窗口(排除隐私窗)」或「只采集指定的若干窗口」。即便你显式把 IME 窗口 ID 加进白名单,系统仍会因隐私策略屏蔽 IME 内容——所以你会看到「指定了但就是采不到」。

  4. 正确姿势

    • 想要「常规录屏(不含键盘)」:默认即可,无需额外配置;
    • 想要「只录某个应用窗口」:用 WindowSelectionWINDOW_SELECTION_BY_ID 并填目标窗口 ID 列表;
    • 想要「键盘也出现在画面里」:系统不允许采集 IME 隐私窗口,只能引导用户用物理键盘或把输入区做成应用内自定义输入框(属于你自己 App 的窗口,可采)。

示例代码

C 侧配置(采集指定窗口,IME 仍被排除):

#include <multimedia/screen_capture/av_screen_capture.h>

OH_AVScreenCapture *capture = OH_AVScreenCapture_Create();

OH_AVScreenCapture_Config config;
config.captureMode = OH_SCREEN_CAPTURE_MODE_SURFACE;
config.dataType = OH_SCREEN_CAPTURE_DATA_TYPE_VIDEO;
config.videoInfo.windowId = 0;            // 0 表示整屏
config.videoInfo.windowRect = (OH_Rect){0, 0, 0, 0}; // 全屏
config.audioInfo.micSwitch = false;
config.audioInfo.innerSwitch = false;

OH_AVScreenCapture_Init(capture, &config);

// 选择「只采集指定窗口」(IME 即便加入也会被隐私策略屏蔽)
OH_AVScreenCapture_WindowSelection selection;
selection.selectionMode = OH_WINDOW_SELECTION_BY_ID;
uint64_t ids[] = { targetWindowId }; // 你的业务窗口 ID
selection.windowIds = ids;
selection.windowCount = 1;
OH_AVScreenCapture_SetWindowSelection(capture, &selection);

OH_AVScreenCapture_Start(capture);

ArkTS 侧拿窗口 ID(用于「只录本应用窗口」):

import { window } from '@kit.ArkUI';

// 在 UIAbility 里获取当前窗口 ID
const win = await window.getLastWindow(this.context);
const id: number = win.getWindowProperties().id; // 传给 native 作为 targetWindowId

关键修正

  • 输入法候选词/键盘悬浮窗是隐私窗口,平台强制排除,任何配置都采不到——这不是 bug,别在 Config 上死磕;
  • SetWindowSelection 用来选「采集哪些可见窗口」(全屏 / 指定窗口),不是用来「解锁隐私窗」;
  • 若业务确需「输入内容出现在录屏里」,把输入控件做成应用内自定义组件(属于你自己的窗口,可采),而非依赖系统 IME;或用外接物理键盘;
  • 排查顺序:确认 captureMode/dataType 正确 → 用 WindowSelection 选窗口 → 接受 IME 不可采的事实 → 需要就改产品设计。

总结

  • OH_AVScreenCapture 默认排除隐私窗口,IME(键盘/候选词悬浮窗)即属此类,系统级不可采集
  • OH_AVScreenCapture_SetWindowSelection 控制采集范围(整屏 or 指定窗口 ID),无法突破隐私策略;
  • 想「键盘进画面」:用应用内自定义输入框(自身窗口可采)或物理键盘,而非系统 IME;
  • 录指定窗口:用 OH_WINDOW_SELECTION_BY_ID + 目标 windowId,从 window.getWindowProperties().id 获取。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐