8.AndroidSDK接入总结

  1. 8.总结
    1. 8.1 核心要点速览
      1. SDK 是什么
      2. 为什么要接入 SDK
      3. 学习接入时的三条主线
      4. 在项目周期里的位置
      5. 交互工程在整条链路里的位置
      6. Android Studio 工程初始化
      7. 从「可运行 App」改成「给 Unity 用的库」
      8. classes.jar、UnityPlayerActivity、入口 Activity
      9. AndroidManifest 与产出 aar
      10. 第三方 SDK 接入的通用套路
      11. 获取 SDK 与开发者账号(百度定位示例)
      12. SHA1 指纹与 AK
      13. 解压、放入 libs 与文档驱动配置
      14. 百度定位:Android 侧初始化与回调
      15. Unity 侧:Java 调用与字符串回传
      16. aar 回灌与出包策略
    2. 8.2 面试题精选
      1. 基础题
        1. 1. 什么是 SDK?它和「调几个 HTTP 接口」有什么本质区别?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 接入第三方 SDK 前,你会做哪些工程向准备?(排期与验证)
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. AndroidJavaClass / AndroidJavaObject 与 currentActivity 是什么关系?(JNI 封装层)
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. UnitySendMessage 的限制有哪些?收不到回调时你怎么查?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      2. 进阶题
        1. 1. 只有原生 Android SDK、没有 Unity 插件时,一般有哪几种集成路径?各适合什么场景?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 把 Application 模块改成给 Unity 用的 Android Library,Gradle 与入口类通常要动哪些点?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        3. 3. 地图 / 定位开放平台为什么要登记包名和 SHA1?填错会怎样?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        4. 4. Release 开启 R8/混淆后,Call 调不到 Java 或回调异常,优先怀疑什么?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
      3. 深度题
        1. 1. Debug 定位正常,Release 鉴权失败;已确认 SHA1 无误时,还可能是什么?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章
        2. 2. 多个第三方 aar/jar 叠在一起时,Unity Build 与 Android Studio 各自擅长解决什么问题?
          1. 题目
          2. 深入解析
          3. 答题示例
          4. 参考文章

8.总结


8.1 核心要点速览

SDK 是什么

  • 全称:Software Development Kit,常称「软件开发工具包」:面向某一平台或框架,把库、工具、文档打在一起,用来在该平台上做应用开发。
  • 和游戏开发的关系:你不会自己去实现微信登录协议栈或地图引擎;厂商把能力封进 SDK,你按文档接 初始化、权限、回调,业务侧只关心「什么时候调、数据从哪来」。

为什么要接入 SDK

  • 登录、支付、统计、渠道与平台能力等,多数由第三方提供;客户端要启用这些能力,就要接入对应 SDK。
  • 典型场景:渠道要求 QQ / 微信登录——包内必须带对方提供的登录能力,用 SDK 接入比自研对接成本低几个数量级。

学习接入时的三条主线

主线 要搞清的事 落地时
Unity ↔ Android 互调 C# 怎么拿到 Activity、Java 怎么 UnitySendMessage 多数流程是:原生里初始化 SDK,Unity 只调封装好的 public 方法
读文档 API 顺序、Manifest、Gradle、混淆规则 当前版本 官方文档为准,旧博客只能当线索
打包验证 依赖是否进最终 APK 集成第三方库后,用 真机 + 与线上一致的签名 跑一遍

在项目周期里的位置

  • 一般放在版本中后期:包名、签名、渠道参数相对稳定后再接,少返工。前期若频繁改包名,地图、支付类控制台里的 包名 + SHA1 也要跟着改。

交互工程在整条链路里的位置

  • 只在 Android 工程里初始化原生 SDK、再封装给 Unity 时,才需要单独的 Android 交互工程:里面引 jar/aar、写 MainActivity 桥接,最后 Make Module 出 aar 给 Unity。
  • 本系列示例:百度定位用 jar,Java 侧建 LocationClient、拼地址字符串;Unity 侧只 Call("GetCurrentPosition") 并接收字符串——交互工程把「百度那套 API」挡在 Android 层。
  • Unity 先切 AndroidApplication IdMinimum API Level 与 Android Studio 工程对齐,否则清单合并、签名、控制台登记会对不上。

Android Studio 工程初始化

  • 新建 Empty Activity,设备类型选 Phone and Tablet
  • 包名Minimum SDK 必须与 Unity Player Settings 中一致;若本机没有对应 API 级别,在 Android Studio 的 SDK 管理里补装。
  • 工程首次同步完成后,按教程清理:删除两个 Test 相关工程,以及 res 下暂时用不到的资源,减少干扰。

