You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 16中使用Family Control框架获取应用每日屏幕时长遇问题求解答

iOS 16 Family Control框架获取应用每日屏幕时长失败的问题分析

你的代码目前只完成了启动设备活动监控的基础步骤,但没有实现核心的应用使用数据查询逻辑,同时存在几处关键错误:


核心问题点

  • 监控名称不匹配:启动监控时用的是.daily系统预设名称,但查询调度时却用了自定义的DeviceActivityName(rawValue: "Event"),导致无法找到对应的监控任务
  • 缺少数据查询逻辑:DeviceActivityCenter启动监控后不会主动返回数据,必须调用queryActivityHistory方法来拉取指定时间段内的应用使用记录
  • 未配置必要权限:Family Control功能需要在Info.plist中添加NSFamilyUsageDescription权限描述,否则会被系统拒绝访问数据

修正后的代码示例

1. 正确启动监控

// 定义统一的活动标识,避免名称不匹配
let dailyUsageActivity = DeviceActivityName(rawValue: "DailyAppUsage")

// 创建覆盖全天的调度规则
let dailySchedule = DeviceActivitySchedule(
    intervalStart: DateComponents(hour: 0, minute: 0),
    intervalEnd: DateComponents(hour: 23, minute: 59),
    repeats: true,
    warningTime: nil
)

let activityCenter = DeviceActivityCenter()

do {
    // 使用统一的活动名称启动监控
    try activityCenter.startMonitoring(dailyUsageActivity, during: dailySchedule)
    
    // 验证监控是否启动成功
    if let activeSchedule = activityCenter.schedule(for: dailyUsageActivity) {
        print("每日应用使用监控已启动:\(activeSchedule)")
    }
} catch {
    print("监控启动失败:\(error.localizedDescription)")
}

// 你的其他限制配置代码可以保留
// store.dateAndTime.requireAutomaticDateAndTime = true
// ... 其余配置代码

2. 添加应用使用时长查询逻辑

在需要获取数据的时机(比如用户点击查询按钮、应用前台激活时)调用以下代码:

let calendar = Calendar.current
let todayStart = calendar.startOfDay(for: Date())
let todayEnd = calendar.date(byAdding: .day, value: 1, to: todayStart)!

activityCenter.queryActivityHistory(from: todayStart, to: todayEnd) { activitySegments, error in
    guard let segments = activitySegments, error == nil else {
        print("查询应用使用数据失败:\(error?.localizedDescription ?? "未知错误")")
        return
    }
    
    // 遍历所有活动分段,提取应用信息和时长
    for segment in segments {
        guard let bundleID = segment.applicationIdentifier else { continue }
        
        // 获取应用名称(可通过BundleID查询系统应用列表,注意权限限制)
        var appName = bundleID
        if let appBundle = Bundle(identifier: bundleID) {
            appName = appBundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? appBundle.object(forInfoDictionaryKey: kCFBundleNameKey as String) as? String ?? bundleID
        }
        
        print("应用名称:\(appName) | 屏幕时长:\(segment.duration)")
    }
}

额外注意事项

  • 权限配置:必须在Info.plist中添加NSFamilyUsageDescription键,值为向用户说明需要访问家庭使用数据的原因(比如"需要统计您的应用使用时长")
  • 应用身份限制:只有家庭组织者或被授权的监护人应用才能访问Family Control数据,普通应用无法获取这些信息
  • 系统版本要求:确保测试设备运行iOS 16及以上版本,Xcode版本需匹配(建议使用Xcode 14+)

内容的提问来源于stack exchange,提问作者Anupam Khandel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:50:30