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. ......
相关推荐
zhongcx3 小时前
鸿蒙应用示例:镂空效果实现教程
harmonyos
训山4 小时前
【11】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-模块化语法与自定义组件
笔记·学习·华为·harmonyos·鸿蒙系统
极客先躯4 小时前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
niu_sama5 小时前
仿RabbitMQ实现消息队列三种主题的调试及源码
分布式·rabbitmq
helloxmg5 小时前
鸿蒙harmonyos next flutter混合开发之开发package
flutter·华为·harmonyos
鸡c5 小时前
rabbitMq------客户端模块
分布式·rabbitmq·ruby
Dylanioucn6 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
路上^_^6 小时前
00_概览_kafka
分布式·kafka
极客先躯13 小时前
Hadoop krb5.conf 配置详解
大数据·hadoop·分布式·kerberos·krb5.conf·认证系统
CopyLower14 小时前
Kafka 消费者状态及高水位(High Watermark)详解
分布式·kafka