从「可运行 App」改成「给 Unity 用的库」

环节 操作 说明
Gradle 插件类型 com.android.application 改为 com.android.library 模块以 形式参与打包,而不是独立应用
应用 ID 删除 defaultConfig 里的 applicationId library 模块不写 applicationId,由最终 Unity 出包统一决定包名
同步工程 点击 Sync Now 让依赖与模块类型生效

classes.jar、UnityPlayerActivity、入口 Activity

  • classes.jar:从 Unity 安装目录 Data\PlaybackEngines\AndroidPlayer\Variations\monoil2cpp 下的 Release\Classes 拷贝到 app\libs,再 Add As Library。mono 与 il2cpp 两条路径对应不同脚本后端,与当前 Unity 工程设置一致即可。
  • UnityPlayerActivity 源码:从 Data\PlaybackEngines\AndroidPlayer\Source\ 下拷贝到 app\src\main\java,与 Unity 提供的活动基类对齐。
  • MainActivity:改为继承 UnityPlayerActivity;在 onCreate 里注释掉 setContentView,避免用原生布局盖住 Unity 的渲染视图。

AndroidManifest 与产出 aar

  • 清理 application 节点里与 Unity 无关的多余声明,避免清单合并冲突。
  • 在作为 Unity 入口的 activity 内增加:meta-dataunityplayer.UnityActivity,值 true,标明该 Activity 由 Unity 驱动。
  • 使用 Build → Make Module 生成 aar。若首次构建提示正在下载 Gradle 或依赖,等下载完成后再试,一般即可成功。

第三方 SDK 接入的通用套路

  • 文档从 合作方包体官网 拿;按文档配 Gradle / 权限 / Manifest / 初始化顺序
  • 报错时先看 Gradle 同步Logcat / 构建日志,再对照文档缺啥补啥。
  • 要不要交互工程:官方出 Unity 包(.unitypackage 等)时,往往直接在 Editor 里接;只有 Android / iOS 原生 SDK 时,才像本系列这样在 AS / Xcode 里包一层再给 Unity。支付宝、微信、百度地图等常见能力两条路径都有,以文档为准。

获取 SDK 与开发者账号(百度定位示例)

  • 开放平台进入 Android 定位 SDK 下载页,按功能选包;需要轻量接入时可下 jar
  • 注册开发者账号(个人 / 企业按平台要求选),完成邮箱、实名等验证后才能创建应用、拿密钥。

SHA1 指纹与 AK

  • 控制台要把 包名 + 签名指纹 绑在一起,有点像服务端 IP 白名单:只有「这个包名、且用这个证书签出来的包」才能用你的 AK。指纹常用 SHA1,以平台当前要求为准。
  • 页面取指纹失败时,用 keytool;可执行文件在 Android Studio 目录的 **jbr\bin**(新版)或 **jre\bin**(旧版)。
  • 提交 SHA1 后拿到 AK,再写进 Manifest 或初始化代码(百度各版本写法看文档)。

解压、放入 libs 与文档驱动配置

步骤 内容
解压与拷贝 解压下载包,将 jar 等放入 app/libs
依赖 按官方文档在 build.gradleimplementation fileTreefiles 或远程仓库坐标,以当前文档为准
AK AndroidManifest 或文档指定位置填入 AK
权限 按文档补充 定位等权限 与合并规则

具体改法以 当前版官方接入文档 为准:jar 拷进 libs 后若没配 implementation,构建阶段仍可能找不到类。

百度定位:Android 侧初始化与回调

  • 隐私LocationClient.setAgreePrivacy(true) 必须在 new LocationClient(...) 之前;否则按文档逻辑定位直接不工作。
  • 监听MyLocationListener 继承 BDAbstractLocationListener,在 onReceiveLocation(BDLocation) 里取经纬度、精度、地址等;别在回调里做耗时阻塞。
  • 入口方法MainActivity 里写 GetCurrentPosition()new LocationClientregisterLocationListener → 配 LocationClientOptionstart();官方示例用 try-catch 包住初始化,异常时能在 log 里看到栈,而不是只闪退。
  • 回传UnityPlayer.UnitySendMessage("Lesson6", "GetCurrentPosition", message) 里,Lesson6 是场景里 GameObject 的名字(不是脚本类名);GetCurrentPosition 对应 C# 里 public void GetCurrentPosition(string info)。改名字时三处一起改:Hierarchy 名、Java 字符串、脚本所在物体

