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

技术咨询:如何统计设备解锁次数及单次解锁会话时长?

统计设备解锁次数与会话时长的可行技术方案

移动平台(Android/iOS)

Android

  • 核心实现逻辑:通过系统广播监听解锁与锁屏事件,记录时间戳计算会话时长并统计次数。
    • 注册ACTION_USER_PRESENT广播接收解锁通知,触发时记录当前时间作为会话开始节点;监听ACTION_SCREEN_OFF或ACTION_USER_LEAVING事件,触发时计算当前时间与开始时间的差值,得到本次会话时长,同时将解锁次数+1。
    • 用SharedPreferences或本地SQLite数据库持久化存储记录,避免数据丢失。
  • 关键代码片段:
    class UnlockReceiver : BroadcastReceiver() {
        private var sessionStartTime: Long = 0
    
        override fun onReceive(context: Context?, intent: Intent?) {
            when (intent?.action) {
                Intent.ACTION_USER_PRESENT -> {
                    sessionStartTime = System.currentTimeMillis()
                }
                Intent.ACTION_SCREEN_OFF -> {
                    val sessionDuration = System.currentTimeMillis() - sessionStartTime
                    // 保存会话时长到本地,解锁次数+1
                    updateUnlockRecord(sessionDuration)
                }
            }
        }
    
        private fun updateUnlockRecord(duration: Long) {
            // 实现本地存储逻辑(示例:SharedPreferences)
            val prefs = context?.getSharedPreferences("UnlockStats", Context.MODE_PRIVATE)
            val count = prefs?.getInt("unlock_count", 0) ?: 0
            prefs?.edit()?.putInt("unlock_count", count + 1)?.apply()
            // 存储时长记录可追加到数据库
        }
    }
    
  • 权限适配:Android 13+需申请POST_NOTIFICATIONS权限以保证后台广播接收,同时添加RECEIVE_BOOT_COMPLETED权限确保设备重启后监听仍生效。

iOS

  • 核心实现逻辑:利用应用生命周期回调监听活跃/非活跃状态,间接对应解锁与锁屏事件。
    • 在UIApplicationDelegate中,applicationDidBecomeActive(_:)方法触发时记录会话开始时间;applicationWillResignActive(_:)方法触发时(对应锁屏或切后台)计算会话时长,更新解锁次数。
    • 用UserDefaults或Core Data存储统计数据。
  • 关键代码片段:
    class AppDelegate: UIResponder, UIApplicationDelegate {
        private var sessionStartTime: TimeInterval = 0
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            sessionStartTime = Date().timeIntervalSince1970
        }
    
        func applicationWillResignActive(_ application: UIApplication) {
            let sessionDuration = Date().timeIntervalSince1970 - sessionStartTime
            // 保存时长与次数
            saveUnlockRecord(duration: sessionDuration)
        }
    
        private func saveUnlockRecord(duration: TimeInterval) {
            let defaults = UserDefaults.standard
            let count = defaults.integer(forKey: "unlock_count")
            defaults.set(count + 1, forKey: "unlock_count")
            // 时长记录可存入Core Data
        }
    }
    
  • 注意:iOS后台限制严格,若应用被系统杀死,将无法继续监听事件,需引导用户保持应用后台活跃。

桌面平台(Windows/macOS)

Windows

  • 核心实现逻辑:通过系统事件或API监听会话锁定/解锁状态。
    • 使用C#的SystemEvents.SessionSwitch事件,监听SessionSwitchReason.SessionUnlock(解锁)和SessionSwitchReason.SessionLock(锁定),记录时间差计算时长,统计次数。
    • 也可读取Windows事件日志中Event ID 4624(登录事件)来辅助验证解锁行为。
  • 关键代码片段:
    using Microsoft.Win32;
    using System;
    
    class UnlockTracker {
        private DateTime sessionStart;
    
        public UnlockTracker() {
            SystemEvents.SessionSwitch += OnSessionSwitch;
        }
    
        private void OnSessionSwitch(object sender, SessionSwitchEventArgs e) {
            if (e.Reason == SessionSwitchReason.SessionUnlock) {
                sessionStart = DateTime.Now;
            } else if (e.Reason == SessionSwitchReason.SessionLock) {
                TimeSpan sessionDuration = DateTime.Now - sessionStart;
                // 保存时长与次数
                SaveRecord(sessionDuration);
            }
        }
    
        private void SaveRecord(TimeSpan duration) {
            // 实现本地文件或数据库存储逻辑
        }
    }
    

macOS

  • 核心实现逻辑:监听NSWorkspace通知或电源管理事件。
    • 通过NSWorkspace.shared.notificationCenter监听屏幕状态变化,结合应用激活事件判断解锁;或使用IOPMLogger监听kIOPMNotificationLock与kIOPMNotificationUnlock事件。
  • 关键代码片段(Swift):
    import AppKit
    import IOKit.pwr_mgt
    
    class UnlockMonitor {
        private var sessionStartDate: Date?
        private var notificationPort: IONotificationPort?
        private var notifier: UnsafeMutableRawPointer?
    
        init() {
            registerLockNotifications()
        }
    
        private func registerLockNotifications() {
            let dict = [kIOPMNotificationTypeKey: kIOPMNotificationLock] as CFDictionary
            notificationPort = IONotificationPortCreate(kIOMainPortDefault)
            IONotificationPortSetDispatchQueue(notificationPort!, DispatchQueue.main)
            notifier = IOPMLoggerRegisterForSystemPowerNotifications(notificationPort!, { _, _ in
                // 锁屏时计算时长
                if let start = self.sessionStartDate {
                    let duration = Date().timeIntervalSince(start)
                    self.saveRecord(duration: duration)
                    self.sessionStartDate = nil
                }
            }, dict)
    
            // 监听解锁事件(结合应用激活)
            NotificationCenter.default.addObserver(
                self,
                selector: #selector(handleAppActivate),
                name: NSWorkspace.didActivateApplicationNotification,
                object: nil
            )
        }
    
        @objc private func handleAppActivate(_ notification: Notification) {
            if !NSWorkspace.shared.isScreenLocked {
                sessionStartDate = Date()
            }
        }
    
        private func saveRecord(duration: TimeInterval) {
            // 实现存储逻辑
        }
    }
    

通用注意事项

  • 隐私合规:所有统计行为必须明确告知用户并获得授权,严格遵守GDPR、CCPA等隐私法规,不得收集无关敏感数据。
  • 数据可靠性:处理设备重启、应用崩溃等异常场景,可定期备份统计数据到本地文件或加密存储。
  • 跨版本适配:不同系统版本的API可能存在差异,需针对目标版本做兼容性处理。

内容的提问来源于stack exchange,提问作者Vasant Raval

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:55:29