Time After (Screen) Time, part 3. The Device Activity Monitor Extension.

letvar
3 min readJun 7, 2024

--

Photo by Matt Seymour on Unsplash

Here we are again talking about the Screen Time APIs, shortly before WWDC and with the hope that some of the major issues will be resolved in iOS 18.

Update from WWDC24: it seems that there are no major updates regarding Screen Time, as it wasn’t mentioned in the Keynote and Platforms State of the Union, and no sessions or labs are scheduled in the upcoming days :(

Today I’ll cover the Device Activity Monitor (DAM) Extension, one of the extensions available to monitor usage activity of apps, categories and websites.

What can be done

First of all

Make sure you have requested the production entitlement for Family Controls on your bundle ID, as mentioned in the first part of our Screen Time series.

In your app

With a DAM extension you can monitor the start and end of an interval. Intervals can be repeated over time, and you can also set a warning time to notify the user that the interval is nearing its end.

Intervals are provided with date components to the DeviceActivityCenter class. You should also provide a DeviceActivityName to identify your activity.

Let’s say you want to monitor an activity every day between 10AM and 2PM, but you also want to set a threshold of two hours. To start monitoring in this scenario, you should do the following:

let deviceActivityCenter = DeviceActivityCenter()
let activityName = DeviceActivityName("lunchBreak")

let now = Date()
let components: Set<Calendar.Component> = [.hour, .minute, .second]
let calendar = Calendar.current
let startDate = calendar.date(bySettingHour: 10, minute: 0, second: 0, of: now)!
let endDate = calendar.date(bySettingHour: 14, minute: 0, second: 0, of: now)!
let intervalStart = calendar.dateComponents(components, from: startDate)
let intervalEnd = calendar.dateComponents(components, from: endDate)

let schedule = DeviceActivitySchedule(intervalStart: intervalStart, intervalEnd: intervalEnd, repeats: true)
// you can also provide a warningTime to DeviceActivitySchedule.

let thresholdDate = calendar.date(bySettingHour: 2, minute: 0, second: 0, of: now)!
let thresholdTime = calendar.dateComponents(components, from: thresholdDate)
let event = DeviceActivityEvent(threshold: thresholdTime)
let eventName = DeviceActivityEvent.Name("lunchBreakEvent")

try deviceActivityCenter.startMonitoring(activityName, during: schedule, events: [eventName: event])

To stop monitoring activities, simply call deviceActivityCenter.stopMonitoring() . You can also pass an array of activities to stop — otherwise, all running activities will be stopped.

In the extension

To create a DAM extension, go to File > New > Target in your Xcode project and choose Device Activity Monitor Extension. A DAM extension provides by default some methods extended from the DeviceActivityMonitor class, namely:

func intervalDidStart(for activity: DeviceActivityName) , called when the interval starts.

func intervalDidEnd(for activity: DeviceActivityName) , called when the interval ends.

func intervalWillStartWarning(for activity: DeviceActivityName) , called at the desired warningTime .

func eventWillReachThresholdWarning(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName), called when the specified event will reach the threshold.

func eventDidReachThreshold(_ event: DeviceAcitivityEvent.Name, activity: DeviceActivityName) , called when the specified event has reached the threshold.

From here you can do whatever you want within these intervals. Always remember that you are in a sandboxed environment, so you can’t always get what you want (like network requests).

Downsides and nitpicks

Like other components of the Screen Time APIs, the Device Activity Monitor is not exempt from issues, bugs and limitations. Here’s what we observed:

  • the extension has a budget of just 6 MB of RAM. Yes: 6 megabytes. So make sure to keep your extension as thin as possible, and only perform the tasks you need… otherwise it will crash 💥
  • the DAM extension must be scheduled with a minimum end interval of 15 minutes from the start date. This means, if you want to test the behaviour in real life, you must wait at least 15 minutes. ⏰
  • if your device is in standby or turned off, the methods will be invoked when the device is turned back on and unlocked. 🔐
  • bugs, bugs everywhere. We have seen that the intervalEnd is not always triggered and respected by the system. This means that the behaviour could be unexpected, as we also pointed in this Apple Developer Forums thread. 🐛
Photo by Milad Fakurian on Unsplash

The author

Nicola Giancecchi
Co-founder, CEO and Apple Platforms Engineer @ letvar

Feedbacks are welcome! hello@letvar.io

--

--

letvar

We are a team of creatives and focused on crafting apps for any device.