Unity 侧:Java 调用与字符串回传

方向 写法 易错点
C# → Java AndroidJavaClass("com.unity3d.player.UnityPlayer")GetStatic<AndroidJavaObject>("currentActivity")Call("GetCurrentPosition") Call 的方法名、参数类型与 Java public 方法一致;混淆要 keep
Java → C# UnityPlayer.UnitySendMessage(物体名, 方法名, 字符串) 物体名与 Hierarchy 完全一致(大小写敏感);方法必须是带 一个 string 的 public 实例方法
UI 示例里 info.Contains("null") 时显示「定位中」,否则显示整段文本 字符串协议是业务约定,和百度返回字段强相关

aar 回灌与出包策略

  • aar 放到 Unity 的 Assets/Plugins/Android(或你项目里统一放 Android 插件的目录),再在 Unity 里打 Android 包。
  • Unity 自带 Gradle 也能出 APK,但 多个 aar/jar 叠在一起 时,传递依赖、重复类、Manifest 合并问题在 Android Studio 里看依赖树、跑 assemble 更直观。所以:日常迭代可以 Unity 一键出包发版前用 AS 收一遍依赖更稳,属于工程上的保险,不是否定 Unity Build。

8.2 面试题精选

基础题

1. 什么是 SDK?它和「调几个 HTTP 接口」有什么本质区别?

题目

说明 SDK 交付物一般包含什么;游戏项目里哪些能力更适合通过 SDK 接入而不是自研或纯接口对接?

深入解析
  • SDK 通常包含 原生库 / jar、aar、资源、Manifest 片段、混淆 consumer 规则 等,是「可链接进工程」的一整套交付,而不是只有 REST 文档。
  • 纯接口适合无客户端证书、无复杂原生能力的场景;登录、支付、地图定位、推送 等往往涉及 签名、密钥、系统权限、前后台保活,厂商用 SDK 把复杂度收进库里。
  • 自研部分侧重 玩法、战斗、资源管线;第三方能力侧重 合规、风控、渠道对接成本
答题示例

SDK 是一整套库和配置,而不只是几个 URL。接进来要在工程里加依赖、改清单、按生命周期初始化,有时还要过应用商店和隐私合规。

支付、渠道登录、地图这类,平台要求用他们的客户端能力和密钥体系,自研对接成本和审核风险都高,一般用官方 SDK。我们写玩法和表现,不把支付协议从零实现一遍。

参考文章
  • 1.SDK是什么

2. 接入第三方 SDK 前,你会做哪些工程向准备?(排期与验证)

题目

结合 Unity + Android,说明文档、构建、签名与联调上至少要覆盖什么。

深入解析
  • 互调与生命周期:弄清 SDK 在哪个线程回调、是否必须在 Activity 内初始化(本系列在 MainActivity 封装百度定位)。
  • 文档版本:锁定 SDK 版本号、最低 Android 版本、Gradle 插件 要求,避免「教程是旧的、工程是新的」。
  • 构建验证:用 与线上一致的 keystore 打一次包;必要时 Export Gradle Project 到 Android Studio 看 依赖树 和 Manifest 合并结果,只在 Editor 里 Play 测不到这些。
  • 控制台:地图类提前准备 包名 + SHA1 占位,避免临上线才登记。
答题示例

先读 release note 和混淆说明,确认 minSdk 和 Gradle 要求。排期里留联调时间,因为权限和签名一错就是整包失败。

集成后在真机上用发布签名打 APK,看初始化是否成功。复杂依赖可以导出 Gradle 在 AS 里看一眼依赖树,比在 Unity 控制台里猜传递依赖快。

参考文章
  • 1.SDK是什么

3. AndroidJavaClass / AndroidJavaObjectcurrentActivity 是什么关系?(JNI 封装层)

题目

说明从 C# 调用 MainActivity 上实例方法的典型代码路径;UnityPlayer.currentActivity 指向谁?

深入解析
  • Unity 在 Android 上通过 JNI 调 Java;AndroidJavaClassAndroidJavaObject 属于 高级封装,避免手写 AndroidJNI
  • com.unity3d.player.UnityPlayer 的静态字段 currentActivity 是当前承载游戏的 Activity,本系列里即继承 UnityPlayerActivity 的 **MainActivity**。
  • GetStatic<AndroidJavaObject>("currentActivity") 拿到该实例后,**Call("GetCurrentPosition")** 调的是 Java 侧 public 方法;方法名、参数类型需与 ProGuard 保留规则 一致,否则 Release 会找不到符号。
