Mac原生构建、实时协议与开放问题数降至350以下
目录
从截图构建界面,以及更简化的Initializr
值得了解的较小修复
关于贡献的说明
即将推出的亮点
总结
[LOADING...]
本周我们的工作焦点遍布各处,涵盖了桌面端、变现、通信、媒体等多个方向。这与我们的路线图一致:打造一个真正实现Java未能实现的承诺——"一次编写,随处运行"的通用平台。
但在深入介绍新功能之前,有一个数字让我特别自豪……
开放问题数降至350以下
当前开放问题数已低于350(撰写本文时为332)。这是我们主动梳理问题追踪列表的结果:关闭已修复的问题、复现未确认的问题,并直接修复了一批问题。本周关闭的部分报告自2015年起就处于打开状态。过程中我们偶尔会分心(看到老旧报告很难忍住不立即修复),但方向是明确的:我们希望这个数字持续下降,而且要大幅下降。
我们从最古老的问题开始,逐步向后排查。你可能还记得,当我们开始追踪这一数据时,突破500大关曾是一个重要里程碑——而那仅仅是几周前的事!
本周发布的内容
每一重大功能都有其深度教程。以下是概览,附有完整文章链接。
你的应用现在是原生Mac应用
你现有的Codename One应用无需任何移植工作即可立即以100%原生Mac应用的形式发布。无需重写、无需捆绑JVM、无需Electron外壳:你当前的项目能像生成iPhone应用一样,通过相同的Metal渲染器和经过实战检验的原生管道生成精炼的原生Mac二进制文件。而且它看起来就像真正的Mac应用,而非窗口化的手机应用:原生标题栏、原生菜单栏、交互式滚动条、桌面通知都一应俱全。本周功能中的两项在此一并呈现:下方示例使用稍后介绍的新广告API,以原生Mac应用形式运行,而代码与iOS和Android构建相同:
[LOADING...]
完整教程(包括新的桌面菜单和快捷方式API以及Mac签名提示)请参阅 你的Codename One应用,现在是原生Mac应用。
核心中的WebSocket
com.codename1.io.WebSocket 现已成为框架的一部分,无需 cn1lib,并在每个端口上原生实现。建立实时连接只需一行流畅的代码:
这是下方GraphQL订阅功能的基础,并且足够可靠,我们的截图CI已将其用作设备渲染的传输层。使用它构建实时聊天的动手教程请参阅 核心中的WebSocket、gRPC和GraphQL。
根据你的Schema生成类型安全的GraphQL客户端
cn1:generate-graphql 将GraphQL Schema转换为类型安全客户端:你只需声明一个针对操作(operations)的接口,构建过程会自动生成实现,无需你编写任何HTTP管道。使用 @Subscription 可以通过新的核心WebSocket获取实时服务器推送更新:
注意 Episode 是真正的枚举类型:枚举绑定已随此工作一同落地到JSON/XML映射器中,也修复了 @Mapped 用户长期以来的一个缺口。完整教程在 核心中的WebSocket、gRPC和GraphQL。
无需protoc的gRPC客户端
cn1:generate-grpc 对proto3执行相同操作。指向你的 .proto 文件,它会生成消息、二进制protobuf编解码器和客户端,采用与Envoy及现代gRPC服务器兼容的标准gRPC-Web有线协议。无需安装 protoc,无需原生依赖;调用服务如下:
结合 cn1:generate-openapi 和 cn1:generate-graphql,这意味着只需一个Maven目标即可为几乎任何后端生成类型安全的客户端。从proto文件到运行调用的完整教程在 核心中的WebSocket、gRPC和GraphQL。
全新广告API
原有的广告支持通过三种死胡同式的遗留机制悄然腐朽。一个新的可插拔、格式完整的 com.codename1.ads 子系统取代了它们,内置现代AdMob参考提供商、GDPR同意及iOS应用透明跟踪,以及一个模拟器占位提供商,让你无需设备即可测试每种格式。用户最常询问的激励广告现在只需以下简短代码:
关于横幅广告、原生广告、开屏广告及提供商SPI的完整说明请参阅 全新广告API,从零构建。
后台执行与推送
基于约束的后台工作、前台服务、推送主题、共享内容处理以及更丰富的本地通知API,所有这些都可在模拟器中使用,方便你在桌面端调试这些流程。你只需描述工作需要什么条件,而非指定轮询时间:
从进度通知和内联回复到推送主题和共享内容的完整教程,请参阅 后台工作、推送主题与更丰富的通知。
从截图构建界面,以及更简化的Initializr
生成的应用自带一个位于 .claude/skills/ 下的 codename-one 智能体技能(agent skill),因此在你项目中工作的AI智能体已经知道如何构建、测试和截图Codename One界面。PR #5161 教给它最常见的设计任务:"让这个界面看起来像这个模型图。"
该任务的难点在于智能体没有客观的衡量标准来评估接近程度。现有的截图测试仅能将渲染结果与系统自己生成的基准进行比较,这衡量的是一致性而非正确性。新的 CompareToMockup 工具是一个纯JDK的单文件CLI,它会对渲染结果与目标图像进行评分并输出相似度百分比:一个 STRUCTURAL 分数(基于SSIM的感知度量,对矢量模型图的字体和抗锯齿噪声具有鲁棒性)和一个 PIXEL 分数(在框架自身的三通道"相同像素"容差范围内的像素比例)。它支持区域模式,以免设备边框影响分数;支持 --diff 热力图;以及 --min 门槛。这为智能体提供了真实的信号:渲染 → 评分 → 查看热力图 → 调整 → 重复,直到分数不再增长。配套的 DesignImport 工具可将Figma、Sketch或Adobe XD文件(以及经过 PR #5168 后,来自HTML或React模型图的 tokens.css)转换为初始的 theme.css,使智能体从已有基础进行调整而非从零开始。该技能现在还能通过 UpdateSkills 工具自我更新,因此几个月前生成的项目可以拉取最新的指导,而非携带一份冻结的副本。
智能体现在可以自动将技能更新到最新版本,并描述Codename One GUI的内容。这一点很有价值,因为它们可以审查自己的工作,无需使用视觉识别——后者既更昂贵又不够准确。我们还增加了检查组件对齐的功能,这往往是LLM难以处理的问题。此外还有一个新的linter,我认为将来也应开放给人类开发者。目前你可以像智能体一样查看并使用所有这些工具,但它们更偏向CLI方式。
PR #5168 还围绕Codename One设计语言重建了Initializr(用于搭建新项目的工具),并进行了精简,使其更易于上手。它首先展示核心内容(主类、包名、Java/Kotlin切换开关),将IDE设置、本地化、Java版本和当前设置放在可折叠卡片中,底部有实时预览和单个生成按钮。原来的四模板选择器被替换为Java/Kotlin切换开关,并移除了强调色、圆角按钮和自定义CSS控制。背后的项目模型没有变化,因此生成的项目与之前相同;这纯粹是为了降低上手门槛。
[LOADING...]
值得了解的较小修复
其中几个直接来自问题跟踪器的梳理:
cubic-bezier()动画现在符合CSS标准。 PR #5122 修复了 #1524:Motion.createCubicBezierMotion此前将其控制点直接馈入一维多项式,导致曲线与所基于的CSScubic-bezier()不匹配。现在已修正,因此某些动画的表现可能有所不同。- X轴上的始终弹性效果。 PR #5112 关闭了 #1399(第二大古老的开放问题,提交于2015年3月):
setAlwaysTensile(true)现在也适用于水平方向,而不仅仅是垂直方向。这意味着在X轴滚动时也能看到橡皮筋效果。 - 验证高亮在切换焦点时触发。 PR #5123 关闭了 #1459:当一个字段的值无效时,点击其他字段后该字段会高亮,而不再仅限于按下虚拟键盘的“下一个”/“回车”键。
- EncodedImage.dispose() 现在真正释放内存。 PR #5127 使
dispose()释放解码后的图像数据及编码字节(此前为空操作),并增加了isDisposed()。关闭 #3733。 - NetworkManager.ping()。 PR #5130 添加了
ping(url, timeoutMillis),这是一个真实的服务器可达性探测,与设备端的isConnected()配合使用。关闭 #3669。 - ImageViewer 拖动冒泡。 PR #5132:在缩放级别为1的
ImageViewer上垂直拖动现在会向上冒泡给父容器,而非被吞没。关闭 #3700。这意味着你现在可以在可滚动Y容器中放置多个图像查看器。 - Graphics.isVisible()。 PR #5129 添加了一个裁剪交集原语,使缩放画布可以剔除屏幕外内容并跳过解码/缩放。关闭 #3846。
- 截图区块现在覆盖peer组件。 PR #5107:
ios.blockScreenshotsOnEnterBackground=true此前隐藏了渲染表面,但让peer组件(例如BrowserComponent的WKWebView)在应用切换器快照中仍然可见。已修复。 - 更好的站点搜索。 PR #5090 将站内搜索索引按最新优先排序,并阻止了庞大的开发者指南页面压制所有其他结果。我们还使搜索结果中的博客文章旁边显示了日期,并新增提示说明我们不搜索开发者指南/Javadoc。
关于贡献的说明
我们不再接受社区拉取请求(pull requests)。我们希望精确说明原因,因为很容易对此过度解读。
这并非关于AI生成的PR。我们不会审查贡献的编写方式。
真正的原因是机械性的:我们的CI无法在来自fork的PR上正确运行。截图管道、设备运行器和协议测试都需要凭据和特定设置,fork的PR无法获得这些,因此社区PR无法通过与我们自身代码相同的验证关卡。这个问题不易解决,否则会给我们的流程带来重大安全漏洞。最近,一个看似完全安全的改动悄悄通过了审查,却触发了CI回归,导致构建中断。责任在我们,而非贡献者,但这让我们确信,合并无法完全验证的代码并非明智之举。
因此,我们以另一种方式敞开大门。请继续提交问题(issues)。 附带测试用例的清晰问题对我们来说不难处理,正如上面数字所显示,我们正在积极处理跟踪列表。如果你有修复方案,请在问题中描述、附上失败用例,我们将自行通过CI完成。
对于多年来向我们发送过补丁的人们,尤其是近期贡献者:感谢你们。你们的努力是真实的,我们非常感激;这一决定关乎我们的管道,而非你们的工作。
即将推出的亮点
后续将发布四篇深度教程,每天一篇:
- 周六。 原生Mac构建与更深入的桌面集成。PR #5053、#5136、#5170。
- 周日。 核心中的WebSocket、gRPC和GraphQL。PR #5133、#5099、#5141。
- 周一。 全新广告API。PR #5169。
- 周二。 后台工作、推送主题与更丰富的通知。PR #5142。## 总结
问题追踪器位于此处,是目前与我们联系的最佳途径。讨论论坛在这里,Build Cloud 控制台位于
/console/。Playground、Initializr 和 Skin Designer 的地址保持不变。
本文最初发布于 foojay,标题为 Mac Native Builds, Live Protocols, And Open Issues Under 350。