1# 虚拟屏的创建和使用 (ArkTS) (仅对系统应用开放) 2 3## 场景介绍 4 5虚拟屏是系统中的一种抽象,允许应用创建一个虚拟显示设备,不依赖于物理显示器。它通过Surface提供一个渲染目标,应用可以将图像、视频等内容渲染到这个虚拟显示设备上。 6 7## 接口说明 8 9以下为虚拟屏的常用接口。更多接口说明请参考[ @ohos.screen (屏幕)(系统接口)](../reference/apis-arkui/js-apis-screen-sys.md)。 10 11| 接口名 | 描述 | 12| ------------------------------------------------------------ | -------------------------------------------- | 13| createVirtualScreen(options:VirtualScreenOption): Promise<Screen> | 创建虚拟屏幕,使用Promise异步回调。 | 14| setVirtualScreenSurface(screenId:number, surfaceId: string): Promise<void> | 设置虚拟屏幕的Surface,使用Promise异步回调。 | 15| makeMirror(mainScreen:number, mirrorScreen:Array<number>): Promise<number> | 将屏幕设置为镜像模式,使用Promise异步回调。 | 16| stopMirror(mirrorScreen:Array<number>): Promise<void> | 停止屏幕的镜像模式,使用Promise异步回调。 | 17| destroyVirtualScreen(screenId:number): Promise<void> | 销毁虚拟屏幕,使用Promise异步回调。 | 18 19## 开发步骤 20 211. 创建虚拟屏。 22 23 - 定义用于创建虚拟屏的各项参数。 24 25 - 通过createVirtualScreen()创建虚拟屏。 26 27 需特别注意的是,使用createVirtualScreen()创建虚拟屏时,需要申请`ohos.permission.CAPTURE_SCREEN`权限,配置方式请参见[申请使用受限权限](../security/AccessToken/declare-permissions-in-acl.md)。 28 292. 将渲染目标SurfaceID绑定在虚拟屏上。 30 31 为了使虚拟屏能够准确呈现所需的图像内容,需要将渲染目标的SurfaceID绑定到虚拟屏上。具体操作分为两步: 32 33 - 首先,通过getXComponentSurfaceId()方法获取Surface的唯一标识符SurfaceID。SurfaceID作为一个关键标识,承载着与屏幕图像信息相关的重要数据,借助它可以获取并灵活设置当前屏幕的各种图像属性,例如图像的分辨率、像素格式等。 34 35 - 然后,使用setVirtualScreenSurface()方法将获取到的SurfaceID与虚拟屏进行关联设置,从而确保虚拟屏能够正确接收和处理对应的图像数据。 36 373. 通过makeMirror()创建物理屏的镜像,并映射到虚拟屏上。 38 39 在成功创建虚拟屏之后,应用程序可依据具体的业务需求,通过调用makeMirror()方法来开启物理屏的镜像功能。该方法会将物理屏幕上正在显示的内容完整地复制,并映射到之前创建的虚拟屏上,实现物理屏与虚拟屏之间的实时同步显示。 40 414. 停止镜像。 42 43 当不再需要物理屏与虚拟屏之间的镜像同步功能时,可通过调用stopMirror()方法来停止镜像。这一操作将终止物理屏内容向虚拟屏的映射过程,使虚拟屏恢复到独立状态。 44 455. 销毁虚拟屏。 46 47 当整个业务流程结束,不再需要使用虚拟屏时,应及时释放相关资源,以避免内存泄漏和系统资源的浪费。通过调用destroyVirtualScreen接口,可安全、有效地将虚拟屏销毁,释放其所占用的系统资源。 48 49```ts 50import { BusinessError } from '@kit.BasicServicesKit'; 51import { screen } from '@kit.ArkUI'; 52 53@Entry 54@Component 55struct VirtualScreen { 56 xComponentController: XComponentController = new XComponentController(); 57 58 build() { 59 RelativeContainer() { 60 Column() { 61 XComponent({ 62 type: XComponentType.SURFACE, 63 controller: this.xComponentController 64 }) 65 } 66 Button('虚拟屏') 67 .onClick(() => { 68 // screenVirtualScreen用于存储创建的虚拟屏对象 69 let screenVirtualScreen: screen.Screen | null = null; 70 class VirtualScreenOption { 71 name: string = ''; 72 width: number = 0; 73 height: number = 0; 74 density: number = 0; 75 surfaceId: string = ''; 76 } 77 // option定义创建虚拟屏所需的参数 78 let option: VirtualScreenOption = { 79 name: 'screen01', 80 width: 1080, 81 height: 2340, 82 density: 2, 83 surfaceId: '' 84 }; 85 // 创建虚拟屏 86 screen.createVirtualScreen(option, (err: BusinessError, data: screen.Screen) => { 87 const errCode: number = err.code; 88 if (errCode) { 89 console.error(`Failed to create the virtual screen. Code:${err.code},message is ${err.message}`); 90 return; 91 } 92 screenVirtualScreen = data; 93 console.info('Succeeded in creating the virtual screen. Data: ' + JSON.stringify(data)); 94 // 获取surfaceId 95 let surfaceId = this.xComponentController.getXComponentSurfaceId(); 96 screen.setVirtualScreenSurface(screenVirtualScreen.id, surfaceId, (err: BusinessError) => { 97 const errCode: number = err.code; 98 if (errCode) { 99 console.error(`Failed to set the surface for the virtual screen. Code:${err.code},message is ${err.message}`); 100 return; 101 } 102 console.info('Succeeded in setting the surface for the virtual screen.'); 103 }); 104 let mirrorScreenIds: Array<number> = [screenVirtualScreen.id]; 105 // 获取当前所有屏幕 106 screen.getAllScreens((err: BusinessError, data: Array<screen.Screen>) => { 107 const errCode: number = err.code; 108 if (errCode) { 109 console.error(`Failed to get all screens. Code:${err.code},message is ${err.message}`); 110 return; 111 } 112 // 通过makeMirror创建物理屏的镜像,并映射到虚拟屏上 113 let mainScreenId = data.find(item => item.sourceMode === 0)?.id; 114 screen.makeMirror(mainScreenId, mirrorScreenIds, (err: BusinessError, data: number) => { 115 const errCode: number = err.code; 116 if (errCode) { 117 console.error(`Failed to set screen mirroring. Code:${err.code},message is ${err.message}`); 118 return; 119 } 120 console.info('Succeeded in setting screen mirroring. Data: ' + JSON.stringify(data)); 121 }); 122 // 停止镜像 123 screen.stopMirror(mirrorScreenIds, (err: BusinessError) => { 124 const errCode: number = err.code; 125 if (errCode) { 126 console.error(`Failed to stop mirror screens. Code:${err.code},message is ${err.message}`); 127 return; 128 } 129 console.info('Succeeded in stopping mirror screens.'); 130 }); 131 // 销毁虚拟屏 132 screen.destroyVirtualScreen(mirrorScreenIds[0], (err: BusinessError) => { 133 const errCode: number = err.code; 134 if (errCode) { 135 console.error(`Failed to destroy the virtual screen. Code:${err.code},message is ${err.message}`); 136 return; 137 } 138 console.info('Succeeded in destroying the virtual screen.'); 139 }); 140 }); 141 }); 142 }) 143 } 144 .height('100%') 145 .width('100%') 146 } 147} 148```