OpenHarmony分布式屏幕开发参考示例

简介

分布式屏幕功能早在OpenHarmony-3.1-Release就已经发布。

本示例基于OpenHarmony自带的分布式屏幕相关API,并简单实现了屏幕镜像(或扩展)投屏相关应用功能。示例主要分为ArkTS版本和C++版本,ArkTS版本目前主要基于API9版本分布式屏幕功能的API进行开发。开发者可自行基于API10开发,其中API10版本增加了停止屏幕镜像(或扩展)的API。

效果预览

首页

菜单

设备管理

*虚拟屏幕

应用界面中展示可以点击镜像投屏或扩展投屏,为了添加分布式设备,可以在菜单中进入设备管理页面进行添加。此外,开发者可创建虚拟屏幕,在本机预览投屏后的效果(开启虚拟屏幕会增加系统负荷)。

工程目录

entry/src/main/
|-- ets
|   |-- common
|   |   |-- Constant.ets
|   |   |-- Logger.ts             // 日志工具
|   |   |-- TitleBar.ets
|   |-- entryability
|   |   |-- EntryAbility.ets
|   |-- model
|   |   |-- RemoteDeviceModel.ets
|   |-- pages
|   |   |-- DeviceManager.ets
|   |   |-- FilterOption.ets
|   |   |-- Index.ets            // 首页
|   |   |-- ListDeviceView.ets
|   |-- utils
|       |-- Permission.ts
...
docs
|-- distributed_screen
|   |-- BUILD.gn
|   |-- include
|   |-- src
|       |-- dscreen_expand.cpp  // 扩展投屏C++实现
|       |-- dscreen_mirror.cpp  // 镜像投屏C++实现

具体实现

ArkTS实现

通过在IDE中创建工程,并调用https://docs.openharmony.cn/pages/v3.2/zh-cn/application-dev/reference/apis/js-apis-screen.md 中相关API进行实现,主要实现如下:

makeScreenMirror() {
    logger.info('makeScreenMirror')
    let mainScreenId = 0;
    let mirrorScreenIds: Array<number> = [];

    if (this.enableVirtualScreen) {
      mirrorScreenIds.push(this.virtualScreenId);
    }

    for (let i = this.allScreens.length - 1; i >= 0; i--) {
      if ((this.allScreens[i].id != 0) && (this.allScreens[i].id != 1)) {
        mirrorScreenIds.push(this.allScreens[i].id);
      }
    }

    if (mirrorScreenIds.length == 0) {
      constant.showToast("No found Screen!")
      return;
    }

    try {
      logger.info('mirrorScreenIds:' + JSON.stringify(mirrorScreenIds))
      screen.makeMirror(mainScreenId, mirrorScreenIds, (err, data) => {
        if (err.code) {
          constant.showToast("Failed to makeMirror")
          console.error('Failed to set screen mirroring. Code: ' + JSON.stringify(err));
          return;
        }
        constant.showToast("Succeeded to makeMirror")
        console.info('Succeeded in setting screen mirroring. Data: ' + JSON.stringify(data));
      });
    } catch (exception) {
      constant.showToast("Failed to makeMirror")
      console.error('Failed to set screen mirroring. Code: ' + JSON.stringify(exception));
    }
  }

  makeScreenExpand() {
    logger.info('makeScreenExpand')
    let mainScreenId = 0;
    let startX = display.getDefaultDisplaySync().width;
    let startY = 0;
    let expandExpandOption: Array<screen.ExpandOption> = [];

    expandExpandOption.push({ screenId: mainScreenId, startX: 0, startY: 0 });

    if (this.enableVirtualScreen) {
      expandExpandOption.push({ screenId: this.virtualScreenId, startX: startX, startY: startY });
    }

    for (let i = this.allScreens.length - 1; i >= 0; i--) {
      if ((this.allScreens[i].id != 0) && (this.allScreens[i].id != 1)) {
        expandExpandOption.push({ screenId: this.allScreens[i].id, startX: startX, startY: startY });
      }
    }

    if (expandExpandOption.length <= 1) {
      constant.showToast("No found Screen!")
      return;
    }

    try {
      screen.makeExpand(expandExpandOption)
        .then((data) => {
          constant.showToast("Succeeded to makeExpand")
          console.info('Succeeded in expanding the screen. Data: ' + JSON.stringify(data));
        })
        .catch((err) => {
          constant.showToast("Failed to makeExpand")
          console.error('Failed to expand the screen. Code:' + JSON.stringify(err));
        });
    } catch (exception) {
      constant.showToast("Failed to makeExpand")
      console.error('Failed to expand the screen. Code: ' + JSON.stringify(exception));
    }
  }

