Hi everyone,
I'm working on an app that uses the Screen Time API, and I'm encountering an issue with Live Activities.
The app runs a timer (e.g., 10 minutes), after which the intervalDidEnd method in DeviceActivityMonitor is triggered. To improve the user experience, I've implemented Live Activities to display the remaining time.
However, I'm having trouble stopping the Live Activity when the timer expires and intervalDidEnd is called. It seems that the Screen Time
extensions cannot detect or interact with active Live Activities, even though
both share the same App Group.
My Question:
Since the DeviceActivityMonitor extension does not seem to be able to detect Live Activities, does anyone know if there’s a way to end a Live Activity when the timer expires without relying on a server? Using Apple’s Push Notification service feels excessive given the lightweight nature of the app, which doesn’t use server-side components.
Any insights or suggestions would be greatly appreciated!
Thanks!
Post
Replies
Boosts
Views
Activity
I've been working with the Screen Time API for almost 6 months now.
I found out it's completely unreliable, testing on iOS 17.4, the DeviceActivityReport is not showing, the DeviceActivityMonitor more often than not does not fire intervalDidStart. It's very frustrating.
Has anyone found out a workaround?
We all know there has to be something we're doing wrong, since apps like Opal and Jono does not present those types of issues.
Let's please unite our forces and find a solution. How to use this API should not be a secret!
There is a way to allow DeviceActivityMonitor to make UI changes?
Currently I have some code in the intervalDidStart and intervalDidEnd that updates Core Data entities, and it works correctly.
However, the changes are only reflected if the app is terminated and opened again.
Thus, if the app is opened and one of the methods inside the DeviceActivityMonitor is being called, the UI won't be updated.
PS: I am using @FetchRequest to retrieve the core data entities called BlockEntity, and I have a little circle in the UI which should indicate the status of the block: active/inactive, so it would be nice to update the color in real time when intervalDidStart or intervalDidEnd are called.
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:
Calling .startMonitoring to start monitoring a new event with the same apps starting .now and ending .now + 5 minutes;
Calling in the intervalDidStart, store.shield.applications.subtract(apps) so that the apps are removed from the shield.
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?
Hello,
I wasn't able to figure out how to handle multiple days with DeviceActivitySchedule.
For instance, let's say the user wants to block certain apps from 9:00 AM to 12:00 AM, every day except Saturday and Sunday, how my schedule should look like?
I've tried different things...
This schedule works for each day of the week, but that's not my goal:
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 9, minute: 00),
intervalEnd: DateComponents(hour: 12, minute: 00),
repeats: true)
And if I specify the weekDay inside the DateComponents, like this:
// Gregorian calendar
// 2 -> Monday
// 6 -> Friday
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(..., weekday: 2),
intervalEnd: DateComponents(..., weekday: 6),
repeats: true)
the schedule will block the apps from Monday at 9:00 AM to Friday at 12:00 AM, which is also not my goal.
The only workaround that came to my mind was to create a different schedule for each day of the week:
enum WeekDays: String, CaseIterable {
case sun, mon, tue, wed, thu, fri, sat
var sortOrder: Int {
switch self {
case .sun: return 1
case .mon: return 2
case .tue: return 3
case .wed: return 4
case .thu: return 5
case .fri: return 6
case .sat: return 7
}
}
}
func startMonitoring(weekDays: [WeekDays]) {
for weekDay in weekDays {
let day = weekDay.sortOrder
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(
hour: 9,
minute: 00,
weekday: day),
intervalEnd: DateComponents(
hour: 12,
minute: 00,
weekday: day),
repeats: true)
let activityName = DeviceActivityName(weekDay.rawValue)
do {
try center.startMonitoring(activityName,
during: schedule)
} catch {
print("DEBUG: Error: \(error.localizedDescription)")
}
}
}
This way I kinda get what I want, for example:
I can specify 3 days of the week, let's say Monday, Tuesday and Wednesday, the time interval, let's keep 9:00 AM - 12:00 AM, and this function will block apps on Monday, Tuesday and Wednesday at that time interval, fine.
However...
What if I also want another schedule that blocks at a different time interval but same day?
For example, I want to block certain apps Monday and Tuesday from 2:00 PM - 6:00 PM.
Following the example above the activityName would be overwritten, so the user ( for Monday and Tuesday ) would now have only the schedules that starts from 2:00 PM.
Basically, I want the user to be able to select multiple days for a schedule and to let them create as many schedules as they want.
Does anybody know the correct way to handle multiple days schedules?