将 Unity 项目迁移到 HarmonyOS 后,登录、支付、统计等第三方 SDK 通常需要在 ArkTS 层接入,再通过桥接接口与团结引擎中的 C# 代码通信。本文将梳理 entry 与 tuanjieLib 的职责,介绍本地 HAR 包和中心仓依赖的接入方式,并给出 C# 与 ArkTS 双向调用的基本写法。

接入前先理解模块职责

DevEco Studio 工程与 Android Studio 工程在模块组织上有一些相似之处。在 HarmonyOS 的 Hvigor 构建体系中,每个模块都是独立的编译单元,entry 和 tuanjieLib 分别拥有自己的 oh-package.json5。

  • entry:应用入口模块,承载 Ability 生命周期,适合处理必须依赖应用上下文或生命周期回调的逻辑。
  • tuanjieLib:团结引擎运行模块,适合封装 SDK 能力、桥接接口以及与 C# 交互的代码。

如果把全部 SDK 逻辑都堆在 entry 中,TuanjiePlayerAbility 会很快变得臃肿。更清晰的做法是:在 tuanjieLib 中封装 SDK,在 entry 中仅保留生命周期调用和必要的上下文传递。

在 DevEco Studio 工程中接入 SDK

第三方 SDK 常见的接入方式有两种:引入本地 HAR 包,或者通过 OpenHarmony 三方库中心仓添加依赖。

方式一:引入本地 HAR 包

由于 SDK 需要在 TuanjiePlayerAbility 生命周期中直接调用,所以这一步直接在 entry 模块中引入 SDK。如果引入过程中需要额外封装,可以在 tuanjieLib 中新建 GameSdk 目录承载封装代码,再暴露给 entry 的 TuanjiePlayerAbility 引用。

1. 创建 SDK 代码目录

直接在 entry 中调用 SDK 时,把引入代码写在 entry/src/main/ets 下即可。需要封装时,再在 tuanjieLib/src/main/ets 下创建 GameSdk 目录,并新建 YourSDK.ets。建议把第三方 SDK 的初始化、登录和回调处理统一封装在这个类中,避免业务层直接依赖 SDK 的原始接口。

2. 添加 HAR 文件

将第三方 SDK 的 .har 文件放入对应模块的 libs 目录,例如:

tuanjieLib/libs/YourSDK-1.0.0.har

3. 声明模块依赖

在 tuanjieLib/oh-package.json5 的 dependencies 中添加本地 HAR 依赖:

{
"name": "tuanjieLib",
"version": "1.0.0",
"dependencies": {
"your-sdk-name": "file:./libs/YourSDK-1.0.0.har"
}
}

由于是在 tuanjieLib 中接入的, entry 需要通过 tuanjieLib 的导出接口间接调用。

然后在同一个模块的 build-profile.json5 的 buildOption.arkOptions.runtimeOnly.packages 中加入对应的包名:

"packages": [
"your-sdk-name"
]

这里的包名必须与 oh-package.json5 中 dependencies 的键保持一致。

4. 安装并同步依赖

在 DevEco Studio 中右键 tuanjieLib 模块,选择 Open in Terminal,然后执行:

ohpm install

依赖安装完成后,再执行一次项目同步。如果 IDE 仍然无法解析包,可检查 HAR 路径、依赖名称和模块终端所在目录是否正确。

5. 导出 SDK 桥接类

在 tuanjieLib/exported.ets 中导出封装类:

export { YourSDK } from './src/main/ets/GameSdk/YourSDK';

6. 在 Ability 生命周期中调用

在 entry/src/main/ets/ability/TuanjiePlayerAbility.ets 中引用 SDK,并在合适的生命周期方法中初始化:

import { YourSDK } from 'tuanjieLib';

export default class TuanjiePlayerAbility extends UIAbility {
onCreate(
want: Want,
launchParam: AbilityConstant.LaunchParam
): void {
// 调用封装后的 SDK 初始化方法
YourSDK.Init(this.context);
}
}

不同 SDK 对初始化时机和上下文类型的要求并不相同,应以 SDK 文档为准。不是要把所有初始化逻辑都放进 onCreate,以自己需求为准。

方式二:使用 OpenHarmony 三方库中心仓

