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

2024-01-08 18:32:15

简介

分布式屏幕功能早在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);

}
  1. 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;
}
  1. 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. ……

文章来源:https://blog.csdn.net/maniuT/article/details/135410280
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。