release

提升 target API 之后,画面被切、返回键失灵

本以为改一个数字就行

Google Play 的 target API 要求逐年提高。控制台弹出警告,团队在构建设置里把数字往上挪一格。到这里五分钟就结束了。

问题出在之后。构建好装到真机上,会发现画面上下被系统 UI 吃掉,或者返回键没反应,又或者在平板上锁定的屏幕方向自己松开了。

原因在于,提升 target API 等于声明「这个应用将遵守新的行为规则」。 数字一改,此前一直被豁免的规则就会一次性全部生效。

而且这不是可以往后拖的作业。过了期限,连更新都发不出去。

下面是其中在 Unity 游戏里真正会显出来的那些。

要求的水准和期限逐年变化。当前基准请务必在 Google Play target API 要求 直接确认。行为变更的完整清单在 Android 行为变更文档里。 本文要写的是——提升的时候该确认什么。

拖下去会怎样

这个截止时间是定死的,一旦过了,两件事会同时发生。

1. 更新发不出去。 新应用和应用更新都要满足要求才能提交。 在提升 target API 之前,任何更新都发不了——内容补丁不行,崩溃修复不行, 紧急的安全修复也不行。

2. 触达不到新玩家。 达不到要求的应用,在系统版本高于它自身 target API 的设备上无法全新安装。 这类设备的占比会随时间上升,所以新增量会慢慢断掉。

说准确一点,应用并不会被从商店下架。 已经装好的玩家照样能玩。只是新玩家进不来, 而我们这边什么都改不了。对已上线的游戏来说,后面这半边更难受——因为出了问题也无从下手。

如果已经错过了时间,去控制台看看延期申请的入口是否还开着。但延期是争取时间的手段,不是豁免。

规则分成两类生效

Android 的行为变更里混着性质不同的两种。把它们分开,要处理的范围会小很多。

类型 何时生效 应对
对所有应用生效 系统升级即生效,与 target API 无关 无法推迟
提升 target API 后生效 从我们把数字调高那一刻起 随提升一并确认

下面要讲的是第二类。这些是我们自己打开的,所以知道自己开了什么、逐项确认就够了。

在 Unity 游戏里真正会显出来的

1. 画面被系统 UI 吃掉——边到边显示

应用绘制到整个屏幕,状态栏和导航栏叠在它上面。以前有关掉这个行为的属性,现在那条退路被堵上了。

在游戏里,最先显出来的是 UI 的边缘。左右上方的货币显示、底部的按钮行,这类贴着屏幕边缘摆放的东西会被状态栏或手势条挡住。

Unity 里要看的是 Screen.safeArea。这个值返回的是扣掉系统 UI 之后真正可用的区域,所以如果画布是按整块屏幕,也就是按 Screen.width 和 Screen.height 搭的,就会差出这段距离。此前为刘海屏做过适配的项目大多没事,跳过那一步的项目会在这里栽跟头。

2. 返回键不像从前那样传过来了——预测式返回

onBackPressed() 不再被调用,返回键事件也不再按旧方式送达。

Unity 游戏常用 KeyCode.Escape 来接 Android 的返回键。如果打开暂停菜单、退回上一屏的代码挂在这上面,务必在真机上确认。 清单文件里有把行为退回旧方式的开关,但那是争取时间的手段,不是解决办法。

3. 平板和折叠屏上方向锁定失效——不过游戏是例外

在大屏上,清单文件里的屏幕方向、禁止调整尺寸、宽高比限制都会被忽略。也就是说,按竖屏做的游戏,在平板上可能被拉成横屏。

这里有一条给游戏的例外。 在清单文件里把应用类别声明为游戏,就能从这项强制中排除。

<application android:appCategory="game">
  <activity android:screenOrientation="portrait" />
</application>

Unity 项目里缺这个属性的情况相当常见。如果大屏上布局散掉了,先从这里查。 有可能是一行就能收尾的问题。

4. 积压的定期任务不再补齐执行——主要是插件那边的事

按固定间隔重复预约的任务,因为设备休眠等原因被跳过多次时,以前会按跳过的次数一并补执行,现在只执行一次就往下走。

