接入系统 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>
This commit is contained in:
2026-09-10 09:03:21 +08:00
parent 4d96ab0912
commit d9d45d983b
14 changed files with 651 additions and 19 deletions

View File

@@ -32,6 +32,10 @@
<listEntry value="850">@Strings.FldSeconds</listEntry>
<listEntry value="869">@Strings.FldSeconds0</listEntry>
<listEntry value="873">@Strings.FldWeekCal</listEntry>
<listEntry value="861">@Strings.FldCustomTime</listEntry>
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
<listEntry value="735">@Strings.FldCountdown</listEntry>
<listEntry value="1">@Strings.FldSteps</listEntry>
<listEntry value="14">@Strings.FldStepsRound</listEntry>
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
@@ -56,6 +60,10 @@
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
<listEntry value="204">@Strings.FldFloors7d</listEntry>
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
<listEntry value="828">@Strings.FldSteps28d</listEntry>
<listEntry value="832">@Strings.FldCal28d</listEntry>
<listEntry value="836">@Strings.FldDist28d</listEntry>
<listEntry value="840">@Strings.FldFloors28d</listEntry>
<listEntry value="618">@Strings.FldHeartRate</listEntry>
<listEntry value="276">@Strings.FldRestingHr</listEntry>
<listEntry value="12">@Strings.FldStress</listEntry>
@@ -111,6 +119,24 @@
<listEntry value="313">@Strings.FldUvi</listEntry>
<listEntry value="314">@Strings.FldVisibility</listEntry>
<listEntry value="315">@Strings.FldDewPoint</listEntry>
<listEntry value="612">@Strings.FldNextCal</listEntry>
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
<listEntry value="627">@Strings.FldRace5k</listEntry>
<listEntry value="628">@Strings.FldRace10k</listEntry>
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
<listEntry value="630">@Strings.FldRaceFull</listEntry>
<listEntry value="631">@Strings.FldPace5k</listEntry>
<listEntry value="632">@Strings.FldPace10k</listEntry>
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
<listEntry value="634">@Strings.FldPaceFull</listEntry>
<listEntry value="641">@Strings.FldGolfScore</listEntry>
<listEntry value="619">@Strings.FldRunWeek</listEntry>
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
<listEntry value="695">@Strings.FldApp1</listEntry>
<listEntry value="696">@Strings.FldApp2</listEntry>
<listEntry value="697">@Strings.FldApp3</listEntry>
<listEntry value="698">@Strings.FldApp4</listEntry>
<listEntry value="699">@Strings.FldApp5</listEntry>
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
@@ -134,6 +160,11 @@
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
<listEntry value="542">@Strings.FldOwmCo</listEntry>
<listEntry value="516">@Strings.FldOwmCity</listEntry>
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
<listEntry value="703">@Strings.FldCustom1</listEntry>
@@ -162,6 +193,10 @@
<listEntry value="850">@Strings.FldSeconds</listEntry>
<listEntry value="869">@Strings.FldSeconds0</listEntry>
<listEntry value="873">@Strings.FldWeekCal</listEntry>
<listEntry value="861">@Strings.FldCustomTime</listEntry>
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
<listEntry value="735">@Strings.FldCountdown</listEntry>
<listEntry value="1">@Strings.FldSteps</listEntry>
<listEntry value="14">@Strings.FldStepsRound</listEntry>
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
@@ -186,6 +221,10 @@
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
<listEntry value="204">@Strings.FldFloors7d</listEntry>
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
<listEntry value="828">@Strings.FldSteps28d</listEntry>
<listEntry value="832">@Strings.FldCal28d</listEntry>
<listEntry value="836">@Strings.FldDist28d</listEntry>
<listEntry value="840">@Strings.FldFloors28d</listEntry>
<listEntry value="618">@Strings.FldHeartRate</listEntry>
<listEntry value="276">@Strings.FldRestingHr</listEntry>
<listEntry value="12">@Strings.FldStress</listEntry>
@@ -241,6 +280,24 @@
<listEntry value="313">@Strings.FldUvi</listEntry>
<listEntry value="314">@Strings.FldVisibility</listEntry>
<listEntry value="315">@Strings.FldDewPoint</listEntry>
<listEntry value="612">@Strings.FldNextCal</listEntry>
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
<listEntry value="627">@Strings.FldRace5k</listEntry>
<listEntry value="628">@Strings.FldRace10k</listEntry>
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
<listEntry value="630">@Strings.FldRaceFull</listEntry>
<listEntry value="631">@Strings.FldPace5k</listEntry>
<listEntry value="632">@Strings.FldPace10k</listEntry>
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
<listEntry value="634">@Strings.FldPaceFull</listEntry>
<listEntry value="641">@Strings.FldGolfScore</listEntry>
<listEntry value="619">@Strings.FldRunWeek</listEntry>
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
<listEntry value="695">@Strings.FldApp1</listEntry>
<listEntry value="696">@Strings.FldApp2</listEntry>
<listEntry value="697">@Strings.FldApp3</listEntry>
<listEntry value="698">@Strings.FldApp4</listEntry>
<listEntry value="699">@Strings.FldApp5</listEntry>
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
@@ -264,6 +321,11 @@
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
<listEntry value="542">@Strings.FldOwmCo</listEntry>
<listEntry value="516">@Strings.FldOwmCity</listEntry>
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
<listEntry value="703">@Strings.FldCustom1</listEntry>
@@ -292,6 +354,10 @@
<listEntry value="850">@Strings.FldSeconds</listEntry>
<listEntry value="869">@Strings.FldSeconds0</listEntry>
<listEntry value="873">@Strings.FldWeekCal</listEntry>
<listEntry value="861">@Strings.FldCustomTime</listEntry>
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
<listEntry value="735">@Strings.FldCountdown</listEntry>
<listEntry value="1">@Strings.FldSteps</listEntry>
<listEntry value="14">@Strings.FldStepsRound</listEntry>
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
@@ -316,6 +382,10 @@
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
<listEntry value="204">@Strings.FldFloors7d</listEntry>
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
<listEntry value="828">@Strings.FldSteps28d</listEntry>
<listEntry value="832">@Strings.FldCal28d</listEntry>
<listEntry value="836">@Strings.FldDist28d</listEntry>
<listEntry value="840">@Strings.FldFloors28d</listEntry>
<listEntry value="618">@Strings.FldHeartRate</listEntry>
<listEntry value="276">@Strings.FldRestingHr</listEntry>
<listEntry value="12">@Strings.FldStress</listEntry>
@@ -371,6 +441,24 @@
<listEntry value="313">@Strings.FldUvi</listEntry>
<listEntry value="314">@Strings.FldVisibility</listEntry>
<listEntry value="315">@Strings.FldDewPoint</listEntry>
<listEntry value="612">@Strings.FldNextCal</listEntry>
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
<listEntry value="627">@Strings.FldRace5k</listEntry>
<listEntry value="628">@Strings.FldRace10k</listEntry>
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
<listEntry value="630">@Strings.FldRaceFull</listEntry>
<listEntry value="631">@Strings.FldPace5k</listEntry>
<listEntry value="632">@Strings.FldPace10k</listEntry>
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
<listEntry value="634">@Strings.FldPaceFull</listEntry>
<listEntry value="641">@Strings.FldGolfScore</listEntry>
<listEntry value="619">@Strings.FldRunWeek</listEntry>
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
<listEntry value="695">@Strings.FldApp1</listEntry>
<listEntry value="696">@Strings.FldApp2</listEntry>
<listEntry value="697">@Strings.FldApp3</listEntry>
<listEntry value="698">@Strings.FldApp4</listEntry>
<listEntry value="699">@Strings.FldApp5</listEntry>
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
@@ -394,6 +482,11 @@
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
<listEntry value="542">@Strings.FldOwmCo</listEntry>
<listEntry value="516">@Strings.FldOwmCity</listEntry>
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
<listEntry value="703">@Strings.FldCustom1</listEntry>
@@ -422,6 +515,10 @@
<listEntry value="850">@Strings.FldSeconds</listEntry>
<listEntry value="869">@Strings.FldSeconds0</listEntry>
<listEntry value="873">@Strings.FldWeekCal</listEntry>
<listEntry value="861">@Strings.FldCustomTime</listEntry>
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
<listEntry value="735">@Strings.FldCountdown</listEntry>
<listEntry value="1">@Strings.FldSteps</listEntry>
<listEntry value="14">@Strings.FldStepsRound</listEntry>
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
@@ -446,6 +543,10 @@
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
<listEntry value="204">@Strings.FldFloors7d</listEntry>
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
<listEntry value="828">@Strings.FldSteps28d</listEntry>
<listEntry value="832">@Strings.FldCal28d</listEntry>
<listEntry value="836">@Strings.FldDist28d</listEntry>
<listEntry value="840">@Strings.FldFloors28d</listEntry>
<listEntry value="618">@Strings.FldHeartRate</listEntry>
<listEntry value="276">@Strings.FldRestingHr</listEntry>
<listEntry value="12">@Strings.FldStress</listEntry>
@@ -501,6 +602,24 @@
<listEntry value="313">@Strings.FldUvi</listEntry>
<listEntry value="314">@Strings.FldVisibility</listEntry>
<listEntry value="315">@Strings.FldDewPoint</listEntry>
<listEntry value="612">@Strings.FldNextCal</listEntry>
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
<listEntry value="627">@Strings.FldRace5k</listEntry>
<listEntry value="628">@Strings.FldRace10k</listEntry>
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
<listEntry value="630">@Strings.FldRaceFull</listEntry>
<listEntry value="631">@Strings.FldPace5k</listEntry>
<listEntry value="632">@Strings.FldPace10k</listEntry>
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
<listEntry value="634">@Strings.FldPaceFull</listEntry>
<listEntry value="641">@Strings.FldGolfScore</listEntry>
<listEntry value="619">@Strings.FldRunWeek</listEntry>
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
<listEntry value="695">@Strings.FldApp1</listEntry>
<listEntry value="696">@Strings.FldApp2</listEntry>
<listEntry value="697">@Strings.FldApp3</listEntry>
<listEntry value="698">@Strings.FldApp4</listEntry>
<listEntry value="699">@Strings.FldApp5</listEntry>
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
@@ -524,6 +643,11 @@
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
<listEntry value="542">@Strings.FldOwmCo</listEntry>
<listEntry value="516">@Strings.FldOwmCity</listEntry>
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
<listEntry value="703">@Strings.FldCustom1</listEntry>
@@ -597,6 +721,22 @@
<settingConfig type="numeric" min="-720" max="840"/>
</setting>
<setting propertyKey="@Properties.CountdownDate" title="@Strings.SettingCountdownDate">
<settingConfig type="alphaNumeric" maxLength="10"/>
</setting>
<setting propertyKey="@Properties.TimeFmt" title="@Strings.SettingTimeFmt">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.DateFmt1" title="@Strings.SettingDateFmt1">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.DateFmt2" title="@Strings.SettingDateFmt2">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.OwmKey" title="@Strings.SettingOwmKey">
<settingConfig type="alphaNumeric" maxLength="40"/>
</setting>