Post not yet marked as solved
We have developed a Parental/Self control app using Screen time API.
We have used individual authentication to authorize the app, using the instructions here:
https://developer.apple.com/documentation/familycontrols/authorizationcenter
The problem is , that individual auth can be disabled easily , by the following steps:
enter Settings app.
in Settings app, click on the Parental/Self control app.
click to disable screen time restriction.
show the device owner's face/fingerprint. (or pin code)
Why is that a problem:
Parental control apps, or self-control apps, are about giving control to the software, To make it hard for the user to disable the restrictions.
So using the flow I have introduced above, it's super-easy for a user to disable his Parental control restrictions, which misses the entire point of Parental/Self control idea.
Furthermore, not only the user have the means to unlock his screen time restrictions, he also MUST have the means to unlock it.
This makes Screen time (with individual auth) useless:
I have a code ready to make a great parental control app for my clients, with amazing ideas, but I can't use the Screen time API unless this problem is fixed.
Why child-parent auth is not enough:
My clients are grownups people between ages of 15-40, that are interested in self-control, so they don't have iCloud child accounts.
also, the child-parent auth solution forces my clients to give some control to other person, and my clients prefer their privacy. Some of them prefer self-control and not parental-control.
What I suggest as a solution:
1: Give more options to users how to disable the Screen time restrictions. including:
a second faceID / FingerPrint (that isn't the same as the one used to unlock the device)
a second pin password.
a string password
2: Give the users the option to choose to not have the device's owner Face/Finger/Pincode ID , as a method to disable the Screen time restrictions.
Post not yet marked as solved
Hello,
we have been using the SwiftUI Label with the Family Controls tokens (ApplicationToken, ActivityCategoryToken - https://developer.apple.com/documentation/swiftui/label/init(_:)-39rkz)
And noticed that sometimes (quite rarely) the loading of the labels would take so long that it would freeze the entire app. Unfortunately as this only happened to our users (few times during user interviews) we aren't able to reproduce it on our devices and profile it.
My guess is that this "mapping" of tokens to images happens entirely on the UI thread because it is supposed to be fast but sometimes there is huge delay and everything freezes.
It would be great if the labels were somehow "prepared" on the background and the Label view would perhaps show some sort of loading and then get updated with the image of the app or category.
This freezing was happening even when our app showed at most six labels on the screen.
We tried some workarounds, namely to render the Label components in a backround and then use it as an image but instead of app icons we got yellow squares with red cross - probably due to privacy reasons.
Anyone run into this issue? Any solutions?
Post not yet marked as solved
How long will it take to request Family Controls? I've been asking for two weeks and still haven't heard anything back from Apple
Post not yet marked as solved
Hello,
I am trying to make use of Screentime API in my app, I have issue with the DeviceActivityMonitor extension. I have schedule DeviceActivitySchedule which I set like this:
let schedule = DeviceActivitySchedule(
intervalStart: DateComponents(hour: 00, minute: 00),
intervalEnd: DateComponents(hour: 23, minute: 59),
repeats: false
)
and DeviceActivityEvent which I set like this:
let dateComponent = DateComponents(minute: 1)
var events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [
.encouraged: DeviceActivityEvent(threshold: dateComponent)
]
The issue is that every time I start monitoring, by calling this piece of code from the app:
do {
print("Try start monitoring...")
try center.startMonitoring(.daily, during: schedule, events: events)
} catch {
print("Error: ", error)
}
I catch in the extension that the event intervalDidStart is called, but in the same second I get called eventDidReachThreshold. What could be done wrong? Is event set properly?
I was trying to set event with different Datecomponents (minute, hour, second), by setting different amount of time, like:
let dateComponent = DateComponents(minute: 3)
let dateComponent = DateComponents(second: 120)
but nothing worked differently, every time, it was triggering eventDidReachThreshold right after the interval starts.
If I put something unnormally high, like:
let dateComponent = DateComponents(second: 120)
The event eventDidReachThreshold is not triggered same time as the intervalStarts, but it is not counting time properly.
Please if someone could help me, I want to be able to use events properly, with the amount of time which I set. Any help would be appreciated.
Thanks in advance
Post not yet marked as solved
The eventDidReachThreshold calls immediately not waiting for accumulated time.
Example of setting the event:
let events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [
.monitorEducation: DeviceActivityEvent(
applications: educationalApps.applicationTokens,
threshold: DateComponents(minute: 15)
)
]
What could be wrong?
Post not yet marked as solved
Hi,
I'm building an app for iPhone, iPad and Mac (Mac Catalyst).
Unfortunately when I'm adding Family Controls capability to project I'm unable to run Mac Catalyst version of app. Everything is compiling, it fails when run and shows "Could not launch App"
Launch Service error
IDELaunchErrorDomain: code 20
RBSRequestErrorDomain: code 5
NSPOSIXErrorDomain: code 153
iOS version work without any problems and Screen Time releated Api too. My minimum deployment target is iOS 15. Our permission for Family Controls to distribute in AppStore is currently processing but I guess it shouldn't has influence as I'm running debug.
Best,
Marcin
Post not yet marked as solved
I'd like to implement prevent of deleting the app. In app I use Screen Time API with .individual type of authorisation.
I know it possible do manually in iPhone's Settings:
Settings > Screen Time > Content & Privacy Restrictions > iTunes & App Store Purchases > Deleting Apps
and then choose Don’t Allow option.
I've seen this implementation in other apps has been done programmatically.
How I can do the same?
Post not yet marked as solved
I want to deny deleting of my app. In the doc says that we can use:
var denyAppRemoval: Bool? { get set }
But it's doesn’t work. Example of applying:
store.application.denyAppRemoval = true
What I'm doing wrong?
Should it work for .individual type of Family Control auth?
Post not yet marked as solved
Modifying the WebContentSettings.FilterPolicy of a managedSettingsStore object to so that its type is not .none removes the private browsing capability in Safari by default.
Is there a way to avoid this? Is this mentioned somewhere in the documentation? Are there any other unexpected side-effects of modifying the WebContentSettings.FilterPolicy?
Post not yet marked as solved
Hi,
I'm having trouble understanding what is the correct DateComponents format for the DeviceActivityCenter.startMonitoring to work as expected.
Here's how it behaves with my setup:
The schedule interval is set for 15 minutes (the minimum).
On intervalDidStart I set the shields
shield.applicationCategories = .all(except: exclCat)
shield.webDomainCategories = .all(except: exclWeb)
On intervalDidEnd I clear the settings
shield.applicationCategories = nil
shield.webDomainCategories = nil
Different behavior with different DeviceActivitySchedule intervals. In the below examples I'll refer to hour, minute and second components as time components, and the calendar, timeZone, year, month, day, hour, minute and second components as date and time components.
Also, with all combinations below no errors are thrown when calling the startMonitoring method.
A. ❌ The start interval has time components, while the end interval has date and time components:
The intervalDidStart is not triggered.
DeviceActivitySchedule(schedule: <USDeviceActivitySchedule: 0x28354a5e0>
IntervalStart: <NSDateComponents: 0x2839c7f40> {
Hour: 9
Minute: 24
Second: 55
IntervalEnd: <NSDateComponents: 0x2839c7f70> {
Calendar: <CFCalendar 0x2818f9090 [0x1e4fb1d10]>{identifier = 'gregorian'}
TimeZone: Asia/Manila (GMT+8) offset 28800
Calendar Year: 2023
Month: 5
Leap Month: 0
Day: 15
Hour: 9
Minute: 39
Second: 55
Repeats: 0
WarningTime: (null))
B. ❌ The start interval has date and time components, while the end interval has time components:
Here, the opposite of the above example happens — the intervalDidStart is triggered, but the intervalDidEnd is not.
C. ❌ Both intervals have time components:
The intervalDidStart is not triggered.
D. ✅ Only hour, minute, and second components for both start and end intervals:
Callbacks are called as expected.
DeviceActivitySchedule(schedule: <USDeviceActivitySchedule: 0x282e80450>
IntervalStart: <NSDateComponents: 0x2822f39f0> {
Hour: 9
Minute: 12
Second: 15
IntervalEnd: <NSDateComponents: 0x2822f3a00> {
Hour: 9
Minute: 27
Second: 15
Repeats: 0
WarningTime: (null))
So it seems that the correct and working version is with the time components only.
However, from the documentation, the maximum schedule interval is a week.
So if I need to set the schedule starting from a certain time of day A and ending in a certain time of day B, what should the DateComponents look like?
Thanks for you help!
Post not yet marked as solved
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?
Post not yet marked as solved
I'm posting this here to bring attention to an issue we reported in July 2022 but haven't received any feedback on (FB10768388). Unfortunately, the issue still persists in iOS 16.5.
When using the application.blockedApplications property of a ManagedSettingsStore to block apps, they disappear from the user's springboard as expected. However, when unblocking them, they only reappear in the App Library, which disrupts the organisation of the user's springboard if those apps were in folders or the dock.
This renders the blockedApplications settings completely useless, forcing us to resort to shielding instead. We have received numerous complaints from users that their carefully crafted springboard organisation has been ruined by this issue 😅.
I'm using the 'store.webContent.blockedByFilter' feature to block malicious domains on iOS 16.4. However, I have a list of over 20,000 domains to block, and I'm concerned if there's a limit to the number of domains I can include.
let store = ManagedSettingsStore()
var blockedDomains: Set<WebDomain> = []
/*contains over 20000 domains names*/
let blackList: [String] = getBlacklistedDomains()
for domain in blackList {
let webDomain = WebDomain(domain: domain)
blockedDomains.insert(webDomain)
}
store.webContent.blockedByFilter = WebContentSettings.FilterPolicy.specific(blockedDomains)
With this code it appears that either no domains are being blocked or only a few are affected.
Will having such a large list cause any issues or performance problems?
Post not yet marked as solved
I am passing a group of apps that the user did not select to the ManagedSettingsStore. I write it like this I then block the user from using this group of apps.
ManagedSettingsStore().shield.applicationCategories = ShieldSettings.ActivityCategoryPolicy.all(except:familyActivitySelection.applicationTokens)
This problem occurs when you select three or more categories in the FamilyActivityPicker. For example, if you select only the Education category, only the apps in the Education category will be available, but if you add the Productivity/Lifestyle category to the selected categories, all apps in the iPhone will be available. This problem occurs whether the number of categories to select is four or five. Perhaps IOS is not generating the exact set of apps when it generates the set.
Post not yet marked as solved
Hello Apple Developer Community,
I am currently exploring the Screen Time API and its potential for creating a parental control-style application. However, I have a slightly different use case in mind that I need some guidance on.
I am wondering if it is possible to use the Screen Time API to create a monitoring application for a consenting adult, instead of the traditional parent-child scenario provided by the Family Sharing setup. For example, if a friend of mine wants to apply an internet filter on their iPhone and have me monitor it, can I create an app to do so?
To elaborate, I'm envisioning a setup similar to how the 'Find My Friends' app allows us to locate our friends (who are not necessarily a part of our family) after obtaining their consent. Is it possible to leverage the capabilities of the Screen Time API to create a 'monitoring' app on my device that can track and control aspects of my friend's device usage without having to engage the Family Sharing and Family Controls frameworks?
I understand that privacy and consent are paramount in such a situation, but this is a scenario between two consenting adults. This is purely for the purpose of assisting my friend in managing their digital habits more effectively.
I appreciate any insights or advice that the community can provide on this topic.
Thank you in advance!
Post not yet marked as solved
Using the DeviceActivity framework we are able to display data based on a user's screentime and device usage. With the DeviceActivityFilter property, you can specify the date interval to collect data between.
In testing, it seems that data only becomes accessible once the extension has been installed (so the extension isn't reading the screentime data already collected on device). However, once installed, I'm curious how far back you can query data from in the data interval?
Opal which uses the Screentime API appears to have a lifetime Screentime metric, so hypothetically it should possible to query data as far back as collection starts. Unless they are getting around the sandbox environment and storing the data somehow.
Side note on Opal -- They seem to have a community average of Screentime among people in the same age group. Does anyone know how they are collecting the data for this average? Is it actually using live Screentime data or just aggregating data from other studies?
Post not yet marked as solved
Can't find much right now, but maybe Apple devs can share some updates ;)
Documentation:
https://developer.apple.com/documentation/ManagedSettings?changes=latest_minor
https://developer.apple.com/documentation/DeviceActivity?changes=latest_minor
https://developer.apple.com/documentation/FamilyControls?changes=latest_minor
Videos:
https://developer.apple.com/wwdc23/sessions/?q=screen%20time
Post not yet marked as solved
Hey 👋
I have an extension of type "Device Activity Report Extension".
Is there a way to know from the parent app if the extension process is alive?
the process name is DeviceActivityReportService
Why would I like to detect that?
The extension sometimes crashes due to memory pressure and I would like to reload the view automatically when this happens.
This issue happens under normal app use — the user switches quickly between two tabs that have DeviceActivityReport.
I filed a bug for this with a sample project to replicate (12192929)
Here is an output from the Console app when the DeviceActivityReportService is killed and the UI disappears:
kernel memorystatus: killing process 33061 [DeviceActivityReportService] in high band FOREGROUND (100) - memorystatus_available_pages: 68660
kernel DeviceActivityReportService[33061] Corpse allowed 1 of 5
SpringBoard [xpcservice<com.apple.DeviceActivityUI.DeviceActivityReportService([application<com.labalab.Screen-Time.marcin>:33046])>:33061] Workspace connection invalidated.
SpringBoard [xpcservice<com.apple.DeviceActivityUI.DeviceActivityReportService([application<com.labalab.Screen-Time.marcin>:33046])>:33061] Now flagged as pending exit for reason: workspace client connection invalidated
SpringBoard [FBInterfaceOrientationServiceServer] Removing client xpcservice<com.apple.DeviceActivityUI.DeviceActivityReportService([application<com.labalab.Screen-Time.marcin>:33046])>:33061.
SpringBoard Removed client for observing orientation events: <FBServiceFacilityServerClientHandle: 0x281fa23a0; com.apple.frontboardservices.orientation-observer; xpcservice<com.apple.DeviceActivityUI.DeviceActivityReportService([application<com.labalab.Screen-Time.marcin>:33046])>:33061: remote>
kernel 266908.072 memorystatus: killing_specific_process pid 33061 [DeviceActivityReportService] (per-process-limit 100) 35873KB - memorystatus_available_pages: 68793
Screen Time Terminating interface and invalidating assertion: identifier: com.apple.DeviceActivityUI.DeviceActivityReportService; assertion: 0x282316b70
Screen Time Terminating interface and invalidating connection: identifier: com.apple.DeviceActivityUI.DeviceActivityReportService; assertion: 0x0
Post not yet marked as solved
Hi,
I'm new to the developer community and am developing an app for a school project that relies on the screentime API. I'm using SwiftUI to generate Labels using the given ApplicationToken generated from my FamilyActivitySelection. However, I notice that the icon for these tokens is extremely small: only about 25x25 px.
I'm wondering if there is a way that the screentime API can let us use higher-res images using the opaque tokens?
This would be extremely useful in developing a more HIG-aligned app (e.g. a scroll-view of blocked apps).
Thank you!
Hello,
I would like to know if it is possible to extract or send data from the Device Activity Report Extension of a child phone to a parent phone (using a custom backend or not) with the child phone application.
Best regards,
Indigen