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

Swift屏幕时间应用:Firebase同步数据至问责伙伴的可行性与实现

方案可行性与实现指南

一、方案可行性

完全可行。Apple的屏幕时间权限允许获取总屏幕使用时长(无需应用细分数据),只要用户授予对应权限即可,不会触发额外隐私限制——你仅请求汇总时长,未涉及应用级细分数据,符合Apple隐私规范。

二、具体实现步骤

1. 申请屏幕时间权限

  • 在Info.plist中添加NSScreenTimeUsageDescription键,填写明确的权限用途(例如"为让你的问责伙伴查看总屏幕使用时长")。
  • 使用ScreenTime框架发起授权请求:
    import ScreenTime
    
    STAuthorizationCenter.shared.requestAuthorization { status in
        switch status {
        case .authorized:
            // 授权成功,可获取屏幕时间数据
        case .denied, .restricted:
            // 处理授权失败逻辑,提示用户开启权限
        @unknown default:
            break
        }
    }
    

2. 获取总屏幕时间

通过STActivitySummary查询指定时间段的总活跃时长(以当天为例):

func getTotalScreenTime() -> TimeInterval? {
    guard STAuthorizationCenter.shared.authorizationStatus == .authorized else { return nil }
    
    let calendar = Calendar.current
    let startOfDay = calendar.startOfDay(for: Date())
    let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)!
    
    do {
        let summaries = try STActivitySummary.queryActivitySummaries(startDate: startOfDay, endDate: endOfDay)
        guard let summary = summaries.first else { return nil }
        // totalActiveTime 为总活跃时长(单位:秒)
        return summary.totalActiveTime
    } catch {
        print("获取屏幕时间失败: \(error.localizedDescription)")
        return nil
    }
}

3. 向下取整到最近0.5小时并控制更新逻辑

实现取整函数,仅当取整后数值变化时触发后续更新:

// 存储上次上报的取整值,避免重复同步
private var lastReportedValue: Double?

func formatAndCheckUpdate(_ totalSeconds: TimeInterval) -> String? {
    let totalHours = totalSeconds / 3600
    // 向下取整到最近0.5小时:1.716小时→1.5,2.166小时→2.0
    let roundedHours = floor(totalHours * 2) / 2
    
    // 仅当数值变化时返回格式化结果,否则返回nil跳过更新
    guard roundedHours != lastReportedValue else { return nil }
    lastReportedValue = roundedHours
    
    return "\(roundedHours)小时+"
}

4. 同步数据到Firebase实时数据库

  • 确保用户已通过Firebase Auth完成登录,获取唯一用户ID。
  • 当取整后数值变化时,将数据写入指定节点:
import FirebaseDatabase

func syncToFirebase(formattedTime: String) {
    guard let userId = Auth.auth().currentUser?.uid else { return }
    
    let targetRef = Database.database().reference().child("users").child(userId).child("accountability")
    targetRef.setValue(["totalScreenTime": formattedTime]) { error, _ in
        if let error = error {
            print("同步数据失败: \(error.localizedDescription)")
        }
    }
}

5. 问责伙伴获取数据

  • 用户需主动将自己的userId共享给问责伙伴(可通过邀请码、通讯录匹配等方式)。
  • 伙伴通过对方userId读取对应数据:
func fetchPartnerScreenTime(partnerUserId: String, completion: @escaping (String?) -> Void) {
    let targetRef = Database.database().reference().child("users").child(partnerUserId).child("accountability")
    targetRef.observeSingleEvent(of: .value) { snapshot in
        guard let dataDict = snapshot.value as? [String: String],
              let screenTime = dataDict["totalScreenTime"] else {
            completion(nil)
            return
        }
        completion(screenTime)
    }
}

三、注意事项

  • 隐私合规:必须明确告知用户数据仅共享给其指定的问责伙伴,且仅包含总屏幕时长,无应用细分信息。
  • 权限失效处理:若用户后续撤销屏幕时间权限,需提示用户重新授权,并暂停数据同步。
  • Firebase权限配置:需设置数据库规则,确保只有用户本人及授权伙伴能读取对应数据(例如在用户节点下存储伙伴ID列表,规则中校验访问者身份)。

内容的提问来源于stack exchange,提问作者Aishah Hamman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 22:54:53