主要使用到https://docs.openharmony.cn/pages/v3.2/zh-cn/application-dev/reference/apis/js-apis-screen.md 中的相关API如下:

方法名称 描述
screen.getAllScreens 获取所有的屏幕,可以是本地屏幕和其他设备的屏幕
screen.makeMirror 将屏幕设置为镜像模式
screen.makeExpand 将屏幕设置为扩展模式
C/C++实现

基于分布式屏幕的C/C++相关API实现一个简单的程序,并增加BUILD.gn用于开发者自行编译验证参考。

说明:源码及BUILD.gn在OpenHarmony-3.2-Release版本有验证,OpenHarmony-4.x版本,需要修改BUILD.gn

参考源码和BUILD.gn内容如下。

  1. dscreen_mirror.cpp

    #include "display.h"
    #include "display_manager.h"
    #include "screen.h"
    #include "screen_client.h"
    #include "screen_client_common.h"
    #include "screen_manager.h"

    // ... (省略部分源码)

    using namespace std;
    using namespace OHOS;
    using namespace OHOS::DistributedHardware;
    using namespace OHOS::Rosen;
    using namespace OHOS::Media;

    int main(int argc, char **argv)
    {
    uint64_t remoteScreenId;
    std::string remoteScreenName;
    std::vector<uint64_t> mirrorIds;

     // 获取 screen 列表
     std::vector<sptr<Screen>> allScreens = ScreenManager::GetInstance().GetAllScreens();
    
     // 选择待镜像的远程目标 screen
     // IsReal 返回true时 代表为本地screen / false为远程screen
     // GetName 当返回screen的id 包含远程设备信息
     // GetId 返回screenId
     for (auto screen: allScreens) {
         mirrorIds.push_back(screen->GetId());
     }
    
     for (auto screen: allScreens) {
         if (!screen->IsReal()) {
           // 仅找第一个远程screen
           remoteScreenId = screen->GetId();
           remoteScreenName = screen->GetName();
           break;
         }
     }
    
     printf("[DscreenMirror] remoteScreenId : %lu.\n", remoteScreenId);
     printf("[DscreenMirror] remoteScreenName : %s.\n", remoteScreenName.c_str());
    
     // 选择待镜像的本地screen
     sptr<OHOS::Rosen::Display> defaultDisplay = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
     uint64_t localScreenId = defaultDisplay->GetScreenId();
    
     printf("[DscreenMirror] localScreenId : %lu...\n", localScreenId);
    
     // 调用接口并启动镜像投屏
     ScreenManager::GetInstance().MakeMirror(localScreenId, mirrorIds);
    
     printf("[DscreenMirror] Wait MakeMirror Stop.\n");
     getchar();
    
     // 停止
     std::vector<uint64_t> stopMirrorIds;
     stopMirrorIds.push_back(remoteScreenId);
     ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(stopMirrorIds);
    

    }

  2. dscreen_expand.cpp

    #include "display.h"
    #include "display_manager.h"
    #include "screen.h"
    #include "screen_client.h"
    #include "screen_client_common.h"
    #include "screen_manager.h"

    // ... (省略部分源码)

    int main(int argc, char **argv)
    {
    uint64_t remoteScreenId;
    std::string remoteScreenName;

     // 获取 screen列表
     std::vector<sptr<Screen>> allScreens = ScreenManager::GetInstance().GetAllScreens();
    
     // 选择待镜像的远程目标 screen
     // IsReal 返回true时 代表为本地screen / false为远程screen
     // GetName 当返回screen的id 包含远程设备信息
     // GetId 返回screenId
     for (auto screen: allScreens) {
         if (!screen->IsReal()) {
           // 仅找第一个远程screen
           remoteScreenId = screen->GetId();
           remoteScreenName = screen->GetName();
           break;
         }
     }
    
     printf("[DscreenExpand] remoteScreenId : %lu.\n", remoteScreenId);
     printf("[DscreenExpand] remoteScreenName : %s.\n", remoteScreenName.c_str());
    
     // 选择待拓展的本地screen
     sptr<OHOS::Rosen::Display> defaultDisplay = OHOS::Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
     uint64_t localScreenId = defaultDisplay->GetScreenId();
    
     printf("[DscreenExpand] localScreenId : %lu...\n", localScreenId);
    
     // 拓展屏幕与本地屏幕的位置关系
     std::vector<ExpandOption> options = {
         {localScreenId, 0, 0},
         {remoteScreenId, defaultDisplay->GetWidth(), 0}
     };
    
     // 调用结构启动拓展投屏
     ScreenManager::GetInstance().MakeExpand(options);
    
     printf("[DscreenExpand] Wait MakeExpand Stop.\n");
     getchar();
    
     // 停止投屏
     std::vector<uint64_t> stopExpandIds;
     stopExpandIds.push_back(remoteScreenId);
     ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(stopExpandIds);
    
     return 0;
    

    }

  3. BUILD.gn(仅供参考)

    import("//build/ohos.gni")
    import("//build/ohos_var.gni")
    import("//foundation/distributedhardware/distributed_screen/distributedscreen.gni")

    ohos_executable("dscreen_mirror") {
    sources = ["src/dscreen_mirror.cpp"]
    include_dirs = [
    ".",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_source/include",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_source/include/callback",
    "//foundation/distributedhardware/distributed_hardware_fwk/common/utils/include",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_sink/include",
    "//foundation/distributedhardware/distributed_screen/common/include/",
    "//foundation/distributedhardware/distributed_screen/services/screenclient/include/",
    ]

    cflags = [
    "-Wall",
    "-Werror",
    "-Wno-cast-qual",
    "-Wno-pointer-arith",
    "-Wno-unused-parameter",
    "-Wno-unused-variable",
    "-Wno-delete-incomplete",
    ]

    deps = [
    "{common_path}:distributed_screen_utils", "{interfaces_path}/innerkits/native_cpp/screen_sink:distributed_screen_sink_sdk",
    "{interfaces_path}/innerkits/native_cpp/screen_source:distributed_screen_source_sdk", "{services_path}/screenclient:distributed_screen_client",
    "{windowmanager_path}/dm:libdm", "{windowmanager_path}/wm:libwm",
    "//base/security/access_token/interfaces/innerkits/nativetoken:libnativetoken",
    "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc",
    "//foundation/communication/dsoftbus/adapter:softbus_adapter",
    "//foundation/communication/dsoftbus/sdk:softbus_client",
    "//foundation/graphic/graphic_2d:libsurface",
    "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics",
    "//foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform:platform",
    "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client",
    "//foundation/systemabilitymgr/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy",
    ]

    external_deps = [
    "hiviewdfx_hilog_native:libhilog",
    "multimedia_player_framework:media_client",
    ]

    install_enable = true
    install_images = [ "vendor" ]
    part_name = "rockchip_products" # 根据实际编译的产品调整part_name
    }

    ohos_executable("dscreen_expand") {
    sources = ["src/dscreen_expand.cpp"]
    include_dirs = [
    ".",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_source/include",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_source/include/callback",
    "//foundation/distributedhardware/distributed_hardware_fwk/common/utils/include",
    "//foundation/distributedhardware/distributed_screen/interfaces/innerkits/native_cpp/screen_sink/include",
    "//foundation/distributedhardware/distributed_screen/common/include/",
    "//foundation/distributedhardware/distributed_screen/services/screenclient/include/",
    ]

    cflags = [
    "-Wall",
    "-Werror",
    "-Wno-cast-qual",
    "-Wno-pointer-arith",
    "-Wno-unused-parameter",
    "-Wno-unused-variable",
    "-Wno-delete-incomplete",
    ]

    deps = [
    "{common_path}:distributed_screen_utils", "{interfaces_path}/innerkits/native_cpp/screen_sink:distributed_screen_sink_sdk",
    "{interfaces_path}/innerkits/native_cpp/screen_source:distributed_screen_source_sdk", "{services_path}/screenclient:distributed_screen_client",
    "{windowmanager_path}/dm:libdm", "{windowmanager_path}/wm:libwm",
    "//base/security/access_token/interfaces/innerkits/nativetoken:libnativetoken",
    "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc",
    "//foundation/communication/dsoftbus/adapter:softbus_adapter",
    "//foundation/communication/dsoftbus/sdk:softbus_client",
    "//foundation/graphic/graphic_2d:libsurface",
    "//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics",
    "//foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform:platform",
    "//foundation/graphic/graphic_2d/rosen/modules/render_service_client:librender_service_client",
    "//foundation/systemabilitymgr/samgr/interfaces/innerkits/samgr_proxy:samgr_proxy",
    ]

    external_deps = [
    "hiviewdfx_hilog_native:libhilog",
    "multimedia_player_framework:media_client",
    ]

    install_enable = true
    install_images = [ "vendor" ]
    part_name = "rockchip_products" # 根据实际编译的产品调整part_name
    }

    group("distributed_screen") {
    deps = [
    ":dscreen_mirror",
    ":dscreen_expand",
    ]
    }