答题示例

AndroidJavaClass 用来拿 Java 类,GetStaticUnityPlayer 上的 currentActivity,类型是 AndroidJavaObject,对应正在跑游戏的那个 Activity。

对它 Call 就是在调 Java 实例方法。我们项目里 MainActivity 继承 UnityPlayerActivity,上面挂了 GetCurrentPosition,所以从 C# 能直接 Call 过去。

参考文章
  • 6.Unity调用对应百度定位API

4. UnitySendMessage 的限制有哪些?收不到回调时你怎么查?

题目

说明三个参数含义;除 GameObject 名写错外,还有哪些常见坑?

深入解析
  • 签名:UnityPlayer.UnitySendMessage(gameObjectName, methodName, message)payload 只能是 string无返回值,适合把定位结果拼成一段文本回传(本系列做法)。
  • gameObjectName 必须与 Hierarchy 名称完全一致(大小写敏感);不是脚本类名。
  • methodName 对应 public恰好一个 string 参数 的实例方法;多脚本挂在同一物体上时,需保证 方法名不歧义(Unity 按消息派发规则查找)。
  • 进阶追问:高频回调或要强类型接口时,团队会评估 AndroidJavaProxy 等方案;本系列正文采用 UnitySendMessage,实现成本最低。
答题示例

三个参数是:场景里物体名、方法名、字符串参数。接收方法要写 public void xxx(string s)

收不到先看 Hierarchy 名字和 Java 里字符串是不是逐字一致,再看方法是不是 public、参数是不是只有一个 string。物体被禁用或场景没加载时也会调不到。

参考文章
  • 6.Unity调用对应百度定位API

进阶题

1. 只有原生 Android SDK、没有 Unity 插件时,一般有哪几种集成路径?各适合什么场景?

题目

对比「Plugins/Android 直放 aar」「Unity 导出 Gradle 再在 AS 里集成」「先建 Android Library 出 aar 再给 Unity」。

深入解析
  • 官方提供 Unity 包:优先 Plugins/Android 或 Package 方式接入,迭代快。
  • 只有原生文档:常见两条路——导出 Gradle,在 AS 里按原生文档改 build.gradle 和 Manifest;或像本系列一样 先建 library 模块,把 SDK 和桥接代码封进 aar,Unity 只引用 aar,业务边界清晰
  • 选型看 谁维护原生工程、是否要 多项目复用同一套 aar、CI 是否要求 可脚本化的 AS 构建
答题示例

有 Unity 插件就按官方放 Plugins 里。只有 jar 文档时,要么导出工程在 AS 里硬集成,要么单独建 Android 工程打成 aar,Unity 当插件引用。

我们这条线是先 AS 里接百度 SDK 和桥接,再 Make Module 出 aar,Unity 只调封装好的方法,原生细节不污染 C#。

参考文章
  • 3.了解SDK接入套路

2. 把 Application 模块改成给 Unity 用的 Android Library,Gradle 与入口类通常要动哪些点?

题目

说明 com.android.applicationapplicationId 的处理;classes.jarUnityPlayerActivitymeta-data 各自解决什么问题。

深入解析
  • **com.android.library + 去掉 applicationId**:库模块由最终 Unity 出包 统一决定 applicationId,避免与宿主 App 模型冲突。
  • **classes.jar**:让 Java 侧能引用 Unity 引擎侧 API(如 UnityPlayer);放入 libs 并参与 implementation
  • **继承 UnityPlayerActivity**:生命周期与 GL 视图 由 Unity 接管;注释 **setContentView**,避免原生布局盖住游戏画面。
  • Manifestunityplayer.UnityActivitymeta-data 声明该 Activity 由 Unity 驱动,合并进最终 APK 时主工程能识别。
答题示例

application 改成 library,删掉 applicationId,同步 Gradle。classes.jar 加进依赖,MainActivity 继承 UnityPlayerActivity,onCreate 不要 setContentView。

清单里给主 Activity 加上 Unity 的 meta-data。最后 Make Module 打出 aar。

参考文章
  • 2.交互项目创建

3. 地图 / 定位开放平台为什么要登记包名和 SHA1?填错会怎样?

题目

从「密钥与盗用风险」角度说明平台侧逻辑;同一包名 Debug 与 Release 为何可能都要配。

深入解析
  • AK 与客户端绑定:包名 限制进程命名空间,SHA1 限制「谁签的名」;二者一起降低 密钥被其他应用盗用 的风险。
  • Debug / Release 使用 不同 keystoreSHA1 不同;控制台只配 Debug 时,上架包会 鉴权失败
  • 现象多为 错误码、初始化失败、有权限仍无定位;用 keytool -list -v实际安装包所用证书 核对。
