
简介面向Unity开发者的华为SDK接入Demo工程专注解决在Unity项目中集成HMS SDK的常见问题适合需要接入华为账号、推送、游戏服务、排行榜等能力的移动应用开发者。压缩包共2000个文件整体约28.82MB文件类型覆盖bin数据、java与class源码、jar依赖库、dll原生插件、cs脚本、xml配置、png图标以及meta序列化文件等完整还原了Unity项目的原始目录结构可直接导入Unity Editor中查看和运行。资源内含完整的HuaweiSdkDemo工程详细展示了SDK导入、脚本后端切换至IL2CPP、初始化调用、账号登录、权限声明与打包测试等关键环节的代码实现并包含大量由Unity生成的资源缓存与编译中间文件便于对照排查集成过程中遇到的版本兼容和构建问题。无论是初学者还是已有Unity基础的开发者都可从中获得可运行的接入范例。已有1842人学习下载是快速上手Unity接入华为生态的实用参考。1. Unity 接入华为HMS SDKDemo 调通只是开始链路对齐才是关键说实话Unity 接华为 HMS SDK 最容易被“demo 包”三个字带偏。你下载一个官方示例改完包名、放好签名、点一下 Build确实能跑起来但把同一套思路搬进自己的工程第一个报错就能让你卡一下午——问题基本不在 C# 代码而在 AGC 后台配置、Unity 导出 Android 工程后的 Gradle 环境、以及 HMS SDK 与设备上 HMS Core 服务的版本匹配。这篇笔记记录一次真实的 HMS SDK 接入拆解从 AppGallery Connect 后台、Unity 导出、Gradle 依赖、Huawei ID 登录到最后把桥接模块做成 AAR 复用。读者最好有一年以上的 Unity 打包经验没接触过 Android 工程也不怕步骤按顺序抄即可。2. 华为HMS SDK接入准备先把 AGC 后台、签名和 Unity 工程三者对齐2.1 HMS Core 与 HMS SDK 的边界在开始配置之前先搞清楚一个概念。HMS Core 是华为手机系统层框架HMS SDK 是你上架包里的客户端。你的 Unity 游戏要调用华为登录、支付、推送实际上是 App 里的 SDK 和华为手机上的 HMS Core 在通信。C# 的命令不可能直接触达 HMS Core必须通过 Android 层 Java 桥转发所以接入的第一步不是写代码而是确定桥的载体。目前常见做法有两条路一是使用华为官方放出的 Unity 插件导入.unitypackage后用 C# 调二是自己写一个 Java 桥通过 AndroidJavaClass / AndroidJavaObject 在 C# 和 Java 之间传数据。我一般选第二种原因有三个HMS 官方插件更新节奏追不上 Unity 的版本更新部分 HarmonyOS 设备上插件对 Activity 生命周期管理不透明自建桥的代码可控性高出问题时直接断点打到 Java 层。这套思路下Unity 与华为侧的唯一接口就是你写的 libs 模块后续接游戏服务、支付都可以在同一个桥里扩展。2.2 AGC 后台应用创建与指纹配置AGCAppGallery Connect后台是所有华为能力的中控台。步骤固定照着做即可。进入华为开发者网站的 AppGallery Connect创建项目并添加应用。平台选 Android填写应用名称和包名。包名必须和 Unity Player Settings 里com.company.product拼出来的包名一致一个字符都不能差。包名要用全小写不要带下划线_华为侧对包名合法性校验严格。创建完成后进入“应用信息”找到“SHA-256 证书指纹”入口用 keytool 读取签名信息。生成指纹的命令keytool -list -v -keystore ./your.keystore -alias your_alias -storepass your_password输出里找到 SHA256 那一行复制到 AGC 后台。debug 和 release 如果用不同的 keystore需要把两个指纹都填进去我自己项目里填过 debug 漏填 release结果调试包能登录、线上包登录必失败后来逼着我把两个指纹都维护进 AGC 才消停。提示如果你团队多人开发每个人的debug.keystore不一样AGC 只认你填的那几个指纹谁想在自己机器上跑登录谁就要把自己的 debug 指纹加进去。2.3 下载 agconnect-services.json把文件放对位置AGC 应用详情页的“开发资源”里能下载到agconnect-services.json这是整个华为 SDK 的命脉包含 appid、client_id、api_key、client_secret 等信息登录、推送、支付服务全共用这一个文件。存放路径必须是UnityProject/Assets/Plugins/Android/agconnect-services.jsonUnity 打包时会把Assets/Plugins/Android目录下的内容合并进 APK所以 JSON 放这里才会被带进最终资源。常有人把它放在Assets/StreamingAssets那个目录只是原样拷贝HMS SDK 在启动时是按assets/根路径找agconnect-services.json的找不到就报初始化错这也是我在群里见过最多人翻车的位置。另一个注意点是这个 JSON 是跟着 AGC 应用走的。同一个工程换到另一个 AGC 应用要重新下载覆盖别在多个渠道包之间复制同一个文件否则 api_key 错配和额外流量问题会一起找上门。2.4 Unity Player Settings 在导出前就锁死导出 Android 工程前以下参数我会直接在 Unity 里设好包名与 AGC 后台严格一致。Minimum API Level设 22 或 23。HMS 最低要求 API 19但华为新机基本都是 Android 10 以上设低了没有意义且低版本系统对推送后台行为限制得更严。Target API Level按当前 Unity 版本推荐值填写华为应用市场对 targetSdk 有硬性要求低了上传直接被拒。Scripting BackendIL2CPP同时勾选 ARM64。HMS SDK 的 so 库只做 64 位纯 ARMv7 包连初始化都过不去。Build SystemGradle。这些参数导出后不好改一旦你后面是用 Android Studio 编译想在 Gradle 里临时把 targetSdk 改低测试又会撞上华为市场和 HMS 的版本校验所以最好在 Unity 侧就把它们定死。3. 从 Unity 导出到 Android 工程Gradle 改造是绕不开的主战场3.1 为什么要先导出 Android 工程而不是直接出包Unity 编辑器直接 Build 也能把这个桥打进去但做渠道接入时我建议至少第一个版本走导出流程原因很直接HMS SDK 集成过程完全发生在 Gradle 层直接出包你只能看到最终 APK看不到依赖冲突和 Manifest 合并过程出了问题日志也不好定位。Unity 的导出结果是一个完整 Gradle 工程用 Android Studio 打开后能看见launcher和unityLibrary两个模块。前者负责启动 Activity后者承载 Unity 运行时和你的桥接代码。HMS 相关改造主要在launcher/app和unityLibrary的 Gradle 文件里进行。这一个流程走通之后后续你可以回到 Unity 里直接 Build不会再被 Gradle 卡住但第一次导出调试收益远大于损失。我见过有团队图省事直接在编辑器里出包然后被 Manifest 合并错误绕得团团转最后还是回头走导出路线白白搭进去两天时间。3.2 Gradle 添加华为仓库与 HMS SDK 依赖Unity 2021 之后导出的工程settings.gradle里默认带google()和mavenCentral()还得加华为仓库。打开settings.gradle在pluginManagement.repositories和dependencyResolutionManagement.repositories都加上一行maven { url https://developer.huawei.com/repo/ }然后定位到launcher模块的build.gradle在 dependencies 块里添加华为账号 SDKdependencies { implementation fileTree(dir: libs, include: [*.jar]) implementation project(:unityLibrary) // 华为账号服务 SDK版本号以华为开发者网站最新推荐为准这里只是示例 implementation com.huawei.hms:hwid:6.11.0.301 }如果后面还要接推送、支付、游戏服务依赖按服务追加即可接入服务AGC 开通的服务名Gradle 依赖关键字华为账号登录华为账号服务hwid消息推送推送服务push应用内支付应用内支付服务iap排行榜/成就游戏服务games注意版本号不要照抄登录 AGC 后能看到当前推荐的 SDK 版本以那个为准。华为有时候会下线旧版本老版本号在华为 repo 里会 404同步失败时先去查版本。依赖优先级上还有一条规矩HMS 相关全部用implementation不要把 jar 手动丢进libs目录和依赖混用。两种来源的版本会被 Gradle 区别对待常常出现 jar 里的旧类覆盖依赖里的新类这种玄学问题这也是我后来去项目里救过的现场之一。3.3 自定义 MainActivity把 HMS 生命周期接进 UnityUnity 默认的 Activity 是com.unity3d.player.UnityPlayerActivityHMS 的登录结果是通过onActivityResult回传的所以必须在导出工程里注册一个继承它的 MainActivity然后把 HMS 桥接对象绑定到生命周期上。先新建src/main/java/com/example/hmsbridge/MainActivity.javapackage com.example.hmsbridge; import android.content.Intent; import android.os.Bundle; import com.unity3d.player.UnityPlayerActivity; public class MainActivity extends UnityPlayerActivity { private HMSLoginBridge hmsBridge; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); hmsBridge new HMSLoginBridge(this); } Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (hmsBridge ! null) { hmsBridge.handleActivityResult(requestCode, resultCode, data); } } }这段代码的要点是onCreate里初始化桥onActivityResult统一转发给桥处理。如果没有这一步Unity 场景里再怎么调 C#登录结果也回不来。然后检查AndroidManifest.xml把 application 标签里指向UnityPlayerActivity的入口改成com.example.hmsbridge.MainActivity。如果你用的是导出工程这个文件通常在launcher/src/main/AndroidManifest.xml。3.4 AndroidManifest 合并别冲突Unity 工程本身也会生成一个清单路径在Assets/Plugins/Android/AndroidManifest.xml。两个清单在构建时做 manifest merge公共属性必须一致。最常见的冲突是 SDK 要求android:exportedtrue而 Unity 导出工程默认给了false合并时直接报错中断构建。排查手法是看构建输出里的merger_report.txtAndroid Studio 每个模块的 build 目录下都有。看到launcher或unityLibrary里的某个 activity 溢出或权限声明不一致优先去Assets/Plugins/Android/AndroidManifest.xml里补上同样的声明。另外只要改过 Manifest就要重新执行一次 Gradle Sync。有人改了文件不 Sync 直接 Build下一次构建还在用旧配置耗时半天找不到原因这种低级问题在渠道接入阶段非常常见。4. 开发华为账号登录 DemoC# 调 Java 再回 C# 的完整链路4.1 AGC 后台开通华为账号服务在 AGC 项目里找到应用进入“构建”区域添加服务选择“华为账号服务”按引导完成开通。开通过程会要求设置应用的发布状态或测试范围调试期选“测试”即可。这一步做完后agconnect-services.json里才会带上账号服务相关的配置参数如果之前已经下载过 JSON开通后需要重新下载覆盖。4.2 Java 桥接类登录请求与结果回传Java 侧核心类是 HMSLoginBridge职责只有三个发起登录、接收结果、把结果转成字符串回传 Unity。写一个可直接抄的版本package com.example.hmsbridge; import android.app.Activity; import android.content.Intent; import com.huawei.hms.support.api.hwid.AuthHuaweiId; import com.huawei.hms.support.api.hwid.HuaweiIdAuthManager; import com.huawei.hms.support.api.hwid.HuaweiIdAuthParams; import com.huawei.hms.support.api.hwid.HuaweiIdAuthParamsHelper; import com.huawei.hms.support.api.hwid.HuaweiIdAuthService; import com.unity3d.player.UnityPlayer; public class HMSLoginBridge { private static final int REQ_SIGN_IN 10001; private Activity activity; public HMSLoginBridge(Activity activity) { this.activity activity; } public void login() { // 构造登录参数请求 id_token 和用户基本信息 HuaweiIdAuthParams params new HuaweiIdAuthParamsHelper( HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM) .setIdToken() .setProfile() .createParams(); HuaweiIdAuthService service HuaweiIdAuthManager.getService(activity, params); // signIn 会拉起华为账号登录页结果通过 onActivityResult 回传 service.signIn(activity); } public void handleActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode ! REQ_SIGN_IN) { return; } if (resultCode ! Activity.RESULT_OK) { UnityPlayer.UnitySendMessage(HuaweiLoginManager, OnLoginResult, {\code\:\-1\,\message\:\user cancel\}); return; } AuthHuaweiId account AuthHuaweiId.parseAuthResultFromIntent(data); if (account null) { UnityPlayer.UnitySendMessage(HuaweiLoginManager, OnLoginResult, {\code\:\-2\,\message\:\parse account empty\}); return; } String openId account.getOpenId(); String name account.getDisplayName() null ? : account.getDisplayName(); String avatar account.getAvatarUriString() null ? : account.getAvatarUriString(); // 注意不要直接拼接 JSONdisplayName 里如果带引号会导致 Unity 侧解析失败 String json {\code\:\0\,\openId\:\ openId \,\displayName\:\ name \,\avatar\:\ avatar \}; UnityPlayer.UnitySendMessage(HuaweiLoginManager, OnLoginResult, json); } }这段代码几个重点拆开讲HuaweiIdAuthParamsHelper里DEFAULT_AUTH_REQUEST_PARAM是华为预置的参数集包含 openid 和基本资料授权。只做登录可以不加额外 scope。signIn(activity)是拉起登录页的唯一入口传进去的 Activity 必须和最终接收回调的 Activity 一致否则回调会丢这也是最容易忽略的一环。UnitySendMessage的三个参数分别是 GameObject 名、脚本方法名、字符串参数。Unity 场景里必须存在名为HuaweiLoginManager的游戏对象且对象上有接收OnLoginResult的脚本。4.3 Unity C# 侧AndroidJavaObject 桥接C# 侧写一个单例挂到场景里using UnityEngine; public class HuaweiLoginManager : MonoBehaviour { private AndroidJavaObject bridge; private void Awake() { // 拿到 Unity 当前 Activity传给 Java 桥 using (AndroidJavaClass unityPlayer new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { AndroidJavaObject activity unityPlayer.GetStaticAndroidJavaObject(currentActivity); bridge new AndroidJavaObject(com.example.hmsbridge.HMSLoginBridge, activity); } } public void StartLogin() { if (bridge ! null) { bridge.Call(login); } } // Java 侧通过 UnitySendMessage 调用 public void OnLoginResult(string json) { Debug.Log([HMS] json); // 这里再交给业务层处理 } }AndroidJavaObject有两个重载容易搞混new AndroidJavaObject(类名, 参数)是构造实例AndroidJavaClass(类名)是引用静态类。登录桥需要持有 Activity 实例所以必须用前者把 Activity 传进去。回调链路整理如下Unity 场景按钮触发StartLogin()C# 调 Javabridge.Call(login)Java 拉起华为账号登录页用户确认后 HMS SDK 把结果塞进onActivityResultMainActivity 把结果转发给HMSLoginBridge.handleActivityResultJava 拼 JSON 字符串用UnitySendMessage回调 C#UnityOnLoginResult拿到 JSON如果链路任何一步断掉现象都是“登录页闪一下然后没反应”排查顺序就按这个链条从后往前查。4.4 登录结果解析与取消场景处理华为登录有几种非成功结果用户主动取消、页面被系统回收后返回空数据、授权 scope 被拒。以上三种在 Java 侧都要有明确分支。建议把返回码统一设计code含义客户端动作0登录成功携带 openId 等数据进游戏-1用户取消不提示或者友好提示-2服务器返回空账户提示重试-3华为侧配置错误检查 AGC 指纹与签名C# 侧拿到 JSON 后先用JsonUtility.FromJsonT()解析成结构体。displayName是用户可控字段理论上可能出现引号我在生产环境里会给 Java 侧做一次 JSON 转义再返回不要在 C# 端赌它安全。5. 接入 HMS SDK 避坑清单五个真金白银换来的坑5.1 错误码 907135000签名校验不通过现象点击登录后华为登录页弹出“系统繁忙”或直接无响应Logcat 出现907135000。原因这是 HMS 签名校验失败的典型错误。客户端实际签名指纹和 AGC 后台配置的指纹不一致。常见于 debug 包用自动生成的 debug.keystorerelease 包用正式签名后台只填了其中一个。解决把 debug 和 release 两组 keystore 的 SHA-256 指纹都填进 AGC。多人协作时每人本机 debug 指纹不同需要在后台一并登记否则每个人第一次跑登录都要踩一遍这个错误。5.2 自定义 Activity 没注册登录完成后黑屏现象华为登录页正常弹出输入账号密码后返回Unity 画面直接黑掉或卡在加载。原因自己写了 MainActivity 但忘在 AndroidManifest 里注册或者注册了但入口 Activity 还是 UnityPlayerActivity两者指向不一致。解决打开AndroidManifest.xml的application标签确认入口 activity 指向com.example.hmsbridge.MainActivity并且已添加android:exportedtrue。在导出工程里改完 Manifest 后要重新执行 Gradle Sync只改文件不 Sync 等于白改。5.3 混淆配置缺失Release 包回调消失现象Debug 包登录一切正常Release 包点登录没反应Logcat 提示ClassNotFoundException或NoSuchFieldError。原因ProGuard 把 HMS SDK 的类名混淆掉HuaweiIdAuthManager找不到对应实现。解决在proguard-rules.pro里加-keep class com.huawei.hms.** { *; } -keep interface com.huawei.hms.** { *; } -dontwarn com.huawei.hms.**保存后重新构建 Release 包验证。这条规则建议直接写进工程根目录的混淆文件而不是某个模块否则 unityLibrary 的混淆配置不会被命中。5.4 UnitySendMessage 目标不存在回调被静默丢弃现象登录成功华为侧已经拿到 token但 Unity 场景里的业务代码没有执行Logcat 没有任何错误。原因Java 侧UnitySendMessage按名字找 GameObject场景里没有叫HuaweiLoginManager的对象或者对象在场景切换时被销毁回调自然没人接。解决让接收回调的脚本挂在常驻节点上并在Awake里调用DontDestroyOnLoad(gameObject)。Java 侧的 GameObject 名和 C# 方法名一旦定了就不要随意在场景里改名改了就是静默丢回调。5.5 HMS SDK 版本漂移Gradle 同步失败或类找不到现象从老工程复制依赖Gradle 同步报 404或者运行时提示某个类不存在。原因华为 repo 会下架旧 SDK 版本直接写死旧版本号拉不到另一种情况是同一个工程里同时从libs目录引了老 jar 又在 Gradle 里引了新版两套类并存互相覆盖。解决依赖统一走 Gradle版本号到 AGC“开发指南”页面查最新推荐值再填。libs目录里看到*.jar和 HMS 相关的文件能删就删别让构建系统同时看到两个来源。6. 进阶把 HMS 桥接模块打成 AAR让下一个项目不再重新造轮子第一次接入做的只是个 demo真正值得沉淀的是把 HMSLoginBridge 连同 MainActivity 一起打成一个 AAR放到Assets/Plugins/Android/下这样新项目不需要再导出 Android 工程Unity 直接引用就能跑登录。AAR 的结构是HmsBridge.aar ├── classes.jar ├── AndroidManifest.xml └── res/打包方式不复杂在 Android Studio 里新建一个 Library Module把 HMSLoginBridge、MainActivity、相关资源全部放进去Gradle 依赖里把 HMS SDK 声明成implementation对 UnityPlayer 相关类用compileOnly files(libs/unityLibrary.jar)这个 jar 从 Unity 导出的unityLibrary模块里拿。打成 AAR 后复制到 Unity 工程的Assets/Plugins/Android再在Assets/Plugins/Android/AndroidManifest.xml里留好 MainActivity 的注册Unity 构建时会自动把这个 AAR 合并进去。这样做的最大收益是新项目从 AGC 下载新配置文件在 Unity 里把包名和场景脚本一换登录功能零成本迁移而且 Java 层调试点到哪个类、改到哪个方法逻辑完全可控不再依赖华为官方插件的黑匣子。验证 AAR 是否生效有一套固定流程先在 Unity 里跑出 debug 安装包观察 Logcat 里是否有HMS开头的初始化日志然后用adb shell dumpsys package确认包名签名和 AGC 后台一致最后在场景里点登录按钮确认能拉起华为账号页并且返回后再发一次取消两条路径都通才算守住底。我自己的习惯是每接一个渠道 SDK第一件事不是写业务代码而是先跑一个空工程把 AGC 配置、签名、SDK 依赖、回调链路全部打通再做业务逻辑。那次因为没验证 AAR 版本导致上线前连续翻车后这个顺序我再也没改过。希望这份笔记能帮你在华为 HMS 接入的路上少踩几个坑把宝贵时间留给真正的游戏开发。本文还有配套的精品资源点击获取