Foreground State
前台应用时段与窗口标题时段
前台状态 Observer 记下某台设备上系统确认的前台应用和窗口标题。两种观测由同一个程序实例形成,各有自己的 EntitySchema 和时间线:标题变化时,应用时段照样延续;标题读取失败时,应用时段照样记录。
它记下的是前台时长。用户是否活跃由读取方组合多条时间线判断,见 Desktop · 各自的时间线。
实体
| 实体 | 资源名 | 说明 |
|---|---|---|
| Foreground State Observer | foreground-state-observers | 一个前台状态 Observer 程序实例 |
| Local Application | local-applications | 设备上的一个应用安装 |
| Foreground Application Period | foreground-application-periods | 应用处于前台的一个时段 |
| Foreground Window Title | 待定 | 窗口标题的一个时段 |
程序实例
- 一个程序实例对应本机上运行的一个前台状态 Observer。它重启或升级后沿用原来的 EntityId;另一台设备上的、或独立运行的实例,各有自己的 EntityId。
- 身份文件由
--identity-file指定,只保存程序实例的 EntityId。文件不存在时生成一个 UUIDv7;文件损坏时报告错误,并保留原文件。 - 一个身份文件同时只允许一个进程使用。
- 本机应用的身份保存在单独的登记文件中,见 Local Application · 登记文件。
- 程序实例本身是一个业务实体,EntitySchema 见 Foreground State Observer。
采集
应用、焦点窗口和标题在同一次读取中取得,再分别更新应用时段和标题时段。读取由三种情况触发:
- 启动时,读取一次当前状态。
- macOS 报告应用激活、焦点窗口切换或窗口标题变化时,立即读取。切换应用或焦点窗口后,监听目标随之更新。
- 默认每秒定时读取一次,确认当前状态。
macOS 即将休眠时,当前时段结束;唤醒后重新读取。读取失败时,当前时段也结束,下一次成功读取开始新的时段。锁屏和无输入不影响前台时段。时段边界的完整规则见 Foreground Application Period · 事实时间。
标题通过所属的应用时段 Observation 关联到这一段活动,窗口本身没有身份。标题怎样分段,见 Foreground Window Title · 粒度。
提交
前台状态 Observer 使用 .NET SDK,采用结束后提交:进行中的时段是 SDK 中的草稿,只在本地补全,结束时才冻结并安排发送,所以后端只会看到已结束的时段。业务事件对应的操作如下:
| 业务事件 | 交给 SDK 的操作 |
|---|---|
| 首次确认应用在前台 | 识别本机应用;形成观测内容和 Observation 的草稿 |
| 再次确认同一段活动 | 把新的结束边界合并进 Observation 的草稿 |
| 切换应用,或应用名称、时区变化 | 通知当前时段结束;为新状态形成新的草稿 |
| 读取失败、停止采集或其他中断 | 当前时段结束于最后一次确认,通知结束;恢复后形成新的草稿 |
观测内容被 Observation 引用,形成后随即冻结;它引用的本机应用版本也一样。结束当前时段和开始新的时段在同一个本地事务中完成。
程序异常退出后,下次启动时,SDK 恢复遗留的草稿,业务代码通知它结束于本地保存的最后一次确认。程序实例的身份不变,停机期间不计入时段,新的读数开始新的时段。
被拒绝的版本
| 情况 | 处理 |
|---|---|
| 另一个程序实例已为同一个应用保存了首版(VERSION-6),内容相同 | 采用已保存的首版 |
| 用户删除了某个本机应用(HISTORY-7,或时段的引用违反 ENTITY-6) | 为这个安装分配新的 EntityId,更新登记文件,再改写待发送的时段 |
| 其他原因 | 报告错误,暂停发送 |
用户删除的是过去的数据。之后继续采集时,同一个应用以新的身份出现。
实现
| 平台 | 应用时段 | 窗口标题 |
|---|---|---|
| macOS | 已实现:本机应用身份、连续时段,经 .NET SDK 上传 | 未实现 |
| Windows | 未实现 | 未实现 |
| Android | 未实现 | 未实现 |
macOS 程序在 src/Observers/Orisumi.Observer.ForegroundState/,通过 AppKit 读取前台应用,可以持续采集,也可以只采样指定的次数。启动参数见该目录的 README。平时由 macOS 客户端作为 helper 运行。
用到的 macOS 接口:应用激活通知、焦点窗口变化通知、标题变化通知。
测试 Case:本机应用身份、时段边界、提交与恢复、被拒绝的版本。
待定
- Android 上来源身份、重复查询与 Activity 生命周期的对应关系。
- 程序实例本身被用户删除后,前台状态 Observer 怎样继续。
- 跨平台应用的身份,见 Local Application · 待定。