摘要:本文聚焦鸿蒙PC最基础的跨设备能力,通过完整可运行的代码示例,带你30分钟搭建首个跨设备应用。涵盖SoftBus设备认证、KVStore数据同步、系统级拖拽等核心功能,适合初次接触鸿蒙PC开发的开发者。


一、鸿蒙PC技术栈的三维协同模型

鸿蒙PC基于HDF统一驱动框架、软总线(SoftBus)分布式通信、端侧AI引擎构建垂直协同体系(图1)。其核心设计在于将硬件驱动标准化、分布式数据/设备管理能力与本地AI算力调度深度整合,开发者通过声明式配置即可实现跨设备功能。

驱动服务化
设备发现与认证
数据同步
状态通知
元数据
推理结果
设备列表
共享数据
硬件层 HDF
软总线 SoftBus
分布式设备管理
分布式数据管理
AI能力引擎
ArkUI应用层

图1 鸿蒙PC技术栈协同架构(API 12)

1.1 硬件抽象层的真实能力边界

鸿蒙通过HDF框架实现硬件服务化封装,开发者需理解其真实能力边界:

  • 本地硬件标准化:指纹模组、摄像头等通过HDF封装为HDI接口。开发者调用@ohos.multimedia.camera接口,无需关心底层驱动差异,一套代码可在同架构设备上运行(非跨设备远程调用硬件)。

👉 开发者案例:某考勤应用团队用@ohos.multimedia.camera实现人脸识别,PC端调用内置摄像头、平板端调用前置摄像头,无需修改核心代码,仅需调整UI布局适配屏幕。

  • 安全硬件通道:敏感操作依赖HUKS密钥管理系统与TEE环境联动。金融类开发者反馈,调用@ohos.security.huks实现支付验证时,系统原生提供硬件级加密,无需自行实现复杂安全逻辑。

二、跨设备文件协同的开发实践

以"PC-平板跨设备拖拽传输+数据同步"为例,解析实际开发流程(含可执行代码)。

2.1 前置配置:权限与分布式能力启用(必做步骤)

跨设备功能需同时配置权限与分布式开关,新手常因漏配调试受阻:

// module.json5 配置
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "跨设备文件数据同步",
        "usedScene": { "ability": ["MainAbility"], "when": "always" }
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DEVICE_IDENTIFIER",
        "reason": "获取在线设备列表",
        "usedScene": { "ability": ["MainAbility"], "when": "always" }
      }
    ],
    "abilities": [
      {
        "name": "MainAbility",
        "supportMultiDeviceDrag": true,  // 启用系统跨设备拖拽
        "distributedEnable": true        // 启用Ability分布式能力
      }
    ]
  }
}

2.2 设备互联:系统自动认证

鸿蒙软总线(SoftBus)已内置设备认证逻辑,开发者无需手动验证证书:

import { distributedDeviceManager } from '@ohos.distributedDeviceManager';
import { DeviceTypeId } from '@ohos.distributedDeviceManager';

let dmInstance: distributedDeviceManager.DeviceManager | undefined = undefined;

// 初始化设备管理器(需在Ability onCreate中调用)
async function initDeviceManager(bundleName: string) {
  try {
    dmInstance = distributedDeviceManager.createDeviceManager(bundleName);
    if (!dmInstance) throw new Error("设备管理器初始化失败");
  } catch (err) {
    console.error(`DeviceManager错误: ${(err as Error).message}`);
  }
}

// 获取在线可信平板设备
async function getTrustedTablet(): Promise<distributedDeviceManager.DeviceInfo | null> {
  if (!dmInstance) return null;
  try {
    const trustedDevices = await dmInstance.getTrustedDeviceList();
    return trustedDevices?.find(dev => dev.deviceTypeId === DeviceTypeId.TABLET) || null;
  } catch (err) {
    console.error(`获取设备列表失败: ${(err as Error).message}`);
    return null;
  }
}

👉 开发者踩坑:某团队曾尝试手动解析设备证书,导致连接不稳定;改用系统内置认证后,设备连接成功率从85%提升至99%。

2.3 跨设备拖拽与数据同步

2.3.1 拖拽发送端实现

跨设备拖拽由系统自动处理目标设备选择:

import { DragEvent, DragItemInfo } from '@ohos.ui.dragdrop';
import { util } from '@ohos.util';

@Component
export struct FileDragPage {
  @State fileList: Array<FileMeta> = [
    { id: "1", name: "report.docx", size: 2048, path: "/docs/report.docx", lastModifyTime: 1730000000000 }
  ];

