Device Activity

RSS for tag

Monitor web and app usage through custom time windows and events.

Posts under Device Activity tag

90 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

DeviceActivityMonitor Extension not working
I am developing a project with the Screen Time API, and I cannot understand why the methods inside DeviceActivityMonitor extension are not being called. Some points to note: I do start by requesting authorization from the User (this is working as expected when opening the app) Both the DeviceActivityMonitor Extension and the main app are under the same App Group I have added Family Controls capability to both targets and have the developer account to use it. I start by calling center.startMonitoring() I have overridden the original methods. Yet, when startMonitoring is called, there is no action that is supposed to be taken that is being taken, and as far as I can tell, the methods aren't even being called. Here are some relevant snippets of code: // EXT class DeviceActivityMonitorExtension: DeviceActivityMonitor { override func intervalDidStart(for activity: DeviceActivityName) { super.intervalDidStart(for: activity) let store = ManagedSettingsStore(named: .daily) } override func intervalDidEnd(for activity: DeviceActivityName) { super.intervalDidEnd(for: activity) let store = ManagedSettingsStore(named: .daily) store.clearAllSettings() } override func eventDidReachThreshold(_ event: DeviceActivityEvent.Name, activity: DeviceActivityName) { super.eventDidReachThreshold(event, activity: activity) let store = ManagedSettingsStore(named: .daily) let model = BeeFreeModel.shared let applications = model.selectionToDiscourage.applicationTokens let categories = model.selectionToDiscourage.categoryTokens let webDomains = model.selectionToDiscourage.webDomainTokens store.shield.applications = applications.isEmpty ? nil : applications store.shield.applicationCategories = categories.isEmpty ? nil : ShieldSettings.ActivityCategoryPolicy.specific(categories) store.shield.webDomains = webDomains.isEmpty ? nil : webDomains } } // APP extension DeviceActivityName { static let daily = Self("daily") } extension DeviceActivityEvent.Name { static let discouraged = Self("discouraged") } let schedule = DeviceActivitySchedule( intervalStart: DateComponents(hour: 0, minute: 0, second: 0), intervalEnd: DateComponents(hour: 23, minute: 59, second: 59), repeats: true ) class BeeFreeSchedule { static public func setSchedule() { print("Setting schedule...") print("Hour is: ", Calendar.current.dateComponents([.hour, .minute], from: Date()).hour!) let events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [ .discouraged: DeviceActivityEvent( applications: BeeFreeModel.shared.selectionToDiscourage.applicationTokens, categories: BeeFreeModel.shared.selectionToDiscourage.categoryTokens, webDomains: BeeFreeModel.shared.selectionToDiscourage.webDomainTokens, threshold: BeeFreeModel.shared.thresholdToDiscourage ) ] let center = DeviceActivityCenter() do { print("Try to start monitoring...") // Call startMonitoring with the activity name, schedule, and events try center.startMonitoring(.daily, during: schedule, events: events) } catch { print("Error monitoring schedule: ", error) } } } // APP class BeeFreeModel: ObservableObject { // Import ManagedSettings to get access to the application shield restriction let store = ManagedSettingsStore() //@EnvironmentObject var store: ManagedSettingsStore @Published var selectionToDiscourage: FamilyActivitySelection @Published var thresholdToDiscourage: DateComponents @Published var setOfApps: [String] init() { selectionToDiscourage = FamilyActivitySelection() thresholdToDiscourage = DateComponents() var setOfAppIdentifiers: Set<String?> = Set<String?>() setOfApps = [String]() if selectionToDiscourage.applicationTokens.isEmpty {} else { for application in BeeFreeModel.shared.selectionToDiscourage.applications { setOfAppIdentifiers.insert(application.localizedDisplayName) setOfApps = setOfAppIdentifiers.compactMap { $0 }.sorted() } } } class var shared: BeeFreeModel { return _BeeFreeModel } func setSelection() { let applications = BeeFreeModel.shared.selectionToDiscourage } func changeThreshold(threshold: DateComponents) { thresholdToDiscourage = threshold } } // APP /// ... Button("Select Apps to Discourage") { isDiscouragedPresented = true } .familyActivityPicker(isPresented: $isDiscouragedPresented, selection: $model.selectionToDiscourage) } .onChange(of: model.selectionToDiscourage) { BeeFreeModel.shared.setSelection() } // ... // ... Button("Save Time") { saveTime() let new_threshold = DateComponents(hour: savedTime?.hours, minute: savedTime?.minutes, second: savedTime?.seconds) model.changeThreshold(threshold: new_threshold) } } .onChange(of: model.thresholdToDiscourage) { BeeFreeSchedule.setSchedule() // ... I believe I am using the latest stable version of Xcode (recently deleted and reinstalled). I'm really new to mobile development to Swift so any help is greatly appreciated. Thank you! :)
5
1
566
Feb ’24
Shield Configuration Extension sometimes doesn't update on app switcher
Sometimes the app switcher doesn't show the correct shield configuration if there is like 7 or more apps in the app switcher. if I clear all apps from app switcher cache and leave 4 apps, the correct shield configuration will show every time instantly when I change the shield configuration from my parent app and go back to the app switcher; but if there is like 7 or more apps in the app switcher, I can see some of the app's shield configurations don't update instantly and I have to scroll past the app in the app switcher and go back to for it to update to the correct shield if it does at all. This is misleading to users and in the case of my app detrimental to one of its core functionalities override func configuration(shielding application: Application) -> ShieldConfiguration { let sharedUserDefaults = UserDefaults(suiteName: SharedUserDefaults.suiteName.rawValue)! let isPaidOn = sharedUserDefaults.bool(forKey: SharedUserDefaults.paidSwitchKey.rawValue) if isPaidOn == true { return ShieldConfig.paid } else { return ShieldConfig.free } }
0
0
359
Feb ’24
[iOS 17.4] Default value for DeviceActivityEvent's includesPastActivity should be set to true
Starting with iOS 17.4, the DeviceActivityEvent initializer includes a new parameter named includesPastActivity.