答题示例

平台要把 AK 和你的应用身份绑死:包名对上,还要证明这个包是你用指定证书签的,所以登记 SHA1。

Debug 和 Release 证书不一样就要各配一套指纹,否则线上包过不了校验。

参考文章
  • 4.获取SDK完成准备工作

4. Release 开启 R8/混淆后,Call 调不到 Java 或回调异常,优先怀疑什么?

题目

说明 JNI 反射与混淆的关系;MainActivity 上给 Unity 调的方法、第三方 SDK 包名在 proguard-rules 里通常怎么处理?

深入解析
  • R8 会裁剪并重命名未保留的 public API;C# 侧用 字符串Call("方法名") 时,若 Java 方法被改名或类被删掉,运行期会 NoSuchMethodError 或静默失败。
  • 工程上需 -keep 住桥接类:如 MainActivity 及供 Unity 调用的 public 方法;第三方 SDK 按 官方文档 追加 consumer rules 或手动 **-keep class com.thirdparty.** { *; }**(以文档为准)。
  • UnitySendMessage 同理:接收方法若被 混淆成短名,字符串对不上也会收不到。
答题示例

混淆会把方法名改掉,而 Unity 这边写的是字符串方法名,对不上就调不到。要在 proguard 里 keep 住给 Unity 调的那几个 public 方法,第三方库按厂商给的规则加。

出问题先看 mapping.txt 里方法有没有被改掉,再对照 Call 里的字符串。

参考文章
  • 2.交互项目创建
  • 6.Unity调用对应百度定位API

深度题

1. Debug 定位正常,Release 鉴权失败;已确认 SHA1 无误时,还可能是什么?

题目

签名、控制台、混淆 三条线上扩展排查;本系列桥接代码要注意什么?

深入解析
  • 签名线:仍用 keytool 核对 实际安装包 证书,排除 多渠道重签名Google Play App Signing 与本地证书不一致。
  • 控制台线包名大小写、是否登记了 多个指纹、是否限制了 包名后缀
  • 混淆线AK 是否在 Manifest / meta-datamanifestPlaceholdersbuildType 覆盖错误;**LocationClient 初始化** 是否被 R8 剔除(按百度文档 keep)。
  • 桥接线:**setAgreePrivacy** 是否在 LocationClient 构造之前;Release 若 日志关闭,需用 Logcat + 非脱敏日志 区分「鉴权失败」与「隐私未同意」。
答题示例

SHA1 对齐仍失败,我会再看控制台包名是否完全一致,以及是不是上架包走了另一套签名。

再查混淆:桥接 Activity 和 SDK 包名有没有按文档 keep。百度这边隐私接口顺序错了 Release 上也会直接不定位,和 SHA1 无关,要对照官方初始化顺序。

参考文章
  • 4.获取SDK完成准备工作
  • 5.配置修改和权限修改
  • 6.Unity调用对应百度定位API

2. 多个第三方 aar/jar 叠在一起时,Unity Build 与 Android Studio 各自擅长解决什么问题?

题目

追问 Duplicate class、传递依赖、Manifest merger 冲突时,你在哪一侧排查?与「插件已放进 Unity」是否矛盾?

深入解析
  • Unity 导出 Gradle 时会把 Plugins/Android 下插件 合并进模板;多厂商 SDK 常见 同一传递依赖不同版本support 与 AndroidX 混用同名类打进多份,报错 Duplicate classdex 冲突
  • Android Studio 里可看 Gradle 依赖树、用 ./gradlew :module:dependencies、对冲突包做 exclude强制版本Manifest merger 可在 AS 里看 合并报告
  • 不矛盾:Unity 负责 产出可运行的导出工程;AS 负责 在完整 Android 工程语境下收敛依赖。实践上 日常用 Unity 出包迭代发版前用 AS 打 release 或至少同步一次依赖,与本系列 优先 AS 打包 的建议一致。
答题示例

多 aar 最容易撞重复类和传递依赖版本。Unity 日志有时只报 dex 或合并失败,不好一眼看出是哪两个库冲突。

导出到 AS 里打开依赖树,看哪两个库引入了同名的不同版本,按文档 exclude 或统一版本。Manifest 冲突也在 AS 的 merger 报告里更直观。Unity 只管把插件放进去,最终 Gradle 能不能收干净,AS 更好查。

参考文章
  • 7.打包测试

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