如果 SDK 已发布到 OpenHarmony 三方库中心仓,可以直接在模块的 oh-package.json5 中声明版本依赖,使用方式类似于 Android Gradle 中的远程依赖:

{
"dependencies": {
"@ohos.thirdparty.your-sdk-name": "1.0.0"
}
}

修改后执行 ohpm install 并同步工程。对于正式项目,建议锁定经过验证的版本,避免构建环境自动获取到未经测试的新版本。

检查 SDK 的间接依赖

DevEco Studio 工程中的 HAR 依赖不一定会自动补齐 SDK 使用的全部间接依赖。如果构建时出现模块找不到、符号缺失等错误,应检查 SDK 文档或 HAR 包的依赖声明,并在当前模块的 oh-package.json5 中显式添加缺失的库。

团结引擎与 ArkTS 双向通信

SDK 接入完成后,通常还需要打通两条调用链路:ArkTS 通知 C#,以及 C# 主动调用 ArkTS。

ArkTS 调用 C#

ArkTS 可以通过消息机制调用场景中指定对象的方法:

import { Tuanjie } from 'classesLib';

Tuanjie.TuanjieSendMessage(
'GameObjectName',
'FunctionName',
parameter
);

三个参数分别表示:

  1. 场景中的 GameObject 名称;
  2. 挂载在该对象上的 C# 方法名;
  3. 传递给方法的字符串参数。

接收对象必须已经存在于当前场景中,对应方法名和参数形式也必须匹配。

C# 调用 ArkTS 静态方法

按照上一篇的桥接步骤,先确保 ArkTS 类已经在 tuanjieLib/exported.ets 中导出。

ArkTS 侧定义静态方法:

export class YourSDK {
public static FunctionName1(value: string) {
}
public static FunctionName2(value: string): number {
return 0;
}
}

C# 侧通过 OpenHarmonyJSClass 调用:

var harmonyClass = new OpenHarmonyJSClass("YourSDK");

// 无返回值
harmonyClass.CallStatic("FunctionName1", args);

// 指定返回值类型
int result = harmonyClass.CallStatic<int>("FunctionName2", args);

建议在初始化阶段创建并缓存 OpenHarmonyJSClass,不要在高频调用路径中重复实例化。一来可以节省资源,再者初始化后立即调用可能会失败。

C# 调用 ArkTS 实例方法

如果 ArkTS 类需要保存状态,可以先创建实例,再调用实例方法:

export class YourSDK {
private tag: string;

constructor(tag: string) {
this.tag = tag;
}

public log(message: string): void {
console.info(`[${this.tag}] ${message}`);
}
}

C# 侧调用示例:

var harmonyClass = new OpenHarmonyJSClass("YourSDK");
var instance = harmonyClass.CreateInstance("Game");
instance.Call("log", "hello from engine");

如果桥接接口涉及登录凭证、支付结果等敏感数据,不要将完整内容写入日志。跨语言调用失败时,也应返回明确的错误码或错误对象,便于定位是参数、生命周期还是 SDK 本身的问题。

延迟团结引擎启动流程

有些项目希望在隐私授权、SDK 初始化或闪屏播放完成后,再让游戏继续运行。但团结引擎的初始化与 TuanjiePlayerAbility 生命周期紧密绑定,随意移动初始化代码可能导致引擎生命周期异常。

一种相对简单的方案是:保持引擎原有初始化流程,在启动后立即暂停,前置流程结束后再恢复。

暂停引擎:

const tuanjiePlayer: TuanjiePlayer = TuanjiePlayer.getInstance();
tuanjiePlayer.onPause();

完成隐私授权或 SDK 初始化后恢复:

const tuanjiePlayer: TuanjiePlayer = TuanjiePlayer.getInstance();
tuanjiePlayer.onResume();

从 ArkTS 重启应用

热更新或资源修复完成后,有时需要重启应用。该逻辑可以在 ArkTS 侧通过 appRecovery 实现:

import { appRecovery } from '@kit.AbilityKit';

export class AppUtility {
public static RestartApplication(): void {
appRecovery.enableAppRecovery(
appRecovery.RestartFlag.ALWAYS_RESTART,
appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR,
appRecovery.SaveModeFlag.SAVE_WITH_FILE
);

appRecovery.restartApp();
}
}