The default value for this parameter is set to false, whereas device activity events have behaved as though this parameter were set to true up until now. This breaking change is a MAJOR ISSUE for developers who used device activity events in their apps before iOS 17.4 because their apps might not work the way they intended after the update. They'll have to release new app versions that specifically set includesPastActivityto true. In my opinion, the default value for includesPastActivity should be true to avoid disrupting events scheduled on older versions of iOS. I have filed an enhancement report (FB13573556) about this. I really hope this is changed before the official iOS 17.4 release.
3
4
907
Mar ’24
App with DeviceActivityReport extension either won't install on device or won't upload to TestFlight
We have integrated DeviceActivityReport to our Family Controll app. All capabilities are added. We built the app and tested it, but when we want to upload to TestFlight the following error happened (see attached image) When we are adding NSExtensionMainStoryboard or NSExtensionPrincipalClass the following error appears during installation process. DeviceReport.appex with id com.example.example.DeviceReport defines either an NSExtensionMainStoryboard or NSExtensionPrincipalClass key, which is not allowed for the extension point com.apple.deviceactivityui.report-extension
1
0
394
Jan ’24
Device Activity Monitor Extension Sometimes Fails To Launch
The device activity monitor extension sometimes fails to launch when a schedule starts/ends or when an event threshold is reached. This issue may persist for several minutes or hours once it begins. Currently, the only known workarounds are: Restarting the phone. Waiting for an indeterminate period, ranging from a few minutes to hours, after which the device activity extension may or may not launch. I've filed a new bug report (FB13556935), which includes a sysdiagnose and precise timestamps of when the issue was reproduced. By looking at the errors, it appears the system is failing to launch the extension because it's looking at an invalid path: Service could not initialize: access(/private/var/containers/Bundle/Application/C6598B47-8977-447C-870B-4D21BDE8ACF9/Jomo.app/PlugIns/JomoDeviceActivityMonitor.appex/JomoDeviceActivityMonitor, X_OK) failed with errno 2 - No such file or directory, error 0x6f - Invalid or missing Program/ProgramArguments [u 8104FF60-5C49-45BD-8AFB-97BE88488134:m (null)] [()] Failed to start plugin; pkd returned an error: Error Domain=PlugInKit Code=4 "RBSLaunchRequest error trying to launch plugin com.jomo.Jomo.JomoDeviceActivityMonitor(8104FF60-5C49-45BD-8AFB-97BE88488134): Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x5dd8273e0 {Error Domain=NSPOSIXErrorDomain Code=111 "Unknown error: 111" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}" UserInfo={NSLocalizedDescription=RBSLaunchRequest error trying to launch plugin com.jomo.Jomo.JomoDeviceActivityMonitor(8104FF60-5C49-45BD-8AFB-97BE88488134): Error Domain=RBSRequestErrorDomain Code=5 "Launch failed." UserInfo={NSLocalizedFailureReason=Launch failed., NSUnderlyingError=0x5dd8273e0 {Error Domain=NSPOSIXErrorDomain Code=111 "Unknown error: 111" UserInfo={NSLocalizedDescription=Launchd job spawn failed}}}} This bug is CRITICAL for all apps relying on the Device Activity framework. It likely explains a range of issues reported since the framework's release. Specifically, due to this bug, end users may encounter problems such as apps not unblocking at the end of a schedule, apps not blocking at the start of a schedule, and time limits not being updated, among others.
6
3
837
3d
Screen Time API Access
Having tried to gain access to the total daily screen time API using the text/code from the below thread, we were unable to get any data access. Has anyone else had the same issue and any resolutions? Not looking for application limits, just statistics to inform user through our 3rd party application. Thanks for any guidance around areas we can attempt https://developer.apple.com/documentation/deviceactivity/deviceactivitydata/activitysegment
0
0
349
Jan ’24
Providing Pre-Selections to FamilyActivityPicker?
I am able to correctly select and store the tokens of apps and categories my users will block, but I am unable to pre-populate Picker whenever the app is rebooted with previously selected and stored tokens. Below is the selection variable I am passing to the picker... var selectionsToBlock = FamilyActivitySelection() { willSet { saveSelection(selection: newValue) blockersSelected = true } } Is there any way I can provide my existing blockers (shown below) so that the user can easily edit their list of restricted apps from the Picker? func savedBlockers() -> FamilyActivitySelection? { let defaults = UserDefaults.standard guard let data = defaults.data(forKey: userDefaultsKey) else { return nil } return try? decoder.decode( FamilyActivitySelection.self, from: data ) }
2
0
487
Feb ’24
App Usage
I'm developing a mental wellness app, and I need to get user's screentime and app usage data and send it to my flask backend for analytics. Is it possible on iphone right now? I've looked into ScreenTime and DeviceActivity frameworks, but they're really poor in terms of examples and documentation, so I'm not sure if this is actually possible or not.
0
1
320
Dec ’23
UserDefaults and @AppStorage causing DeviceActivityMonitor to crash on iOS 17
I use App Groups to share UserDefaults data between my host app and DeviceActivityMonitor extension. On iOS 17, it appears that reading @AppStorage variables are causing my DeviceActivityMonitor extension callback functions to crash. Weirdly, writing values is okay. I see this in the extension logs: Couldn't read values in CFPrefsPlistSource<0x10fe251d0> (Domain: GROUP_NAME, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd However, through searching this log message on the internet and the fact that it also appears in my host app logs without crashing, this seems to be a warning - possibly indicating an issue but also a possible red herring. But the fact remains that when I don't read UserDefaults values or variables decorated with @AppStorage in the DeviceActivityMonitor extension, everything works fine. Are UserDefaults, and specifically @AppStorage decorators supported in the DeviceActivityMonitor extension?
1
1
791
Dec ’23
Activity log app on iPhone?
Hey. Is there any app that shows a precise activity log? When I was using Android I had an app Quality Time which keeps the track of what are you doing minute by minute. It has a log which shows 13:24 PM Open Facebook, 13:45 Open Instagram etc. Is there any app on iPhone that tracks your activity like this and stores it into a log or something? I need an app like this or something similar Thank you.
0
0
553
Dec ’23
Please help make DeviceActivityReport reliably show up
Our app uses DeviceActivityReport to display the user’s screen time. The performance of DeviceActivityReport is often very poor. These issue occur commonly: Screen time is reported as 0 minutes DeviceActivityReport View appears completely blank The host app loses connection with the DeviceActivityReport altogether I have implemented several workarounds which only slightly improve the performance, to varying degrees depending on the device iOS: Inside the DeviceActivityReport code - retry fetching screen time data until it returns a non-zero result Implement a “refresh” button which reloads the DeviceActivityReport view from the host app However, due to the sandboxed nature of DeviceActivityReport, there is no way for the host application to tell if the DeviceActivityReport extension is experiencing these performance issues. It results in a really bad user experience. I am building the app with Xcode 14 due to another issue where DeviceActivityReport fails to load for all iOS 16 devices when built with Xcode 15 (this is a know issue, here’s a link to a discussion on the developer forums: https://developer.apple.com/forums/thread/735915). However, when testing on iOS 17 devices with Xcode 15 builds, the above issues still occur. I have received no crash reports from DeviceActivityReport. These issues are known bugs and have been discussed on the developer forums, but I haven't yet seen a solution. Other screen time apps exist that use the DeviceActivityReport seemingly flawlessly, so I know that there is a way to improve the performance of DeviceActivityReport in my app. Please help! I have been dealing with this poor performance for a long time now with almost no improvement!
3
2
769
Apr ’24
DeviceActivityMonitor unreliable with iOS 17 - any other ways to schedule tasks?
We have an app that uses the Screen Time APIs to block certain apps set by the user on a schedule: We use ManagedSettings to shield selected apps We use DeviceActivityMonitor to shield the apps automatically on a schedule set by the user. The shielding starts during the intervalDidStart callback function and ends during the intervalDidEnd callback function We are getting reports from the majority of our iOS 17 users that the app blocking schedules no longer work on iOS 17. We have tested this on our own iOS 17 devices and reproduced the behavior. But the feature still works consistently on iOS 16 devices. The app is still built using Xcode 14 instead of Xcode 15 due to another issue - the DeviceActivityReport is blank for all iOS 16 users when built in Xcode 15 (link to issue on the developer forums: https://developer.apple.com/forums/thread/735915). When testing with Xcode 15 builds, the bug appears to improve - however it still occurs intermittently. Are there any other mechanisms to run tasks on repeating schedules? For this specific feature, we don't need to eventDidReachThreshold callbacks, which is the main purpose of DeviceActivityMonitor. So we really don't need any Device Activity integration at all, just setting and disabling ManagedSettings shields at certain times. Would love if anyone could suggest and alternative to DeviceActivityMonitor.
1
0
667
Dec ’23
AuthorizationCenter.shared times out and makes my ScreenTime App Unusable
Any way that I try requesting authorization for family controls is incredibly inconsistent. The line of code that hangs is **let center = AuthorizationCenter.shared ** I've looked at other posts and I saw someone recommended declaring let center = AuthorizationCenter.shared outside the main thread and somehow get the status on the main thread. I've tried that approach with no success. I've scoured GitHub to see how other people approach the request but it's all pretty similar. The following code sometimes works great for a few minutes and then I rebuild and run and it hangs on AuthorizationCenter.shared.requestAuthorization(for: FamilyControlsMember.individual). Would love any suggestions!!! .onAppear { Task { do { print("try requestAuthorization") try await AuthorizationCenter.shared.requestAuthorization(for: FamilyControlsMember.individual) print("requestAuthorization success") switch AuthorizationCenter.shared.authorizationStatus { case .notDetermined: print("not determined") case .denied: print("denied") case .approved: print("approved") @unknown default: break } } catch { print("Error requestAuthorization: ", error) } } }
0
0
434
Dec ’23
Device Activity Report View Size and Background
Hello! I am a new developer and am attempting to use Apple's Device Activity API. However, I am struggling with the View of the Device Activity Report. For one, the view stretches to fill all available space instead of simply being the size of its content. Secondly, the background color seems fixed and I can't figure out how to remove it. The Screen Time API demo video shows this Device Activity API used with a clear background, so I know it is possible, I just can't figure out how to do it as it seems to be built into the Device Activity Report itself. Does anyone have any ideas? I'll attach a photo to show you what I mean. The black box is the Device Activity Report that I am trying to edit. Thank you for your help!
6
1
639
Dec ’23
Screen Time Api
Hi Folks, How to sheild or lock the apps in childs phone from the Guardians Phone. I got the opaque tokens from childs phone , but on the parents device there are only categories options but not the applications. so how to get the applications in parentsl device . when i try to authorisee the family controls with .individual option there are not the applications in family activity picker but only the categories and others. Thanks in advance
0
0
299
Nov ’23
HELP ScreenTime API DeviceAcivityReport continious issues
Hi everyone, I've been spending my evenings on the app for around 6 months that's using Screen Time API introduced in WWDC 21 (https://developer.apple.com/videos/play/wwdc2021/10123/), I'm having many issues with this API and looking for anyone who has experience with this API, I will appreciate any help or advice I can get! I'm using DeviceActivityReport to display the dashboard with screen time usage and certain metrics. Device activity report extension runs in an isolated sandbox, which makes it harder to debug and can't make any network call or write to any storage, for privacy purposes which makes sense, but makes it very hard for development. The issue is that the process where DeviceActivityReport is running crashes for no reason frequently or doesn't run at all. The API itself has many bugs, which is backed up by my experience, Opal app developers and Screen Time even made the news with its bugs. I see the same behaviour with other apps like Opal, but they can workaround somehow it and reload the report. I'm experienced with UIKit but have little experience with SwiftUI, since ScreenTime API is using SwiftUI only I have to embed DeviceActivityReport in UIKit using UIHostingController and then inside of the device activity report extension target I'm using UIViewControllerRepresentable to embed UIKit into SwiftUI. But I've done some testing and the behaviour is the same when using pure SwiftUI, although there might be fewer hiccups, I couldn't rewrite the whole app. That's the gist, there's too much code to include, but I can drop more code snippets if there's anyone who has experience with this API who can help me.
2
1
643
Nov ’23
Multiple Days Schedules • Screen Time API
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?
4
0
831
May ’24
Device Activity Report incorrect date intervals
Hey, I am experiencing this bug where I ask the device activity report for data within a date range, in daily segments. the device report receives the truncated date range: some date 23:00 -> some other date 23:00. however the async data list returns date ranges of the sort: 22:00 -> 22:00 (of the next day). and sometimes it returns 22:00 -> 23:00 (of the same day), but then the data contained in that range is still relative to tne entire day since the total screen time is greater than an hour. I think that the way date intervals are treated by the device activity report extension contains bugs and is not consistent. Is anyone experiencing similar bugs?
0
0
289
Nov ’23
DeviceActivityMonitor - eventDidReachThreshold Callback Not Triggering Properly
Hello, I'm currently experiencing an issue with the DeviceActivityMonitor extension in my code, specifically with the eventDidReachThreshold callback. I'm hoping to get some insights into why this problem occurs and how to resolve it. Problem: Issue 1: The eventDidReachThreshold callback is not triggering as expected. It appears that the callback is not being invoked when the threshold is reached. Issue 2: After a few seconds, the eventDidReachThreshold callback starts to trigger multiple times. This unexpected behavior is causing problems in my code, as it results in incorrect actions being taken. Issue 3: There are instances where the eventDidReachThreshold callback provides an incorrect event name. iOS version: iOS16.7.2 and iOS17.1.1 Here is my code to start the monitoring: func startMonitoring() { var startTime : DateComponents = DateComponents(hour: 0, minute: 0) let endTime : DateComponents = DateComponents(hour: 23, minute: 59) /// Creates the schedule for the activity, specifying the start and end times, and setting it to repeat. let schedule = DeviceActivitySchedule(intervalStart: startTime, intervalEnd: endTime, repeats: true, warningTime: nil) /// Defines the event that should trigger the encouragement. let event = DeviceActivityEvent(applications: socialActivitySelection.applicationTokens, categories: socialActivitySelection.categoryTokens, webDomains: socialActivitySelection.webDomainTokens, threshold: DateComponents(minute: 2)) let events: [DeviceActivityEvent.Name: DeviceActivityEvent] = [.socialScreenTimeEvent : event] do { activityCenter.stopMonitoring([.socialScreenTime]) /// Tries to start monitoring the activity using the specified schedule and events. try activityCenter.startMonitoring(.socialScreenTime, during: schedule, events: events) } catch { /// Prints an error message if the activity could not be started. print("Could not start monitoring: \(error)") } } In addition, I should mention that, with each iteration through the eventDidReachThreshold callback, I increment the threshold by 2 minutes and restart the monitoring. If there are any known workarounds or potential solutions, please share them. Thank you.
1
0
608
Dec ’23