Family Controls

RSS for tag

Prevent access to the Screen Time API without guardian approval and provide opaque tokens that represent apps and websites.

Posts under Family Controls tag

185 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

all my DeviceActivitySchedules are killed when granting unrelated 4th party app access to screen time API permission
I have two repeating DeviceActivitySchedules running in my app and noticed a super strange behavior: whenever I modify Screen Time API permission settings (granting an additional app permission, or removing permission for a different app (completely different unrelated screen time apps from App Store)) all my DeviceActivitySchedules are cancelled and the intervalDidEnd callbacks are called my permission is not modified in this scenario this is a super strange and unexpected behavior is anyone able to reproduce this? for me this happens 100% of the times I do this any known workarounds?
0
0
503
Mar ’24
In DeviceActivityReportScene count numberOfPickups for given Application
How can I count the number of pickups for a certain application? The docs say that there is a struct ApplicationActivity within the DeviceActivityData: https://developer.apple.com/documentation/deviceactivity/deviceactivitydata Using this code I receive a warning in XCode: Value of type 'DeviceActivityData' has no member 'applicationActivity' struct ApplicationPickupCountReport: DeviceActivityReportScene { // Define which context your scene will represent. let context: DeviceActivityReport.Context = .applicationPickupCount // Define the custom configuration and the resulting view for this report. let content: (String) -> ApplicationPickupCountView func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> String { var totalPickups = 0 let totalPickups = await data.flatMap { $0.applicationActivity }.reduce(0, { $0 + $1.numberOfPickups }) return "\(totalPickups)" } }
0
0
489
Mar ’24
DeviceActivityEvent with threshold spanning over midnight → threshold not working
Hello, I am using a DeviceActivityEvent to limit access to an app after the user has spent x minutes on it. Sometimes it can happen that a DeviceActivitySchedule spans from 11:55pm - 12:25am (just an example). In these cases, I have noticed, the DeviceActivityMonitorExtension’s eventDidReachThreshold is not called after the user has reached the threshold time interval in the observed app. I assume this is because we have transitioned over midnight and something weird happens to the DeviceActivitySchedule. I’ve tried adding the day components to the DeviceActivitySchedule as well, but then it fails completely. Any advice how to handle this? I could, of course, create two separate DeviceActivitySchedules: one for before midnight, and one for after. But depending on the user’s real app usage that could lead to slightly different (and unexpected) behavior.
0
0
548
Mar ’24
Un-shield an application of a particular schedule when multiple schedules are in place.
If we want to un-shield category/application for particular schedule, then what is the mechanism for this, as for now we are using ManagedSettingsStore().shield.applications = nil and ManagedSettingsStore().shield.applicationCategories = nil, which is actually un-shielding all category/applications without considering the selection of category/application for that schedule. What is the best approach to handle multiple schedules for shielding of apps?
0
0
427
Mar ’24
iOS 17.4 broke something with app limits?
Update 1: Seems like app limits do work, but they don't account for time spent already in the day (only counts it since it first was scheduled? - but just guessing). This seems to be the change in behavior that is making it seem like broken. I have an app that uses individual FamilyControls / Screen Time authorization. I am still investigating but reporting ASAP. Will add feedback and more later. I am not sure what's going on, but so far: App limits generally work fine throughout the day(?) At around 9 PM they stop working if I clear ManagedSettingStore/DeviceActivityCenter (it might be unrelated to the time, but just clearing, but this is just what I know so far) I tried setting app limits from Apple's Setting app (so I could see if it's not just my app, and that system could have issues) and it crashes. The whole Settings app freezes and then crashes. (edit: after some freezing, including in the app picker, I was able to set a limit and it worked...did notice some odd behavior where 1 minute break did not work, but selecting 15 minute break did work) going to also update: FB13688616
2
0
1.3k
Apr ’24
App Shielding unexpectedly active outside of schedule
I'm using the Screen Time API to shield apps the user selects. The problem is, that the apps are always shielded, even outside of the schedule. Here is my function initiateMonitoring: func initiateMonitoring(scheduleStart: DateComponents, scheduleEnd: DateComponents) { let schedule = DeviceActivitySchedule( intervalStart: scheduleStart, intervalEnd: scheduleEnd, repeats: true ) let center = DeviceActivityCenter() do { try center.startMonitoring(.daily, during: schedule) logger.log("STARTED MONITORING") } catch { logger.log("FAILED MONITORING: \(error.localizedDescription)") } } The expected result should be that the selected Apps should be blocked during the schedule the user specified, but not outside the schedule, but it is blocked 24/7. I've experimented with the DateComponents, but the issue may be somewhere else. What's maybe interesting is, I tried Logging the DeviceActivityMonitor and somehow it doesn't get called. The logging-output from initiateMonitoring is printed in the console, but for the DeviceActivityMonitor it's not. I implemented it as recommended as a separate Extension Target. For more context, here is my DeviceActivityMonitor: class DeviceActivityMonitorExtension: DeviceActivityMonitor { let store = ManagedSettingsStore() let logger = Logger() override func intervalDidStart(for activity: DeviceActivityName) { super.intervalDidStart(for: activity) logger.log("INTERVAL STARTED") let model = ShieldManager.shared let applications = model.selectionToDiscourage.applicationTokens let categories = model.selectionToDiscourage.categoryTokens let webCategories = model.selectionToDiscourage.webDomainTokens store.shield.applications = applications.isEmpty ? nil : applications store.shield.applicationCategories = ShieldSettings.ActivityCategoryPolicy.specific(categories, except: Set()) store.shield.webDomains = webCategories.isEmpty ? nil : webCategories } ... What's confusing me is that the apps are in fact shielded, so the MonitorExtension should be called, but neither the logging works nor my separate ShieldConfigurationExtension, maybe the issues are connected... Any help would be gladly appreciated!
1
0
548
Mar ’24
ManagedSettingsStore&socialStore.shield
when i watch the video (https://developer.apple.com/videos/play/wwdc2022/110336/) i find the code let socialStore = ManagedSettingsStore(named: .social) let socialCategory = database.socialCategoryToken socialStore.shield.applicationCategories = .specific([socialCategory]) i try to find ManagedSettingsStore shield and specific([socialCategory]) i Documentation , but i failed. who can tell me wher i can find about ManagedSettingsStore shield or specific([socialCategory]) ? thanks a lot.
0
0
355
Mar ’24
DeviceActivityMonitor does not trigger UI updates
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.
0
0
516
Mar ’24
Family Controls: `authorizationStatus` and `requestAuthorization` beyond dysfunctional
The functionality of authorizationStatus and requestAuthorization is completely broken. I'm using Xcode 15.3 and iOS 17.4. Does anyone have a solution? authorizationStatus doesn't behave as promised Revoking authorization in the system-wide settings does not change the authorizationStatus while the app is not closed. Calls to center.authorizationStatus will still return .approved instead of .denied. Even closing and relaunching the app after revoking authorization does not work: authorizationStatus is then .notDetermined when it should be .denied. Tapping "Don't Allow" in the alert shown after an initial call to requestAuthorization leaves the authorizationStatus unchanged, i.e. at .notDetermined. This is contrary to the promised outcome .denied (defined as: "The user, parent, or guardian denied the request for authorization") and contrary to the definition of .notDetermined (defined as: "The app hasn’t requested authorization", when it just did). Same issue when first tapping "Continue" followed by "Don't Allow" on the next screen. As a consequence of authorizationStatus being broken, its publisher $authorizationStatus is worthless too. requestAuthorization doesn't behave as promised This is most likely a consequence of the corrupted authorizationStatus: when revoking authorization in the system-wide settings, a call to requestAuthorization opens the authorization dialogue instead of doing nothing. It is thus possible to repeatedly ask a user to authorize Family Controls. Code sample To reproduce, create a new SwiftUI app, add the "Family Controls" capability and a button executing the following task when tapped: let center = AuthorizationCenter.shared var status = center.authorizationStatus print(status) do { try await center.requestAuthorization(for: .individual) print("approved") } catch { print("denied") } status = center.authorizationStatus print(status)
3
3
518
Mar ’24
Block Websites without FamilyActivityPicker
I want to block specific Websites with FamilyControls in my App. To do this, I need to access the WebDomainTokens of a specific Website, without the user selecting it in the FamilyActivityPicker. I basically just want to have a button e.g. "Block Instagram" and when clicking it, the instagram website is blocked. I don't see any way in accessing the WebDomainToken without the FamilyActivityPicker. Or is there maybe another approach to this problem? Currently I tried the following: var selectionToDiscourage = FamilyActivitySelection() { willSet { let applications = newValue.applicationTokens store.shield.applications = applications.isEmpty ? nil : applications let webDomain: WebDomain = .init(domain: "https://www.instagram.com/") print("TOKEN: \(webDomain.token)") print("DOMAIN: \(webDomain.domain)") if let webDomainToken = webDomain.token { let webDomainTokenSet: Set<WebDomainToken> = [webDomainToken] store.shield.webDomains = webDomainTokenSet } } } But when only giving the domain, the token always prints nil. Hope someone can help!
1
0
705
Mar ’24
AuthorizationCenter.shared.authorizationStatus not WORKING!!!
XCODE: 15.2 IOS: 16.0.1 Following the document about how to track the current status of AuthorizationStatus seems to be not working on my current environment. https://developer.apple.com/documentation/familycontrols/authorizationcenter/authorizationstatus The user authorization is .individual Here is my sample code to identify if the status has changed after revoking the permission from the Settings > ScreenTime @ObservedObject var center = AuthorizationCenter.shared @Environment(\.dismiss) var dismiss @State private var isAlert = false var body: some View { VStack { Button { dismiss() } label: { Text("Close") } .buttonStyle(GrowingButton()) } VStack { Button { DispatchQueue.main.async { if center.authorizationStatus != .approved { Task { do { if #available(iOS 15.0, *) { if #available(iOS 16.0, *) { //let center = AuthorizationCenter.shared try await center.requestAuthorization(for: .individual) } } } } } else { self.isAlert = true } } } label: { Text("Validate Screen Time Permission") } .buttonStyle(GrowingButton()) .alert(isPresented: $isAlert, content: { switch center.authorizationStatus { case .notDetermined: Alert(title: Text("Screen Time not Determined")) case .denied: Alert(title: Text("Screen Time is Denied")) case .approved: Alert(title: Text("Screen Time is Approved")) @unknown default: Alert(title: Text("Unknown")) } }) } } } It will still fallback to the APPROVED state even if the permission was already revoked from ScreenTime settings. Highly appreciated if anybody from the community can help me figure out this thing to work. Thank you.
1
5
454
Mar ’24
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: 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?
1
0
887
Mar ’24
ScreenTime permissions revoked on app update from TestFlight or App Store
An app that uses screen time API. After asking for permission and receiving them works, everything generally work, shields applications etc.. Upon new version update (manually update from testFlight old version or App Store) I get an error message, I can then update again without any error but the permissions are revoked and I have to ask for them again. shielding stopes. This happens randomly on TestFlight or App Store and the permissions Did anyone encounter this or solved this? this seems to have started a month ago but maybe I just missed it before
1
0
520
Feb ’24
Using ScreenTime / familyControl
Hello, I want to make a simple project that simply displays the user's current daily ScreenTime. I believe you may be able to do the functionality I want with: FamilyControls or ScreenTime. I believe that you may need to pay for the paid developer account in order to access the FamilyControl framework. I am having trouble finding guidance as to how I would do this as most reddit/stackoverflow posts are incomplete with answers and I cannot find demos/code examples/tutorials/sample usage anywhere on google. I would greatly appreciate any help and guidance. If the solution requires the paid developer tier, I am fine with that. Thank you in advance
0
0
359
Feb ’24
Making App Searchable in Spotlight after Shielding
I have implemented a shielding mechanism via Family Controls to prevent unauthenticated users from deleting specific shortcuts within the Shortcuts app. While this successfully secures the app, it has an unintended consequence: the Shortcuts app no longer appears in Spotlight Search and becomes inaccessible for users subject to this shielding. I understand that this is the default behavior when implementing app shielding or time limits on specific apps. Is there a way to retain the app's visibility in Spotlight Search despite it being shielded?
0
0
431
Feb ’24
DeviceActivityMonitor Extension methods not being triggered at IOS16, but its work at IOS17
I'm writing an app that uses Family Control. Most of the functionality has already been debugged, including in the call try deviceActivityCenter.startMonitoring(activityName, during: schedule, events: [ eventName: event ]) Works fine on my IOS17 device, but on my old IOS16 device I found that it can't be called, like intervalDidStart, intervalDidEnd, eventDidReachThreshold etc can't be called. I checked some information, https://forums.developer.apple.com/forums/thread/724243 delete the Build Settings mentioned in this link, and change the ios Deployment Target to ios16, and found that it didn't work. Don't know where the problem is?
0
0
256
Feb ’24