iOS ScreenTime(DeviceActivity) API全家桶简述——梦想美好,但现实荒唐

2,311 阅读7分钟

起因

最近正好有一个在iOS端需要一定细粒度获取用户使用某个App时长的需求,于是研究一下iOS有没有提供相关的API。iOS一贯以隐私和种种限制著称,但印象中Forest和各种Todo、番茄钟软件近两年也都有了给软件上锁的功能,甚至不乏提供各个App使用时间显示的软件。印象中WWDC22某个很炫的视频中也有提到类似的功能。

开发者的好时代真的来了?于是我在纳米AI搜索(邀请码:BB8KR6,嘿嘿嘿带个私货)里面问了问DeepSeek,得知ScreenTIme API中有一个DeviceActivity框架,可以创建一个扩展来检测使用情况。

注:本文没有进行任何实际上的代码实践,仅为在阅读官方文档和相关博客后的简单总结,作为个人对这方面开发的笔记,以及为中文开发者有相似疑惑的朋友们一个简单参考。

正文

权利申请和使用限制

首先,作为App可能了解用户手机使用情况的一种手段(虽然这个API鸡肋到基本上什么也了解不了),并且如果家长为孩子的设备配置了家庭控制App,该App将无法在孩子的设备上直接选择卸载,所以Apple认为该API是涉及用户隐私的重要权利,需要在开发者网站的页面中单独申明原因申请使用权。 申请链接

需要注意,这一权限绑定某一特定BundleID而不是开发者账号,如有开发多个相关App的需求需要重新申请。

API内容简述

ScreenTIme API并不是一个单独的框架,其由FamilyControlsManagedSettings(包括gedSettingsUI**)DeviceActivity这三个框架组成。本文的吐槽主要针对DeviceActivity,其余部分只做简述。

FamilyControls:主要用于与iOS中的家人共享功能交互,并非本文涉及的核心内容。但本框架中AuthorizationCenter的requestAuthorization(for:)是访问ScreenTIme API中其它框架所必须的授权代码。可选参数有.individual(用户自己)和 .child,这也决定了应用用途是针对个人还是家长管理。

ManagedSettings:用于对设备上设置和功能的访问进行限制,如应用锁和功能限制选项。可提供的限制选项类似于iOS设置中“屏幕使用时间-内容与隐私限制”内的内容。其亦非本文涉及的核心内容。(PS:印象中在本机中设置这些选项的功能在iOS5时代就有,且描述文件也可以对这些选项进行限制,在Apple Configurator2里面就可以生成这种描述文件。)这里比较有意思的是应用锁,对特定应用进行锁定的功能(效果同在“屏幕使用时间”中停用,而不是iOS18中的隐藏App)在此框架内提供。

DeviceActivity:用于监控用户使用手机的行为与显示屏幕使用时间报告,分为两个不同的扩展Device Activity MonitorDevice Activity Report。可监控的行为包括应用和网站的使用时间,与在屏幕使用时间中可供选取的一样。

注:在官方文档中有一个名为ScreenTime的框架,虽然有相似的名字,但它是提供给浏览器应用适配屏幕使用时间功能的。其并不是ScreenTIme API的一部分。 框架提供了用来报告网页使用时间的标识符设置、屏幕使用时间设置监听、删除与该浏览器应用标识符关联的Web使用情况统计数据等功能。在此可以看到,因为iOS上所有浏览器都是内嵌WebView(不考虑最近欧盟的情况),所以只需要简单绑定就可以适配屏幕使用时间中的按网页监控使用情况功能。(PPS:苹果怎么这么喜欢用这么大的名字实现这么一个小功能啊,文档还很容易令人迷惑,为了养活更多的专栏作者吗(ˉ▽ˉ;)...)

几个主要的吐槽点

本文的吐槽主要集中于DeviceActivity中提供的几个功能,包括通过FamilyActivityPicker显示列表选择要监控的应用、DeviceActivityMonitor中的监控功能与DeviceActivityReport的用户使用报告展示。