  build() {
    List({ space: 10, layoutWeight: 1 }) {
      ForEach(this.fileList, (file: FileMeta) => {
        ListItem() {
          Text(file.name)
            .fontSize(16)
            .padding(12)
            .draggable(true)
            .onDragStart((event: DragEvent) => {
              const encoder = new util.TextEncoder();
              const dragData: DragItemInfo = {
                customInfo: encoder.encode(JSON.stringify(file)), // ✅ 明确返回Uint8Array
                mimeType: "application/json"
              };
              return dragData;
            })
            .onDragEnd((result) => {
              if (result.isSuccess) {
                console.log(`文件${file.name}拖拽成功`);
                this.fileList = this.fileList.filter(item => item.id !== file.id);
              }
            });
        }
      }, (file) => file.id);
    }
    .padding(20);
  }
}
2.3.2 KVStore数据同步
import { distributedData } from '@ohos.data.distributedData';

let kvManager: distributedData.KVManager | null = null;
let kvStore: distributedData.KVStore | null = null;

async function initKVStore(context: Context): Promise<void> {
  try {
    kvManager = distributedData.createKVManager({
      context,
      bundleName: "com.example.harmonypc.dragdemo"
    });
    kvStore = await kvManager.getKVStore("file_meta_store", {
      securityLevel: distributedData.SecurityLevel.S3,
      autoSync: true
    });
  } catch (err) {
    console.error(`KVStore初始化失败: ${(err as Error).message}`);
  }
}

async function syncFileMeta(file: FileMeta): Promise<boolean> {
  if (!kvStore) return false;
  try {
    const entry = await kvStore.get(file.id);
    const version = entry?.version || 0;
    await kvStore.put(file.id, JSON.stringify(file), version + 1);
    console.log(`文件${file.name}元数据同步成功`);
    return true;
  } catch (err) {
    console.error(`元数据同步失败: ${(err as Error).message}`);
    return false;
  }
}
2.3.3 拖拽接收端实现
@Component
export struct FileDropPage {
  @State receivedFiles: Array<FileMeta> = [];
  private decoder = new util.TextDecoder();

  build() {
    Column() {
      Text("拖拽文件到此区域")
        .width('90%')
        .height(200)
        .backgroundColor(Color.Grey)
        .borderRadius(8)
        .textAlign(TextAlign.Center)
        .padding(20)
        .onDrop((event: DragEvent) => {
          const dragData = event.getData();
          if (dragData?.mimeType === "application/json") {
            try {
              const fileMeta = JSON.parse(this.decoder.decode(dragData.customInfo)) as FileMeta;
              this.receivedFiles.push(fileMeta);
              console.log(`接收到文件: ${fileMeta.name}`);
              syncFileMeta(fileMeta);
            } catch (err) {
              console.error(`文件解析失败: ${(err as Error).message}`);
            }
          }
          return true;
        })
    }
  }
}

三、避坑指南:数据冲突与权限边界

坑1:分布式数据冲突

解决方案:KVStore版本控制实现乐观锁

async function updateFileMetaWithVersion(fileId: string, newMeta: FileMeta) {
  if (!kvStore) return false;
  try {
    const entry: distributedData.Entry | undefined = await kvStore.get(fileId);
    const currentVersion = entry?.version || 0;
    const currentMeta = entry ? 
      JSON.parse(new util.TextDecoder().decode(entry.value)) as FileMeta : null;

    if (currentMeta && currentMeta.lastModifyTime > newMeta.lastModifyTime) {
      console.warn("本地数据已过期,需合并后更新");
      newMeta = mergeFileMeta(currentMeta, newMeta);
    }

    await kvStore.put(fileId, JSON.stringify(newMeta), currentVersion + 1);
    return true;
  } catch (err) {
    console.error(`带版本更新失败: ${(err as Error).message}`);
    return false;
  }
}

坑2:权限边界控制

function checkFileAccessPermission(context: Context, filePath: string): boolean {
  const atManager = abilityAccessCtrl.createAtManager();
  const grantStatus = atManager.verifyAccessTokenSync("ohos.permission.READ_DOCUMENTS");
  if (grantStatus !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
    return false;
  }

  const allowedDir = `${context.filesDir}/public/`;
  if (!filePath.startsWith(allowedDir)) {
    console.warn(`禁止访问非授权目录: ${filePath}`);
    return false;
  }

  try {
    fileIo.accessSync(filePath);
    return true;
  } catch {
    return false;
  }
}

四、版本声明与调试工具链

// build-profile.json5 确认配置
{
  "app": {
    "compileSdkVersion": 12,
    "compatibleSdkVersion": 12,
    "buildMode": "debug"
  }
}

调试工具

# 监控KVStore同步
hdc shell bm dump <your-bundle-name> --kvstore

# 追踪拖拽事件
hdc shell hilog | grep "DragDrop"

—本篇完—

Logo

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

更多推荐