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!
Screen Time
RSS for tagShare and manage web-usage data, and observe changes made to Screen Time settings by a parent or guardian.
Posts under Screen Time tag
163 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Is there an API for obtaining the screen usage time of each app on the iPhone development platform
Hello,
We are developing a parental control app consisting of two parts: a parent app to manage settings and a child app to enforce these settings using iOS's Screen Time API, CoreData, and other components. We've attempted to use silent notifications with Firebase Cloud Messaging (FCM) to communicate updates from the parent app to the child app. Our current implementation involves background modes for remote messages and background tasks.
However, we're facing a challenge: while normal FCM push notifications with a 'message' key work as expected, silent notifications (with only a 'data' key) do not trigger the desired behavior in the child app, even though FCM returns a success response.
We're looking for assistance with two main issues:
Alternative Approaches: Is there a better way to notify the child app of changes? We're considering a system where the child app periodically checks for updates via API and then updates CoreData and managed settings. Any recommendations for this architecture or a more reliable notification system would be greatly appreciated.
Debugging Silent Notifications: If our current approach using silent notifications is feasible, could someone help us debug why these notifications are not working as expected? We've been stuck on this for a week, and any help would be a lifesaver.
Here's the relevant part of our AppDelegate code:
import UIKit
import FirebaseCore
import FirebaseMessaging
import BackgroundTasks
@objc class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
let gcmMessageIDKey = "gcm.message_id"
let backgroundTaskIdentifier = "com.your-company.your-app.silentnotification"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
// Register for remote notifications
UNUserNotificationCenter.current().delegate = self
application.registerForRemoteNotifications()
// Register background task
BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in
self.handleBackgroundTask(task: task as! BGProcessingTask)
}
return true
}
// Handle incoming remote notifications
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let aps = userInfo["aps"] as? [String: Any],
let contentAvailable = aps["content-available"] as? Int, contentAvailable == 1 {
// This is a silent notification
handleSilentNotification(userInfo: userInfo, completionHandler: completionHandler)
} else {
// This is a regular notification
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler(.newData)
}
}
// Handle silent notification
func handleSilentNotification(userInfo: [AnyHashable: Any], completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let request = BGProcessingTaskRequest(identifier: backgroundTaskIdentifier)
request.requiresNetworkConnectivity = true
do {
try BGTaskScheduler.shared.submit(request)
performAPICall { result in
switch result {
case .success(_):
completionHandler(.newData)
case .failure(_):
completionHandler(.failed)
}
}
} catch {
completionHandler(.failed)
}
}
// Handle background task
func handleBackgroundTask(task: BGProcessingTask) {
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
performAPICall { result in
task.setTaskCompleted(success: result != nil)
}
}
// Perform API call (placeholder implementation)
func performAPICall(completion: @escaping (Data?) -> Void) {
// Your API call implementation here
// For testing, you can use a simple delay:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
completion(Data())
}
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("FCM token: \(fcmToken ?? "nil")")
// TODO: Send this token to your server
}
}
Additionally, here is how we're sending notifications from the server side using Node.js:
// Import the required Firebase Admin SDK (assumed to be initialized elsewhere)
// const { getMessaging } = require('firebase-admin/messaging');
/**
* Sends a background push notification to an iOS device
* @returns {Promise<string>} The message ID if successful
* @throws Will throw an error if the sending process fails
*/
async function sendBackgroundPushNotification() {
// Construct the message object for a background push notification
const message = {
apns: {
headers: {
// Set the priority of the push notification
"apns-priority": "5",
priority: "5",
// Indicate that this is a background refresh notification
"content-available": "1",
content_available: "1",
// Specify the push type as background
"apns-push-type": "background",
// Set the topic to your app's bundle identifier
"apns-topic": "com.your-company.your-app", // Replace with your actual bundle identifier
},
payload: {
aps: {
// This tells iOS to wake up your app in the background
"content-available": 1,
},
},
},
// Custom data payload to be sent with the notification
// Modify this object to include the data you want to send
data: {
// Add your custom key-value pairs here
},
// Uncomment the following block if you want to include a visible notification
// notification: {
// title: "Notification Title",
// body: "Notification Body",
// },
token
token: "DEVICE_FCM_TOKEN_PLACEHOLDER",
};
try {
// Attempt to send the message using Firebase Cloud Messaging
const response = await getMessaging().send(message);
console.log("Successfully sent background data to iOS:", response);
return response;
} catch (error) {
console.error("Error sending background data to iOS:", error);
throw error;
}
}
// Example usage:
// sendBackgroundPushNotification()
// .then((response) => console.log("Message sent successfully:", response))
// .catch((error) => console.error("Failed to send message:", error));
We would really appreciate any insights or guidance on these issues. Thank you!
I shield a web domain picked by users like this (discouragedSelections is an instance of FamilyActivitySelection() btw) :
let webDomainTokens = discouragedSelections.webDomainTokens
store.shield.webDomains = webDomainTokens
The domain is correcly shielded and I can see the restricted screen when I access it via Safari.
When I tap on the main button of that restricted view, I receive a different token than the one I got from .webDomainTokens from the code above. Why?
override func handle(action: ShieldAction, for webDomain: WebDomainToken, completionHandler: @escaping (ShieldActionResponse) -> Void) {
// webDomain here is different from the one in store.shield.webDomains
}
Hello,
I installed the iPadOS 18 PB 1 on my iPad Pro M4 a few days ago and noticed a bug which is annoying.
If screen time runs out, the first thing I noticed, is that it is no longer possible to get one more minute in an app and also to send a message to the guard.
If I open the screen time settings, it will freeze and forces me to force quit the settings.
I also noticed, that the widget wohnt show something either..
Is this a known issue? I could not find something similar to this in the release notes.
I also submitted this bug in the feedback app.
So I have been using the iOS 18 beta and I would like to say first and foremost really great update I love the timed messages and the car Sickness stuff that’s awesome but my only problem with the update is screen time. I have screen time on my phone and when I updated to iOS 18 beta I can’t seem to claim more screen time. I have my screen time to where I can ignore it once I run out But in the new update I can seem press the button all I want but It wont give me more screen time. This Is what I imagine a minor fix and I would really appreciate if this was fixed soon. But other than that small detail Amazing update love what your doing over here at apple!
Hello.
I have a few questions about Location Push Service and Screentime Family controls.
Do Location Push Service and Screentime Family controls require permission to be tested with development builds?
Will my application for permission to test be approved?
How long does it take to receive results if I apply for permission?
Is it possible to use the functionality of the Screentime api in LocationPushServiceExtention?
Is it possible to control remotely even if I apply for Screen time API's Family Controls permission as an individual? (ex. Change Screen time settings by push from server)
Information is needed to plan an app that includes both functions.
Thank you
I want to display device activity reports for particular selected apps. for getting a daily basis app uses time. Now, what is happening? there are 10 apps selected from the family activity picker but some apps are displayed in the list. I need all 10 apps or more that I will choose from the family activity picker. The bellow code is used for fetching reports.
var body: some View {
VStack {
DeviceActivityReport(context, filter: filter)
}
}
bellow code is used for the filter
@State public var filter = DeviceActivityFilter()
init(selectedApps: Set<ApplicationToken>, selectedCategories: Set<ActivityCategoryToken>, selectedWebDomains: Set<WebDomainToken>) {
self.selectedApps = selectedApps
self.selectedCategories = selectedCategories
self.selectedWebDomains = selectedWebDomains
self.filter = DeviceActivityFilter(
segment: .daily(
during: Calendar.current.dateInterval(
of: .weekOfYear, for: .now
)!
),
users: .all,
devices: .init([.iPhone]),
applications: selectedApps,
categories: selectedCategories,
webDomains: selectedWebDomains
)
}
You can see we selected 3 apps from family activity picker but we getting 2 apps from DeviceActivityReport extension
following code is for device activity report extension
let context: DeviceActivityReport.Context = .totalActivity
// Define the custom configuration and the resulting view for this report.
let content: (ActivityReport) -> TotalActivityView
func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> ActivityReport {
// Reformat the data into a configuration that can be used to create
// the report's view.
var res = ""
var list: [AppDeviceActivity] = []
let totalActivityDuration = await data.flatMap { $0.activitySegments }.reduce(0, {
$0 + $1.totalActivityDuration
})
for await d in data {
res += d.user.appleID!.debugDescription
res += d.lastUpdatedDate.description
for await a in d.activitySegments{
res += a.totalActivityDuration.formatted()
for await c in a.categories {
for await ap in c.applications {
if let apptoken = ap.application.token {
let appName = (ap.application.localizedDisplayName ?? "nil")
let bundle = (ap.application.bundleIdentifier ?? "nil")
let duration = ap.totalActivityDuration
let numberOfPickups = ap.numberOfPickups
let app = AppDeviceActivity(appToken: apptoken, id: bundle, displayName: appName, duration: duration, numberOfPickups: numberOfPickups)
list.append(app)
}
}
}
}
}
return ActivityReport(totalDuration: totalActivityDuration, apps: list)
}
I want to display device activity reports for particular selected apps. for getting a daily basis app uses time. Now, what is happening? there are 10 apps selected from the family activity picker but some apps are displayed in the list. I need all 10 apps or more that I will choose from the family activity picker. The bellow code is used for fetching reports.
var body: some View {
VStack {
DeviceActivityReport(context, filter: filter)
}
}
bellow code is used for the filter
@State public var filter = DeviceActivityFilter()
init(selectedApps: Set<ApplicationToken>, selectedCategories: Set<ActivityCategoryToken>, selectedWebDomains: Set<WebDomainToken>) {
self.selectedApps = selectedApps
self.selectedCategories = selectedCategories
self.selectedWebDomains = selectedWebDomains
self.filter = DeviceActivityFilter(
segment: .daily(
during: Calendar.current.dateInterval(
of: .weekOfYear, for: .now
)!
),
users: .all,
devices: .init([.iPhone]),
applications: selectedApps,
categories: selectedCategories,
webDomains: selectedWebDomains
)
}
You can see we selected 3 apps from family activity picker but we getting 2 apps from DeviceActivityReport extension
following code is for device activity report extension
let context: DeviceActivityReport.Context = .totalActivity
// Define the custom configuration and the resulting view for this report.
let content: (ActivityReport) -> TotalActivityView
func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> ActivityReport {
// Reformat the data into a configuration that can be used to create
// the report's view.
var res = ""
var list: [AppDeviceActivity] = []
let totalActivityDuration = await data.flatMap { $0.activitySegments }.reduce(0, {
$0 + $1.totalActivityDuration
})
for await d in data {
res += d.user.appleID!.debugDescription
res += d.lastUpdatedDate.description
for await a in d.activitySegments{
res += a.totalActivityDuration.formatted()
for await c in a.categories {
for await ap in c.applications {
if let apptoken = ap.application.token {
let appName = (ap.application.localizedDisplayName ?? "nil")
let bundle = (ap.application.bundleIdentifier ?? "nil")
let duration = ap.totalActivityDuration
let numberOfPickups = ap.numberOfPickups
let app = AppDeviceActivity(appToken: apptoken, id: bundle, displayName: appName, duration: duration, numberOfPickups: numberOfPickups)
list.append(app)
}
}
}
}
}
return ActivityReport(totalDuration: totalActivityDuration, apps: list)
}
Can I use Screentime API in CLLocationPushServiceExtension?
For example, I am curious about whether it is possible to set a managed setting in the Screentime API to limit app usage time or change the time limit.
If the implementation of the above function is impossible or causes rejection by the App Store, is there a way to use the Screentime API in the background through push notification?
I implemented parents to manage their children's apps with FamilyActivityPicker.
Then, is there way to get child’s app list without FamilyActivityPicker?
When a request comes from the server, I want to set the screen time API of the requested phone or retrieve usage information. I would like to use silent push to complete that action in the background.
Is it impossible for the Screen Time API to run in the background?
When I go to ignore my screen time notification it won't work. Also when I go to open screentime in my settings it still doesn't work. Please help. Running the latest IOS 18 Beta
Using the Screen Time API, I can create multiple ManagedSettingStore objects with different names. Is there a way to retrieve these later by name?
For example, if I create them dynamically from a configuration managed by the user of my app, and the app crashes or its data gets corrupted, how can I get rid of "stale" ManagedSettingStore objects that I no longer know?
Or, if I somehow lose the name of a ManagedSettingStore I created, how long does the store stay active? Forever? How can I get rid of the "stale" store?
I have recently noticed that ever since I downloaded iOS 18 Public Beta 1, I have been unable to get to the screen time settings, after clicking the tab, the app just freezes. Although after a while I did get to the Screen Time tab, but all of the previous changes to my screen time were voided. App limits, Downtime, you name it, all gone. While my app limits do not work, I noticed that downtime still functioned, but when my parent changed the downtime settings on their phone (running iOS 17 no betas), it did nothing on my end. I am currently submitting feedback to apple and am trying to find workarounds. On an unrelated note to this issue, I noticed that “One More Minute” and “Request More Time” aren‘t there anymore, does anybody have any ideas or workarounds on any of these?
This morning I downloaded iPad/iPhone OS 18 public beta and I went to send a request for youtube and I can’t. the only option that comes up when I press ask for more time is enter screen time passcode. TIA
I used to ignore my screen time limits that I set for myself if the task was important, but when I download IOS 18 Beta, it doesn't allow me to ignore any apps limits despite trying to restart and troubleshoot
i just downloaded the iOS 18 beta yesterday and now my phones (iPhone 15 pro) screen time keeps crashing. when I reach my limit and input the screen time code it won’t respond and keeps me locked out. when I went into the settings to just turn off screen time the entire settings app just freezes and then crashes entirely. I’ve tried restarting the phone several times and nothing has any impact and can’t find anything online except a lot of other people having the same issue without a fix.
"Hi everyone! We've encountered an issue with uploading our app to the App Store. We received the Family Controls Distribution permission, updated the certificates and profiles, submitted it for review, but received feedback that the request simply doesn't appear for the moderators. Does anyone know what the problem might be? Our request is: try await center.requestAuthorization(for: .individual). We also confirmed that the device must have TouchID or FaceID installed."
Hello please fix the screen time issue on IOS 18 Beta. I know its a beta but its been over a month and issue has still not been resolved. This has been such a headache. It keeps crashing and made my life way harder then it should be. please fix this apple as soon as possible. Please FIX IT PLEASE FIX IT