iOS app如何读取其他app的使用时间

在iOS平台中,要实现读取设备上其他App的使用时间,核心依赖于 Screen Time API(也称为 DeviceActivity API),该API是苹果从iOS 12开始推出的,用于支持屏幕使用时间相关功能的开发,仅能在iOS 12及以上版本中使用。本文将详细讲解完整的实现流程、权限配置与核心代码编写。

一、前置条件与核心限制

注意:Screen Time API 是系统级API,仅能获取设备上已安装App的「使用时长」「启动次数」「前台运行时间」等公开数据,无法获取App内的具体操作、内容等隐私信息,苹果对用户隐私保护有严格限制。

二、步骤1:配置项目权限

要使用Screen Time API,首先需要在Xcode项目中配置相关权限,告知用户App将获取屏幕使用时间数据。

  1. 打开Xcode项目,选中项目目标(Target),切换到「Info」标签页
  2. 在「Custom iOS Target Properties」中,添加新的键值对:
  3. 导入Screen Time相关框架,在需要使用的文件头部添加导入语句:
// 导入Screen Time框架
import ScreenTime
import DeviceActivity

三、步骤2:申请用户Screen Time权限

在App首次启动或需要使用该功能时,向用户申请Screen Time权限,只有获得授权后,才能读取其他App的使用数据。

// 初始化Screen Time授权管理器
let center = DASharedApplicationCenter.shared

// 申请授权
func requestScreenTimePermission() {
    center.requestAuthorization { (granted, error) in
        DispatchQueue.main.async {
            if granted {
                // 用户授权成功,可开始读取App使用数据
                print("Screen Time 授权成功")
                self.loadOtherAppUsageData()
            } else {
                // 用户拒绝授权,提示用户前往设置开启
                print("Screen Time 授权失败:\(error?.localizedDescription ?? "未知错误")")
                self.showPermissionTips()
            }
        }
    }
}

// 提示用户前往设置开启权限
func showPermissionTips() {
    let alert = UIAlertController(title: "权限申请失败", message: "请前往「设置」→「屏幕使用时间」→「内容与隐私访问限制」→「允许App」中开启本App的权限", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "知道了", style: .default))
    UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true)
}

四、步骤3:读取其他App的使用时间数据

授权成功后,可通过 DAApplicationUsage 类获取指定时间范围内的其他App使用数据,包括使用时长、启动次数等。

3.1 定义数据模型(存储App使用信息)

// App使用信息模型
struct AppUsageModel {
    let appName: String?  // App名称
    let bundleId: String  // App唯一标识(Bundle ID)
    let usageTime: TimeInterval  // 使用时长(秒)
    let launchCount: Int  // 启动次数
}

3.2 核心读取方法

// 加载其他App的使用时间数据(近24小时)
func loadOtherAppUsageData() {
    // 定义时间范围:近24小时
    let endDate = Date()
    let startDate = Calendar.current.date(byAdding: .day, value: -1, to: endDate)!
    
    // 获取App使用数据
    DAApplicationUsage.fetchUsage(from: startDate, to: endDate) { (usageRecords, error) in
        DispatchQueue.main.async {
            guard let records = usageRecords, error == nil else {
                print("读取App使用数据失败:\(error?.localizedDescription ?? "未知错误")")
                return
            }
            
            // 转换为自定义模型(过滤当前App自身数据)
            let currentBundleId = Bundle.main.bundleIdentifier!
            var appUsageList: [AppUsageModel] = []
            
            for record in records {
                // 过滤当前App,只读取其他App的数据
                guard record.bundleIdentifier != currentBundleId else {
                    continue
                }
                
                let appUsage = AppUsageModel(
                    appName: record.applicationName,
                    bundleId: record.bundleIdentifier,
                    usageTime: record.totalUsageTime,
                    launchCount: record.launchCount
                )
                appUsageList.append(appUsage)
            }
            
            // 处理读取到的其他App使用数据(展示、统计等)
            self.handleAppUsageList(appUsageList)
        }
    }
}

// 处理读取到的App使用数据
func handleAppUsageList(_ list: [AppUsageModel]) {
    for app in list {
        let usageHours = String(format: "%.2f", app.usageTime / 3600)
        print("App名称:\(app.appName ?? "未知App")")
        print("Bundle ID:\(app.bundleId)")
        print("使用时长:\(usageHours) 小时")
        print("启动次数:\(app.launchCount) 次")
        print("————————————————")
    }
}

五、步骤4:数据解析与展示说明

六、常见问题与解决方案

返回主页