一个版本号,差点让整条构建链路翻车。平台版本是 37.2,一条构建路径把标点去掉,读成了 372。这个数字顺利通过了所有常规的最低版本检查。另一条路径则试图把后缀直接当整数解析,当场失败。两条路径的毛病,跟客户真正想构建的那个应用毫无关系。
这就是在目标 SDK 截止日期到来之前该做的事:先让新平台把构建搞崩,再修好它经过构建器的路径。随后,定位按钮会在一个生成的应用里走一遍新的权限流程。与此同时,PEM 解析和任务移除把两块反复出现的安全代码从各个应用中拿了出来。
先让新平台把构建搞崩
常规 SDK 下限仍保持在 36,同时加入这些 API 37 的检查。这样可以在改动客户构建默认值之前,先把迁移失败的问题走一遍。
源码检查的做法是:用同一份源码分别对两个平台 jar 编译,然后比对报错。依赖未解析的可选包可能在两次运行中报同样的错,真正有价值的信号,是只有新平台才会引入的那个错误。
如果类路径上多出一个 android.jar,它会从旧桩里提供一个已被移除的符号,从而让这项检查失效。脚本会清掉这些重复的平台 jar。用已移除的指纹 API 做故障注入探测,验证了这套比对确实能抓到它本该抓到的回归。
平台名不再是一个整数
已安装的 API 37 包使用 android-37.0、android-37.1、android-37.2 这样的命名。把整个后缀当整数处理,在一条构建路径上直接失败。而先去掉标点再解析更糟:37.2 变成 372,悄无声息地通过了所有普通的最低版本检查。
构建器现在能正确提取主 API 级别,更新了 build-tools 的处理方式,并使用与实际被构建的 SDK 根目录相关联的 SDK 管理器。生成项目的检查随后会针对新平台进行组装,覆盖仅靠源码检查看不到的失败。
这是上周平台监测工作的延续。目标是在还有时间修复生产端的时候,把一个未来的平台要求变成一项会失败的检查。
一次性定位要放在明确的用户动作之后
Android 17 引入了一个系统渲染的定位按钮,用于事务性的精确位置访问。Google 的政策页面(9 月 10 日核查)列出了 2027 年 1 月 27 日的合规期限,并说明 Android 17+ 的执行时间仍可能进一步更新。这些日期来自 Google Play 的定位政策;通用的目标 SDK 时间表是另一项独立要求。
Codename One 组件在支持的地方呈现平台控件,在其他地方呈现普通按钮:
- 引入 LocationButton,以“使用精确位置”文案初始化
- 添加位置共享监听器,拿到定位结果后调用附近的搜索逻辑
- 把按钮加入表单
其中的附近搜索属于应用自身代码。当权限被拒绝或没有位置送达时,返回空结果是正常情况。组件暴露 isSystemRendered(),让应用可以检查当前生效的是哪条路径。
Android 的定位按钮把精确位置请求绑定到一次可见的用户动作和一次会话范围内的授权。如果某个任务用粗略位置就能完成,那就继续用粗略位置。
用平台协议,不强迫升级 AndroidX
早先的实现依赖一个 AndroidX 库,其元数据要求 compile SDK 37 和 Android Gradle Plugin 9.1.0。那意味着一个新按钮会迫使每一个使用它的生成应用都做一次工具链迁移。
平台本身在那层封装之下已经暴露了会话 API。合并后的实现通过反射触达它,并用 Java 代理实现回调接口。系统把自己的控件绘制到一个宿主在 Codename One 组件内部的表面上。
Codename One 屏幕的其余部分保持自定义渲染;这块同意界面归操作系统所有。
权限注入和回退仍需留意
生成的清单必须包含 USE_LOCATION_BUTTON。当应用引用 LocationButton 时,仓库构建器会把它加上。另一个 BuildDaemon 镜像当时还没有跟上这项改动,所以云构建器也需要那次更新。
该实现也避免自动把所有精确位置权限都限制为仅按钮访问。一个应用可能同时还有合法的持续定位功能。这个决定需要审查应用实际的位置使用情况和当前平台指引,而不是凭一个类的存在去推断政策。
如果平台会话失败,组件会回退到普通按钮。这保住了可用的控件,但一个面向新事务性定位要求的应用应当测试系统路径是否真的仍然生效。在测试该流程时检查 isSystemRendered()。
Android 17 上的这个按钮
我们在一个 Android 17 模拟器上运行了生成的应用,compile SDK 为 37.2,target SDK 为 37。系统按钮渲染出来了,人工点击打开了平台同意表单,批准后产生了一个带有会话范围权限标志的位置。同一个 APK 在 API 36 上使用的是普通按钮和权限流程。
常规的截图 CI 分支仍在 API 36 上。把这项覆盖扩展到 API 37 是剩余迁移工作的一部分。
关键文件就在那里,为什么还要手工转换?
加载一个密钥往往从一个小转换任务开始:去掉 PEM 外壳、解码 Base64,再判断里面是哪种 DER 容器。让每个应用各自维护一个略有差异的解析器,并不是个好地方。
热门跟贴