DeviceActivityMonitor Schedule Pause

I am trying to understand how to approach 'x minute' pauses for a DeviceActivitySchedule.

For instance, I would like to let the user pause for 5 minutes from an active schedule (meaning un-shielding the apps and re-applying the shield after the 5 min has passed).

The only way that came to my mind was calling the following:

  1. Calling .startMonitoring to start monitoring a new event with the same apps starting .now and ending .now + 5 minutes;
  2. Calling in the intervalDidStart, store.shield.applications.subtract(apps) so that the apps are removed from the shield.
  3. Calling in the intervalDidEnd, store.shield.applications = apps so that the apps are now shielded again.

The problem is that, from the Apple Developer Documentation:

The minimum interval length for monitoring device activity is fifteen minutes.

So the minimum pause I could offer to the user would be 15 minutes.

And that tells me this approach is most likely wrong, because all other Screen Time apps, like Opal, Jomo, AppBlock offer also 5 min pause.

Does anyone know / can think of a different and better approach?

Accepted Reply

The answer actually lies in the recoverySuggestion when you convert the DeviceActivity.DeviceActivityCenter.MonitoringError.intervalTooShort error to LocalizedError (I don't know why they hide it there 😂)

"The minimum interval length for monitoring device activity is fifteen minutes. Consider using the warningTime property of an activity’s schedule to receive callbacks that are more granular than fifteen minutes."

Doc of warningTime: https://developer.apple.com/documentation/deviceactivity/deviceactivityschedule/warningtime

e.g. For a one-minute break, we can set the end time to be 15 minutes later and set the warningTime to be 14 minutes. Then intervalWillEndWarning will be called and we can treat it as the end time to end the break directly.

let now = Date.now
let start = Calendar.current.dateComponents([.hour, .minute, .second], from: now)
let fakeEnd = Calendar.current.dateComponents([.hour, .minute, .second], from: now.advanced(by: 15*60))
try deviceActivityCenter.startMonitoring(.breakTime, during: .init(intervalStart: start, intervalEnd: fakeEnd, repeats: false, warningTime: DateComponents(minute: 14)))

Replies

The answer actually lies in the recoverySuggestion when you convert the DeviceActivity.DeviceActivityCenter.MonitoringError.intervalTooShort error to LocalizedError (I don't know why they hide it there 😂)

"The minimum interval length for monitoring device activity is fifteen minutes. Consider using the warningTime property of an activity’s schedule to receive callbacks that are more granular than fifteen minutes."

Doc of warningTime: https://developer.apple.com/documentation/deviceactivity/deviceactivityschedule/warningtime

e.g. For a one-minute break, we can set the end time to be 15 minutes later and set the warningTime to be 14 minutes. Then intervalWillEndWarning will be called and we can treat it as the end time to end the break directly.

let now = Date.now
let start = Calendar.current.dateComponents([.hour, .minute, .second], from: now)
let fakeEnd = Calendar.current.dateComponents([.hour, .minute, .second], from: now.advanced(by: 15*60))
try deviceActivityCenter.startMonitoring(.breakTime, during: .init(intervalStart: start, intervalEnd: fakeEnd, repeats: false, warningTime: DateComponents(minute: 14)))