通过FamilyActivityPicker显示列表选择要监控的应用:

作为遵纪守法的好App,是不能读取用户选择的应用列表滴,所以Apple善良的提供了FamilyActivityPicker(只能被SwiftUI调用)来选择需要的应用或网站活动。在此应用只能获取一个标识符(FamilyActivitySelection 类型),用于传递给对应的函数,如DeviceActivityEvent等。

DeviceActivityMonitor中的监控功能:

DeviceActivityMonitor的设计旨在根据开发者在DeviceActivityCenter中设置的日程表和事件参数,监控几个简单的事件节点,仅包括:

  • func intervalDidStart(for activity: DeviceActivityName) ,在间隔开始时调用
  • func intervalDidEnd(for activity: DeviceActivityName) ,在间隔结束时调用
  • func intervalWillStartWarning(for activity: DeviceActivityName) ,在间隔即将开始时调用
  • func intervalWillENdWarning(for activity: DeviceActivityName) ,在间隔即将结束时调用
  • func eventWillReachThresholdWarning(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) ,在指定事件(如某些应用的使用时间限制)将达到阈值时调用(达到阈值之前多久调用取决于在事件中设置的WarningTime
  • func eventDidReachThreshold(_ event: DeviceAcitivityEvent.Name, activity: DeviceActivityName) ,在指定事件(如某些应用的使用时间限制)达到阈值时调用

所以,对于想对App使用时间进行管理的开发者来说,能做的只有设定一个(因为有WarningTime,所以也可以理解为两个)固定的时间阈值,然后在用户达到这个阈值时执行一些动作(如提醒、记录、上锁等等)。相比于系统在屏幕使用时间中提供的“App限额”功能,也只是多了应用限额生效时段的设置,以及一次WarningTime的动作罢了。

DeviceActivityReport实现用户使用报告展示:

看起来很美好,可以在自己的应用中展示用户的App使用情况,但Apple提供给你的只是一个只能传入数据的沙盒扩展,只有这个扩展内可以获取到用户授权显示的App使用时间数据,且该扩展不能以任何方式与外部通信。所以,你真的只能为屏幕使用时间中的数据重新写一个UI,除此之外什么都做不了。也许你可以实现一个简单的分析功能,但切记你手上的内存只有100m,不要爆掉哟。

总结与致谢

本文没有任何代码,因为在了解了框架能实现的功能后,就没有任何写个Demo的动力了。/(ㄒoㄒ)/~~ iOS18有了应用锁之后,这个API除了给番茄钟们添加个定时应用锁之外,也没什么应用场景了。

如今,玩手机上瘾成了家常便饭,但iPhone的屏幕使用时间功能还远远不够。Apple给了开发者一个美好的梦,看起来可以基于ScreenTime API实现很多伟大的功能。但一旦拿起来,就会发现其中的鸡肋,看起来很好,但你什么都做不了。

致谢

感谢Nicola Giancecchi撰写的三篇文章,详细的描述了其中的坑与奥妙,为本文提供莫大的帮助。

Time After (Screen) Time, part 1. The underworld of a barely known API. | by letvar | Medium

Time After (Screen) Time,第 2 部分。设备活动报告扩展。|由 letvar |中等 --- Time After (Screen) Time, part 2. The Device Activity Report Extension. | by letvar | Medium

Time After (Screen) Time,第 3 部分。设备活动监视器扩展。|由 letvar |中等 --- Time After (Screen) Time, part 3. The Device Activity Monitor Extension. | by letvar | Medium

感谢效率应用Streaks的开发者,文章中对API的应用做出了详细描写。

Monitoring App Usage using the Screen Time Framework

Apple官网文档

DeviceActivity | Apple Developer Documentation

FamilyControls | Apple Developer Documentation

ManagedSettings | Apple Developer Documentation

ManagedSettingsUI | Apple Developer Documentation

希望研究具体实现和更详细内容的朋友们可以参考他们的文章,也许会有更大的帮助。