Files
AutoTime-Tracker/ios/Runner/TimeTrackingPlugin.swift
2025-11-13 15:45:28 +08:00

155 lines
5.1 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Flutter
import UIKit
import ScreenTime
@available(iOS 14.0, *)
public class TimeTrackingPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "autotime_tracker/time_tracking",
binaryMessenger: registrar.messenger()
)
let instance = TimeTrackingPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "hasPermission":
hasPermission(result: result)
case "requestPermission":
requestPermission(result: result)
case "getAppUsage":
getAppUsage(call: call, result: result)
case "startBackgroundTracking":
startBackgroundTracking(result: result)
case "stopBackgroundTracking":
stopBackgroundTracking(result: result)
case "isBackgroundTrackingActive":
isBackgroundTrackingActive(result: result)
default:
result(FlutterMethodNotImplemented)
}
}
// MARK: - Permission Methods
private func hasPermission(result: @escaping FlutterResult) {
if #available(iOS 14.0, *) {
let authorizationStatus = STScreenTime.getAuthorizationStatus()
result(authorizationStatus == .authorized)
} else {
result(false)
}
}
private func requestPermission(result: @escaping FlutterResult) {
if #available(iOS 14.0, *) {
STScreenTime.requestAuthorization { success, error in
if let error = error {
result(FlutterError(
code: "AUTHORIZATION_FAILED",
message: error.localizedDescription,
details: nil
))
} else {
result(success)
}
}
} else {
result(FlutterError(
code: "UNSUPPORTED_VERSION",
message: "Screen Time API requires iOS 14.0 or later",
details: nil
))
}
}
// MARK: - App Usage Methods
@available(iOS 14.0, *)
private func getAppUsage(call: FlutterMethodCall, result: @escaping FlutterResult) {
guard let args = call.arguments as? [String: Any],
let startTimeMs = args["startTime"] as? Int64,
let endTimeMs = args["endTime"] as? Int64 else {
result(FlutterError(
code: "INVALID_ARGUMENTS",
message: "Invalid arguments",
details: nil
))
return
}
let startTime = Date(timeIntervalSince1970: Double(startTimeMs) / 1000.0)
let endTime = Date(timeIntervalSince1970: Double(endTimeMs) / 1000.0)
//
guard STScreenTime.getAuthorizationStatus() == .authorized else {
result(FlutterError(
code: "PERMISSION_DENIED",
message: "Screen Time permission not granted",
details: nil
))
return
}
// 使
STScreenTime.getAppUsage(from: startTime, to: endTime) { usage, error in
if let error = error {
result(FlutterError(
code: "GET_USAGE_FAILED",
message: error.localizedDescription,
details: nil
))
return
}
guard let usage = usage else {
result([])
return
}
// Flutter
var appUsageList: [[String: Any]] = []
// 使
// Screen Time API 使
// API
//
for (bundleId, timeInterval) in usage {
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? bundleId
appUsageList.append([
"packageName": bundleId,
"appName": appName,
"startTime": startTime.timeIntervalSince1970 * 1000,
"endTime": endTime.timeIntervalSince1970 * 1000,
"duration": Int(timeInterval),
"deviceUnlockCount": 0
])
}
result(appUsageList)
}
}
// MARK: - Background Tracking Methods
private func startBackgroundTracking(result: @escaping FlutterResult) {
// iOS
// iOS
// 使 Background Tasks Notification Service Extension
result(true)
}
private func stopBackgroundTracking(result: @escaping FlutterResult) {
result(true)
}
private func isBackgroundTrackingActive(result: @escaping FlutterResult) {
result(false)
}
}