相关权限

默认添加以下权限

权限名称 描述
ohos.permission.CAPTURE_SCREEN 允许应用截取屏幕图像
ohos.permission.DISTRIBUTED_DATASYNC 允许不同设备间的数据交换
ohos.permission.GET_BUNDLE_INFO 允许应用查询其他应用的信息。该权限仅适用于三方应用。
ohos.permission.INTERNET 允许使用Internet网络

说明:应用需采用系统签名,部分权限可根据是否使用相关模块进行删除

为了能让大家更好的学习鸿蒙 (Harmony OS) 开发技术,这边特意整理了《鸿蒙 (Harmony OS)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (Harmony OS)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. 应用开发导读(Java)

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ......

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ......
相关推荐
JasonYin~33 分钟前
HarmonyOS NEXT 实战之元服务:静态案例效果---电动车电池健康状况
华为·harmonyos
Ai鸿蒙36 分钟前
鸿蒙next之如何实现防截屏功能
华为·harmonyos
JasonYin~41 分钟前
HarmonyOS NEXT 实战之元服务:静态案例效果---咖啡制作实况窗
华为·harmonyos
天乐敲代码4 小时前
Etcd静态分布式集群搭建
数据库·分布式·etcd
光纤传感技术研究5 小时前
分布式光纤传感|分布式光纤测温|线型光纤感温火灾探测器DTS|DTS|DAS|BOTDA的行业16年的总结【2024年】
分布式·dts·光纤传感器·botda·光纤传感技术
dbcat官方5 小时前
1.微服务灰度发布(方案设计)
java·数据库·分布式·微服务·中间件·架构
凯子坚持 c7 小时前
解锁仓颉编程语言的奥秘:枚举类型、模式匹配与类接口全解析
开发语言·华为·harmonyos
JasonYin~7 小时前
HarmonyOS NEXT 实战之元服务:静态案例效果---电动车助手
harmonyos
明达技术7 小时前
分布式 IO 模块助力冲压机械臂产线实现智能控制
分布式
溟洵7 小时前
【C++】异步(并发)实现 线程池 ---附源码+实现步骤(future、async、promise、package_task、任务池原理和框架)
服务器·网络·c++·分布式·后端