先把范围收窄。这更多是 Android 原生那边的事,而不是 Unity 的 C# 代码。 游戏里常见的离线奖励计算,一般是在回到前台时比对时间戳来处理的,不落在这里。

可能被绊到的是,原生插件或第三方 SDK 在内部跑着自己的重复任务——分析事件上报、推送令牌刷新、定期同步之类。这类多半由供应方处理,所以我们要做的是,确认那个 SDK 已经升到支持目标 API 的版本。

已上线的游戏,这里还多一层

如果还没上线,把上面几项改掉再构建就完事了。已经在运营中,情况就不一样。

提升 target API,要重新构建、过审、玩家真的更新了,才算结束。 期限是定死的,所以得从审核周期倒推排期,而在那之前,现有的构建照旧在跑。

这个结构和收到引擎安全公告时一模一样。和那时一样,排期之前,先确认现在还能不能把那个构建重新做出来。 如果构建机已经变样,或者拿不到签名密钥的人不在,排期本身就立不住。

安全这边可以顺手一起看的

趁着提升 target API,有些东西值得一并确认。反正都要重新构建、重新送审。

  • 签名体系有没有变 — 重新构建的过程中,确认签名密钥和流程与此前一致。
  • 插件和 SDK 是否支持目标 API — 含原生二进制的尤其如此。在供应方文档里,从哪个版本开始支持和那个版本是什么时候发布的要一起看。很久没动过的插件常常是拖后腿的那个。
  • 有没有多出不该留在构建里的东西 — 处理过程中加的临时日志或调试开关,别就那样发出去。
  • 改重新做过篡改判定的基准没有 — 构建一变,正常构建的基准也跟着变。重打包的判定在Unity MOD APK 防护指南里讲过。

检查项

提升之前

  • 已在官方文档确认当前的要求水准和期限。
  • 清楚现在商店上的构建是用哪个 target API 做的。
  • 已确认在用的插件和 SDK 支持目标版本。

提升之后,在真机上

  • 屏幕边缘的 UI 没有被系统 UI 挡住。
  • 返回键能正常打开暂停、退回上一屏。
  • 平板和折叠屏上,屏幕方向与布局保持在预期内。
  • 跑重复任务的插件和 SDK,在目标 API 版本上工作正常。

发布流程

  • 已按审核周期倒推排好日程。
  • 签名体系与构建可复现性一并确认过。
  • 临时加的日志和开关已经清掉。

如果你在用 OZero Security

不负责的范围

  • 我们不代做商店政策合规。 target API 的提升、审核排期、清单文件的配置,都是团队的工作。
  • 上述行为变更引发的 UI 与输入问题,同样属于游戏代码这边。

负责的范围

  • 既然是包含原生库的 SDK,让原生库与 Google Play 要求的 API 水准保持兼容是我们的责任。 当前支持到什么范围,可以查看手册或直接问我们。
  • 对重新构建出来的产物,我们识别可执行文件的二进制篡改、调试器附加与挂钩,以及模拟器、Root 这类不可信运行环境,提高绕过的难度。

如果因为政策期限本来就要重新构建和重新送审,把防护接入放进同一轮会更省。 之后单独做,就要多过一次审核。

结论:往上走的不是数字,是行为规则

把提升 target API 当成改构建设置,到真机上就会吃惊。它实际上是,一次性接受此前被豁免的那些行为规则的声明。

所以顺序是这样:先把数字调上去,在真机上亲眼看画面、输入和大屏,然后再排审核日程。只在模拟器上过一遍的话,前面那三项不太容易显出来。

而且这个期限每年都会来。把这次确认过的项目记下来,明年会短得多。

下一步

  1. 确认防护范围 —— 查看各平台的支持规格,以及各方案(Standard / Pro)的防护范围。
  2. 快速开始接入 —— 导入与配置步骤见集成手册。
  3. 技术咨询 —— 关于支持的 API 水准或重新构建的排期,欢迎联系我们。

既然要为商店政策重新构建,不如把防护放进同一轮 — OZero Security。

相关阅读