鸿蒙学习实战之路-Share Kit系列(15/17)-手机与PC/2in1设备间分享

最近好多朋友问我:“西兰花啊,我想实现手机与PC/2in1设备间分享功能,但不知道代码怎么写?” 害,这问题可问对人了!

今天这篇,我就手把手带你实现手机与PC/2in1设备间分享功能,从零到一,全程不超过 10 分钟(不含调试时间)~


手机与PC/2in1设备间分享是啥?

手机与PC/2in1设备间分享就是跨设备分享内容。比如:

  • 你在手机上看到一张好照片,想分享到电脑上查看
  • 你在电脑上看到一篇文章,想分享到手机上阅读

这就像前端的跨设备同步,只不过 Share Kit 是系统级别的服务,体验更统一。


需要申请权限吗?

是的,手机与PC/2in1设备间分享需要申请 ohos.permission.DISTRIBUTED_DATASYNC 权限。

配置权限

module.json5 中声明权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      }
    ]
  }
}

🥦 西兰花警告
我有个朋友忘记申请权限,结果跨设备分享一直不成功,debug 了两小时才发现是权限问题!血泪教训啊朋友们!


完整实现步骤

实现手机与PC/2in1设备间分享,就三步:

  1. 申请权限:在 module.json5 中声明权限
  2. 获取设备列表:使用 deviceManager 模块获取设备列表
  3. 分享到指定设备:使用 systemShare 模块分享到指定设备

步骤 1:申请权限

module.json5 中声明 ohos.permission.DISTRIBUTED_DATASYNC 权限。

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      }
    ]
  }
}

步骤 2:获取设备列表

使用 deviceManager 模块获取设备列表。

import { deviceManager } from '@kit.DistributedDeviceKit';

// 获取设备列表
deviceManager.getTrustedDeviceList((err, data) => {
  if (err) {
    console.error(`获取设备列表失败:${err}`);
    return;
  }
  console.log(`设备列表:${data}`);
});

步骤 3:分享到指定设备

使用 systemShare 模块分享到指定设备。

import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';

// 分享到指定设备
function shareToDevice(deviceId: string) {
  // 构造分享数据
  let shareData: systemShare.SharedData = new systemShare.SharedData({
    utd: 'general.text',
    uri: 'file://.../xxx.txt',
    title: '跨设备分享',
    description: '这是一段跨设备分享文本'
  });

  // 构建分享控制器
  let controller: systemShare.ShareController = new systemShare.ShareController(shareData);

  // 显示分享面板
  let uiContext: UIContext = this.getUIContext();
  let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;

  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DEFAULT,
    selectionMode: systemShare.SelectionMode.SINGLE,
    targetDeviceId: deviceId
  });
}

完整代码示例

把上面的步骤整合起来,就是一个完整的手机与PC/2in1设备间分享的实现:

import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';
import { deviceManager } from '@kit.DistributedDeviceKit';

@Entry
@Component
struct CrossDeviceSharePage {
  // 分享文本
  shareText: string = '这是一段跨设备分享文本';

  // 设备列表
  deviceList: Array<{ deviceId: string, deviceName: string }> = [];

  aboutToAppear() {
    // 获取设备列表
    this.getDeviceList();
  }

  // 获取设备列表
  getDeviceList() {
    deviceManager.getTrustedDeviceList((err, data) => {
      if (err) {
        console.error(`获取设备列表失败:${err}`);
        return;
      }
      this.deviceList = data.map(device => {
        return {
          deviceId: device.deviceId,
          deviceName: device.deviceName
        };
      });
    });
  }

  // 分享到指定设备
  shareToDevice(deviceId: string) {
    // 构造分享数据
    let shareData: systemShare.SharedData = new systemShare.SharedData({
      utd: 'general.text',
      uri: 'file://.../xxx.txt',
      title: '跨设备分享',
      description: this.shareText
    });

    // 构建分享控制器
    let controller: systemShare.ShareController = new systemShare.ShareController(shareData);

    // 显示分享面板
    let uiContext: UIContext = this.getUIContext();
    let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;

    controller.show(context, {
      previewMode: systemShare.SharePreviewMode.DEFAULT,
      selectionMode: systemShare.SelectionMode.SINGLE,
      targetDeviceId: deviceId
    });
  }

