Files
fenix8v3-watchface/manifest.xml
ericwyuan d9d45d983b 接入系统 Complication,补齐倒计时/自定义格式/28天累计/空气质量
字段 125 → 156 项。

Toybox.Complications(source/Comp.mc)
  这条路推翻了我之前几个「表盘做不到」的判断 —— 当时只查了 ActivityMonitor /
  UserProfile / Weather,漏了系统把这些作为 complication 发布出来:
    - 下一个日程(CIQ 确实没有日历 API,但有 CALENDAR_EVENTS complication)
    - 训练状态、完赛预测 ×4、配速预测 ×4、最近高尔夫得分
    - 本周跑步 / 骑行距离(按运动分类的,按天历史做不出来)
    - 第三方 App 1–5(CGM、补水、行情这类 App 发布的)
  需要 ComplicationSubscriber 权限。

其余补齐
  - 近 28 天累计:步数 / 卡路里 / 距离 / 楼层
  - 事件倒计时:设置里填 YYYY-MM-DD,显示还剩几天
  - 自定义时间格式、日期格式 1/2:单字母占位符(h/H/m/s/a/D/M/N/Y/y/w)
  - OWM 空气质量:AQI 等级 + 描述 + PM2.5 + PM10 + CO,走
    /data/2.5/air_pollution —— 那个接口在免费档就开放,不需要 One Call 订阅

运行时踩的坑
  - Complication.unit 不保证是 String(周跑步距离返回的就不是),直接调
    .length() 抛 Symbol Not Found。unit 和 shortLabel 都改成先 instanceof 判型。
  - 浮点 value 直接 toString 印成 "0.000000",统一格式化成一位小数。
  - 第三方 App 槽位每取一次就要走完整个迭代器,四个格子都选 App 时会走四遍。
    改成每帧只枚举一次,由 view 在绘制开始时调 Comp.beginFrame() 失效。

测试
  全字段验证的 harness 本身会触发看门狗(一次 onUpdate 里算 156 个字段),
  改成分批每帧 12 个。实际使用一帧只算 4 个,不受影响。
  156 项全部可渲染,零运行时错误;17 款设备全部编译通过。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 09:03:21 +08:00

49 lines
1.7 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<iq:manifest xmlns:iq="http://www.garmin.com/xml/connectiq" version="3">
<iq:application
entry="Fenix8V3App"
id="f8a3c1b2c3d44e5f8a9b0c1d2e3f4a5b"
launcherIcon="@Drawables.LauncherIcon"
minSdkVersion="4.2.0"
name="@Strings.AppName"
type="watchface"
version="1.0.0">
<iq:products>
<iq:product id="enduro3"/>
<iq:product id="fenix843mm"/>
<iq:product id="fenix847mm"/>
<iq:product id="fenix8pro47mm"/>
<iq:product id="fenix8solar47mm"/>
<iq:product id="fenix8solar51mm"/>
<iq:product id="epix2"/>
<iq:product id="epix2pro47mm"/>
<iq:product id="epix2pro51mm"/>
<iq:product id="fenix7"/>
<iq:product id="fenix7x"/>
<iq:product id="fenix7s"/>
<iq:product id="fr965"/>
<iq:product id="fr265"/>
<iq:product id="fr255"/>
<iq:product id="venu3"/>
<iq:product id="vivoactive5"/>
</iq:products>
<iq:languages>
<iq:language>chn</iq:language>
<iq:language>eng</iq:language>
</iq:languages>
<!-- Sensor is rejected for type="watchface" unless Background is also
requested, so altitude and pressure come from Activity.Info instead. -->
<iq:permissions>
<iq:uses-permission id="UserProfile"/>
<iq:uses-permission id="Communications"/>
<iq:uses-permission id="Background"/>
<iq:uses-permission id="ComplicationSubscriber"/>
<iq:uses-permission id="SensorHistory"/>
</iq:permissions>
</iq:application>
</iq:manifest>