Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Device Activity Report Not showing any information

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)
}}}

Picture of said no data from extension.

Happy to send someone a coffee if they can help!

Two coffees. Or two beers!

Device Activity Report Not showing any information
 
 
Q