  build() {
    Column() {
      Text('跨设备分享示例')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin(20)
        .fontColor(Color.Black);

      Text(this.shareText)
        .fontSize(16)
        .margin({ left: 20, right: 20, bottom: 20 })
        .fontColor(Color.Gray);

      if (this.deviceList.length > 0) {
        Text('选择设备:')
          .fontSize(16)
          .margin(20)
          .fontColor(Color.Black);

        ForEach(this.deviceList, (device: { deviceId: string, deviceName: string }) => {
          Button(device.deviceName)
            .onClick(() => {
              this.shareToDevice(device.deviceId);
            })
            .margin(10);
        });
      } else {
        Text('暂无可用设备')
          .fontSize(16)
          .margin(20)
          .fontColor(Color.Gray);
      }
    }
    .width('100%')
    .height('100%');
  }
}

在实际项目中怎么用?

上面的代码是基础实现,但在实际项目中,你可能会这样用:

示例:跨设备分享图片

import { common } from '@kit.AbilityKit';
import { systemShare } from '@kit.ShareKit';
import { deviceManager } from '@kit.DistributedDeviceKit';

@Entry
@Component
struct CrossDeviceImageSharePage {
  // 分享图片
  shareImage: string = 'file://.../xxx.jpg';

  // 设备列表
  deviceList: Array<{ deviceId: string, deviceName: string }> = [];

  aboutToAppear() {
    // 获取设备列表
    this.getDeviceList();
  }

  // 获取设备列表
  getDeviceList() {
    deviceManager.getTrustedDeviceList((err, data) => {
      if (err) {
        console.error(`获取设备列表失败:${err}`);
        return;
      }
      this.deviceList = data.map(device => {
        return {
          deviceId: device.deviceId,
          deviceName: device.deviceName
        };
      });
    });
  }

  // 分享到指定设备
  shareToDevice(deviceId: string) {
    // 构造分享数据
    let shareData: systemShare.SharedData = new systemShare.SharedData({
      utd: 'general.image',
      uri: this.shareImage,
      title: '跨设备分享图片',
      preview: this.shareImage,
      description: '这是一张跨设备分享的图片'
    });

    // 构建分享控制器
    let controller: systemShare.ShareController = new systemShare.ShareController(shareData);

    // 显示分享面板
    let uiContext: UIContext = this.getUIContext();
    let context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext;

    controller.show(context, {
      previewMode: systemShare.SharePreviewMode.DEFAULT,
      selectionMode: systemShare.SelectionMode.SINGLE,
      targetDeviceId: deviceId
    });
  }

  build() {
    Column() {
      Text('跨设备分享图片示例')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin(20)
        .fontColor(Color.Black);

      Image(this.shareImage)
        .width(200)
        .height(200)
        .margin(20);

      if (this.deviceList.length > 0) {
        Text('选择设备:')
          .fontSize(16)
          .margin(20)
          .fontColor(Color.Black);

        ForEach(this.deviceList, (device: { deviceId: string, deviceName: string }) => {
          Button(device.deviceName)
            .onClick(() => {
              this.shareToDevice(device.deviceId);
            })
            .margin(10);
        });
      } else {
        Text('暂无可用设备')
          .fontSize(16)
          .margin(20)
          .fontColor(Color.Gray);
      }
    }
    .width('100%')
    .height('100%');
  }
}

常见问题

Q1:跨设备分享不成功怎么办?

检查以下几点:

  1. 是否申请了权限

    • 确认是否在 module.json5 中声明了 ohos.permission.DISTRIBUTED_DATASYNC 权限
    • 确认用户是否授权了该权限
  2. 设备是否在同一网络

    • 确认手机和PC/2in1设备是否在同一网络
    • 确认设备是否支持跨设备分享
  3. 设备是否已信任

    • 确认设备是否已添加到信任设备列表
    • 确认设备是否在线

Q2:如何添加设备到信任列表?

在设备的设置中,找到"分布式设备管理",添加设备到信任列表。

Q3:如何判断设备是否支持跨设备分享?

可以通过 deviceManager.getTrustedDeviceList 获取设备列表,然后检查设备类型:

deviceManager.getTrustedDeviceList((err, data) => {
  if (err) {
    console.error(`获取设备列表失败:${err}`);
    return;
  }
  data.forEach(device => {
    if (device.deviceType === 'PC' || device.deviceType === '2IN1') {
      console.log(`支持跨设备分享的设备:${device.deviceName}`);
    }
  });
});

下一步学什么?

看完这篇,你应该已经能实现手机与PC/2in1设备间分享了。接下来可以深入学习:

  1. 隔空传送与可信任设备:隔空传送的实现
  2. 常见问题:分享失败、数据类型不支持等问题的解决方案

推荐资料

📚 官方文档


我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