Hi I'm trying to build a screen time app and the Apple docs and APIs really leave something to be desired. I want to block apps on a schedule. That's it. To do this I need my DeviceActivityMonitorExt to know which apps to block. I need to somehow pass a DeviceActivitySelection from the main app into this DeviceActivityMonitorExt. How can I do this?
Device Activity
RSS for tagMonitor web and app usage through custom time windows and events.
Posts under Device Activity tag
83 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
How can I use the Screen Time API to set a restriction for a child account from my app running on the parent’s account?
I’m creating an app with the Screen Time API and I would like to know how to make the app show a parental control editing view for parents and a view for child accounts that shows which apps are blocked. How can I do this?
I created a ShieldConfigurationExtension in Xcode 14.3 with File > New > Target > ShieldConfigurationExtension. This created the extension with all the necessary Info.plist values (correct NSExtensionPrincipalClass, etc.), with the extension included in embedded content in the host app target.
No matter what I try, the extension is not getting invoked when I shield applications from my host app. The custom UI does not show as the shield, and looking at the debugger, an extension process is never invoked.
I am shielding categories like this:
let managedSettings = ManagedSettingsStore()
...
managedSettings.shield.applicationCategories = .all()
And my extension code overrides all the ShieldConfigurationDataSource functions.
class ShieldConfigurationExtension: ShieldConfigurationDataSource {
override func configuration(shielding application: Application) -> ShieldConfiguration {
return ShieldConfiguration(
backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial,
backgroundColor: UIColor.white,
icon: UIImage(systemName: "stopwatch"),
title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow)
)
}
override func configuration(shielding application: Application, in category: ActivityCategory) -> ShieldConfiguration {
return ShieldConfiguration(
backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial,
backgroundColor: UIColor.white,
icon: UIImage(systemName: "stopwatch"),
title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow)
)
}
override func configuration(shielding webDomain: WebDomain) -> ShieldConfiguration {
return ShieldConfiguration(
backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial,
backgroundColor: UIColor.white,
icon: UIImage(systemName: "stopwatch"),
title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow)
)
}
override func configuration(shielding webDomain: WebDomain, in category: ActivityCategory) -> ShieldConfiguration {
return ShieldConfiguration(
backgroundBlurStyle: UIBlurEffect.Style.systemThickMaterial,
backgroundColor: UIColor.white,
icon: UIImage(systemName: "stopwatch"),
title: ShieldConfiguration.Label(text: "You are in a Present Session", color: .yellow)
)
}
}
What am I missing?
Topic:
App & System Services
SubTopic:
General
Tags:
Extensions
Managed Settings
Family Controls
Device Activity
There is an inconsistent issue when views are rendered from the Device Activity Report Extension. This issue is noticeable only on release versions and it works fine in debug mode.
Around 80% of the times, the Report Views return blank screen and this is only the case when a weekly/monthly filter is used. Although, it works as expected for daily report views.
My questions are:
How are all the Report Activity Views working fine in debug mode but not in release mode?
How the daily activity filter works fine in the release mode but the weekly/monthly filters don't work? Is this because of a memory limit issue in the extension?
As of now, I have the family-controls(distribution) entitlement only for the app and for the extensions I only have family-controls(development) entitlement. Do I need to request for family-controls(Distribution) entitlement even for the extensions?
I have seen threads on the forum mentioning the blank screen issue associated with the DeviceActivityReport but haven't found a solution to it. Any suggestions/feedback would be of great help, thanks.
Topic:
App & System Services
SubTopic:
General
Tags:
Extensions
Entitlements
Device Activity
Screen Time
I'm using FamilyActivityPicker to get consent for app/category management, which returns a FamilyActivitySelection object.
I serialize this FamilyActivitySelection object (just applicationTokens and categoryTokens) and pass it to my DeviceActivityMonitor extension via App Group UserDefaults. I am using the JSON encoder/decoder over PropertyList (though both seem to exhibit the same behavior).
After inspecting the FamilyActivitySelection object immediately after it's returned by FamilyActivityPicker in the main app, the application.bundleIdentifier property is consistently nil for every Application object within selection.applications. Similarly, category.localizedDisplayName is nil for ActivityCategory objects. This happens whether "Select All Apps" is used or if apps/categories are selected individually.
I understand that this is the intended behavior due to Apple's user privacy policies. I read on another post that my app can be provided with bundle identifiers and app names within Shield Configuration extensions and Device Activity Report extensions - I'm not sure which ones or how exactly to do this.
I am aware that I can use Label(applicationToken) SwiftUI view to display the app name/icon, but this doesn't give programmatic access to the bundleIdentifier string.
My app will not log or export these bundleIdentifiers outside of its sandbox. My goal is to create mappings to the FamilyActivitySelection with the publicly accessible bundleIdentifiers.
Any guidance, examples, or clarification on the intended workflow for this scenario would be greatly appreciated!
Hi everyone,
I'm following up on this post I made earlier about an issue I'm having with FamilyControls and the DeviceActivityMonitor extension not working for external TestFlight testers.
To briefly recap:
I have official Apple approval for the com.apple.developer.family-controls entitlement (distribution)
The entitlement is added to both my main app and the DeviceActivityMonitor extension
The App Group is correctly configured for both targets
On internal TestFlight builds, everything works as expected: app blocking works, the extension runs, and selected apps are shielded.
On external TestFlight builds, users get the Screen Time permission prompt, can select apps to block, but nothing is blocked.
Since that post, I submitted a Code Level Support request, and Apple asked me to file a bug report via Feedback Assistant. I did that almost a month ago.
The only reply I’ve received since is that they can’t give a timeframe or guarantee it will be resolved. I'm stuck in limbo with no updates and no fix.
This feature is critical to my app and I cannot launch without it. I’ve reached out to other developers who use app blocking, and none of them have run into this issue. My setup seems correct, and Apple has not said otherwise.
If anyone has experienced something similar, found a workaround, or knows how to get real movement on a bug report like this, I would really appreciate any help. It’s been weeks, and I just want to launch my app.
Thanks so much.
Topic:
Code Signing
SubTopic:
Certificates, Identifiers & Profiles
Tags:
TestFlight
Family Controls
Device Activity
For an iOS app that runs in both child and parent mode across iOS devices. On the child device, with Family Controls enabled using .child permissions via AuthorizationCenter.requestAuthorization(for: .child).
Is any way to display a list of recently used apps by the child on the parent (guardian) device, in a privacy-preserving and Apple-compliant way?
Hello everyone,
I’m working on an iOS app that uses the new DeviceActivity framework to monitor and report user screen‐time in an extension (DeviceActivityReportExtension). I need to persist my processed screen‐time data into a standalone SQLite database inside the extension, but I’m running into issues opening and writing to the database file.
Here’s what I’ve tried so far:
import UIKit
import DeviceActivity
import SQLite3
class DeviceActivityReportExtension: DeviceActivityReportExtension {
private var db: OpaquePointer?
override func didReceive(_ report: DeviceActivityReport) async {
// 1. Construct path in app container:
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.mycompany.myapp")
let dbURL = containerURL?.appendingPathComponent("ScreenTimeReports.db")
// 2. Open database:
if sqlite3_open(dbURL?.path, &db) != SQLITE_OK {
print("❌ Unable to open database at \(dbURL?.path ?? "unknown path")")
return
}
defer { sqlite3_close(db) }
// 3. Create table if needed:
let createSQL = """
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
totalScreenTime DOUBLE
);
"""
if sqlite3_exec(db, createSQL, nil, nil, nil) != SQLITE_OK {
print("❌ Could not create table: \(String(cString: sqlite3_errmsg(db)))")
return
}
// 4. Insert data:
let insertSQL = "INSERT INTO reports (date, totalScreenTime) VALUES (?, ?);"
var stmt: OpaquePointer?
if sqlite3_prepare_v2(db, insertSQL, -1, &stmt, nil) == SQLITE_OK {
sqlite3_bind_text(stmt, 1, report.date.description, -1, nil)
sqlite3_bind_double(stmt, 2, report.totalActivityDuration)
if sqlite3_step(stmt) != SQLITE_DONE {
print("❌ Insert failed: \(String(cString: sqlite3_errmsg(db)))")
}
}
sqlite3_finalize(stmt)
}
}
However:
Path issues: The extension’s sandbox is separate from the app’s. I’m not sure if I can use the same App Group container, or if there’s a better location for an on‐extension database.
Entitlements: I’ve added the App Group (group.com.mycompany.myapp) to both the main app and the extension, but the file never appears, and I still get “unable to open database” errors.
My questions are:
How do I correctly construct a file URL for an SQLite file in a DeviceActivityReportExtension?
Is SQLite the recommended approach here, or is there a more “Apple-approved” pattern for writing data from a DeviceActivity extension?
Any sample code snippets, pointers to relevant Apple documentation, or alternative approaches would be greatly appreciated!
I'm working with the FamilyControls and DeviceActivity frameworks in iOS (Swift).
In my app, I collect selected apps using a FamilyActivitySelection, and I access the selected apps via selection.applicationTokens, which gives me a Set.
I would like to get either the bundle identifier or the display name of the selected apps from these ApplicationTokens.
I tried creating an Application instance using:
let app = Application(token: token)
print(app.bundleIdentifier)
print(app.localizedDisplayName)
However, both bundleIdentifier and localizedDisplayName are always nil.
My questions are:
Outside the extension (in the main app), how can I get the bundleIdentifier or display name from an ApplicationToken?
Is there an Apple-recommended way to resolve a Token into something human-readable or usable?
If not, what is the best practice to store or identify user-selected apps for later use?
Environment:
iOS 17,
Swift 5,
Using FamilyControls and DeviceActivity APIs.
Thank you for any help!
All
After about 20 hours straight of working on this and having scrapped it twice I am realizing I should have asked everyone here for help.
I am just trying to get device activity report extension to work inside an existing app.
I have been heavily using family controls, managedsettings and deviceactivity and decided it would be nice to output some of the app usage so the User (parent) can see their children's app usage.
I installed the target via xcode, confirmed group names match, and think I have it embedded correctly but when I run the app and call the view within the extension to show minutes used by any apps it just shows no time has been used. In addition, when I put print statements into the extension they do not show up in console.
I have confirmed the main app target->Build phases->Link binary with Libraries has:
ManagedSettings.framework
FamilyControls.Framework
DeviceActivity.framework
I have confirmed in xcode that the main app target->Build phases -> Embed Foundation Extensions has:
ShieldConfiguration.appex
ShieldActionExtension.appex
DeviceActivityMonitor.appex
I have confirmed in xcode that the main app target->Build phases-> Embed ExtensionKit Extensions has:
UsageReportExtension.appex
I have used the apps I am trying to show data for extensively in the last 36 hours.
Here is my UsageReportExtension info.plist
EXAppExtensionAttributes
EXExtensionPointIdentifier
com.apple.deviceactivityui.report-extension
.entitlement
com.apple.developer.family-controls
com.apple.security.application-groups
group.com.jrp.EarnYourTurnMVP2.data
Here is the file in the app (timebankview.swift) calling the extension/showing the extension view(AppUsageReportView.swift)
import DeviceActivity
import ManagedSettings
struct TimeBankView: View {
@EnvironmentObject private var appState: AppState
@State private var reportInterval: DateInterval = {
let calendar = Calendar.current
let now = Date()
let yesterdayDate = calendar.date(byAdding: .day, value: -1, to: now) ?? now
return DateInterval(start: yesterdayDate, end: now)
}()
private var reportFilter: DeviceActivityFilter {
let selection = appState.screenTimeController.currentSelection
return DeviceActivityFilter(
segment: .daily(during: reportInterval),
users: .children,
devices: .all,
applications: selection.applicationTokens,
categories: selection.categoryTokens
// webDomains: selection.webDomains // Add if needed
)
}
var body: some View {
ZStack {
Color.appTheme.background(for: appState.isParentMode)
.edgesIgnoringSafeArea(.all)
ScrollView {
VStack(spacing: 20) {
Text("Time Bank")
DeviceActivityReport(.childUsageSummary, filter: reportFilter)
Here is AppUsageReportView.swift
import SwiftUI
struct AppUsageReportView: View {
let config: DetailedAppUsageConfiguration // Use the detailed config
var body: some View {
VStack {
Text("App Usage Details")
Text("Total Screen Time: \(config.totalDurationFormatted)")
if config.applicationsUsed.isEmpty {
Text("No specific app usage data available for the selected period/filter.")
} else {
Text("Apps Used:")
List {
ForEach(config.applicationsUsed) { appInfo in
HStack {
Image(systemName: "app.dashed")
Text(appInfo.appName)
.lineLimit(1)
Text(appInfo.durationFormatted)
Here is AppUsageReportScene.swift:
import SwiftUI
import ManagedSettings
struct AppInfo: Identifiable, Hashable {
let id = UUID()
let appName: String
let durationFormatted: String
}
struct DetailedAppUsageConfiguration {
var totalDurationFormatted: String = "Calculating..."
var applicationsUsed: [AppInfo] = []
}
struct AppUsageReportScene: DeviceActivityReportScene {
let context: DeviceActivityReport.Context = .childUsageSummary
let content: (DetailedAppUsageConfiguration) -> AppUsageReportView
func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> DetailedAppUsageConfiguration {
var config = DetailedAppUsageConfiguration()
var appDurations: [String: TimeInterval] = [:]
var totalAggregatedDuration: TimeInterval = 0
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.unitsStyle = .abbreviated
formatter.zeroFormattingBehavior = .pad
var segmentCount = 0
var categoryCount = 0
var appCount = 0
for await activityData in data {
// Check segments
var tempSegmentCount = 0
for await segment in activityData.activitySegments {
segmentCount += 1
tempSegmentCount += 1
totalAggregatedDuration += segment.totalActivityDuration
var tempCategoryCount = 0
for await categoryActivity in segment.categories {
categoryCount += 1
tempCategoryCount += 1
var tempAppCount = 0
for await appActivity in categoryActivity.applications {
appCount += 1
tempAppCount += 1
let appName = appActivity.application.localizedDisplayName ?? "Unknown App"
let duration = appActivity.totalActivityDuration
appDurations[appName, default: 0] += duration
}}} }
config.totalDurationFormatted = formatter.string(from: totalAggregatedDuration) ?? "N/A"
config.applicationsUsed = appDurations
.filter { $0.value >= 1
.map { AppInfo(appName: $0.key, durationFormatted: formatter.string(from: $0.value) ?? "-") }
.sorted { lhs, rhs in
let durationLHS = appDurations[lhs.appName] ?? 0
let durationRHS = appDurations[rhs.appName] ?? 0
return durationLHS > durationRHS
}
if !config.applicationsUsed.isEmpty {
for (index, app) in config.applicationsUsed.enumerated() {
}
} else {
}
return config
}}
UsageReportExtension.swift
struct UsageReportExtension: DeviceActivityReportExtension {
init() {
print("🚀 [UsageReportExtension] Extension initialized at \(Date())")
print("🔍 [UsageReportExtension] Process info: \(ProcessInfo.processInfo.processName) PID: \(ProcessInfo.processInfo.processIdentifier)")
}
var body: some DeviceActivityReportScene {
let _ = print("📊 [UsageReportExtension] Building report scenes at \(Date())")
TotalActivityReport { totalActivity in
print("🕰️ [TotalActivityReport] Creating view with data: \(totalActivity)")
return TotalActivityView(totalActivity: totalActivity)
}}}
Topic:
App & System Services
SubTopic:
General
Tags:
Device Activity
Family Controls
Managed Settings
Screen Time
If I present "SFSafariViewController" when a "FamilyActivityPicker" is visible, it will automatically dismiss the "SFSafariViewController" and crash the "FamilyActivityPicker."
I'm assuming the cause of the bug is that each is in a separate process (aside from the app), and there's some hacks to try to stop "FamilyActivityPicker" from crashing, and this is causing the new bug because "SFSafariViewController" is also in a separate process.
(I'm not 100% if its just in 18.4 or iOS 18 overall...)
(I'll try to file a feedback soon, but its 100% reproducible for me across multiple devices on iOS 18.4)
Hi,
I'm trying to make use of the Device Activity Labels where you supply an ApplicationToken. I can successfully get it to show the icon + title of the Application (twitter in my case) but I cannot get the styling to work.
// Works
.labelStyle(.iconOnly)
.labelStyle(.titleOnly)
.border(...)

// Does NOT work
.font(.largeTitle)
.foregroundColor(.blue)
I have checked the same style (or just modifiers) against a standard Label and they actually do work in the code below.
// This is an application token. Some style not applied.
Label(targetApp)
.labelStyle(MyStyle())
// Showing the same style using a simple label. All styles correctly applied.
Label("Twitter", systemImage: "video.square.fill")
.labelStyle(MyStyle())
Is changing the font + color of the title for this Label(_ applicationToken:) supported?
Topic:
App & System Services
SubTopic:
General
Tags:
Managed Settings
Family Controls
Device Activity
Hello, I want to echo the DeviceActivityReport "concurrency" problems flagged in https://developer.apple.com/forums/thread/720549, and ask a related question. (Thanks to Kmart and other Apple dev support folks who have been monitoring these forums and responding diligently.)
I would like to display daily and weekly stats in the same view, broken down by specific apps (as in the native Screen Time). However, instantiating multiple DeviceActivityReport objects with different filters and/or different contexts leads to confusion, where the two views will incorrectly and intermittently swap data or duplicate data where it shouldn't (seemingly upon some interval when the extension provides fresh data). There isn't documentation on how to display multiple reports at once. Is the idea that logic for multiple reports should be embedded within the extension itself in the makeConfiguration() function and there should only be a single DeviceActivityReport in the main App, or is this a bug?
Even with a single DeviceActivityReport, I run into inconsistencies where the View provided by the extension takes multiple seconds to load or fails to load altogether. The behavior seems random...I will build the application with the same code multiple times and see different behavior each time.
Finally, a plug for better support in the Simulator for the entire set of Screen Time APIs.
Thanks!
Topic:
App & System Services
SubTopic:
General
Tags:
Family Controls
Device Activity
Screen Time
wwdc2022-110336
We developing a app called Parentgeenee. It's a Parental control app having any limitations on app block from child mobile. Trying to block more than 500 apps but not blocking if any particular method to block a bulk apps.
Topic:
App & System Services
SubTopic:
General
Tags:
Managed Settings
Family Controls
Screen Time
Device Activity
Our business model is to identify Frauds using our advanced AI/ML model. However, in order to do so we need to collect many device information which seems to be ok according to https://developer.apple.com/app-store/user-privacy-and-data-use/
But it's also prohibited to generate a fingerprint, so I need more clarification here.
Does it mean I can only use the data to identify that a user if either fraud or not but I cannot generate a fingerprint to identify the device?
If so, I can see many SKD in the market that generates Fingerprints like https://fingerprint.com/blog/local-device-fingerprint-ios/
and https://shield.com/?
Topic:
Privacy & Security
SubTopic:
General
Tags:
Analytics & Reporting
DeviceCheck
Device Activity
Privacy
Hi there,
My app uses all the Screen Time API's with individual FamilyControls authorization. I've been using the API's for over 2 years (since they came out).
In iOS 18 Beta (maybe started in Beta 3?), I've been experiencing random issues. I tracked it down to where it seems like DeviceActivityMonitor extension is more likely to deadlock in iOS 18.
To reproduce: when DeviceActivityMonitorExtension.intervalDidEnd gets called, IF you call DeviceActivityCenter.startMonitoring for that SAME DeviceActivityName from the DeviceActivityMonitorExtension , the startMonitoring call deadlocks (if I pause debugger, it does not advance past DeviceActivityCenter.startMonitoring).
The bug is reported in FB14664238. It also contains a sample project where you can reproduce this.
I also note in the comment section that this is not the only way to encounter this problem. My application code (which is a lot more complicated) seems to deadlock on calling DeviceActivityCenter.activities. As a result, there seems to be an "overall trend" where, due to some changes, DeviceActivityMonitor extension is more likely to deadlock.
The steps are not reproducible on iOS 17.6. This is built using Xcode 17.4.
Thank you! 🙏
Topic:
App & System Services
SubTopic:
General
Tags:
Family Controls
Device Activity
Managed Settings
Hey everyone,
I have an app using the screen time api, I've had quite a few reports from users saying that our monitoring features stop working until they open our app. What happens is that activities and schedules set with the device activity monitor seem to disappear. This is something we check on app re-opens and so we schedule them again and that is why the monitoring starts working again.
Of course our current solution is not optimal since our app is mainly passive. Has anyone experienced these kinds of issue ?
We are trying to create a screentime app using the Family Controls as well as Device activity frameworks. The build succeeds but while pushing to an iphone we are getting an info.plist file for deviceactivity.framework could not be found error. For reference when using the Screentime API a physical device must be used not a simulator. When we remove the device activity framework this error also occurs for the family controls framework. We have added the Family Controls(development) Capability and applied for the distribution capability. We have redownloaded xcode multiple times on the main device, deleted derived data, and redownloaded all of the iphone SDKs and the issue still persists.
After reading Apple documentation (FamilyControls, DeviceActivity, ManagedSettings, ManagedSettingsUI, ScreenTime) and testing the API, I do not find a way to get the child's device apps on the parent device in order to block them or disable them for a certain time.
Is there a way of doing it?
Or can it only be done locally on the child device?
Topic:
App & System Services
SubTopic:
General
Tags:
Family Controls
Device Activity
Managed Settings
Screen Time