You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何检测iPhone是否被使用/解锁?含后台运行场景需求

针对你遇到的「后台检测用户是否正在使用iPhone」的需求,结合iOS的合规要求和现有API限制,我给你梳理下可行的思路和方案:

先聊聊你提到的现有方案的局限

  • applicationProtectedDataWillBecomeUnavailable/applicationProtectedDataDidBecomeAvailable:确实只有设备设置了锁屏密码时才会触发回调,无密码设备完全不会响应,覆盖范围有限,没法满足全场景需求。
  • Darwin锁屏/解锁通知:这类属于私有API范畴,Apple的审核系统会直接识别并拒绝你的App,绝对不能用于上线产品。
  • 距离传感器通知(UIDeviceProximityStateDidChangeNotification:它只能检测是否有物体靠近听筒,和“用户正在使用设备”的关联度极低,而且后台状态下系统会限制传感器的触发频率,精度完全不够。

合规可行的替代方案

方案1:利用App前后台状态通知(基础场景适配)

如果你的需求是判断用户是否切换到你的App使用,可以通过监听系统提供的App活跃/非活跃通知来实现,虽然没法检测用户解锁设备但未打开你的App的情况,但属于完全合规的基础方案。

代码示例:

// 在AppDelegate或SceneDelegate中注册通知
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    NotificationCenter.default.addObserver(self, selector: #selector(onAppBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(onAppResignActive), name: UIApplication.willResignActiveNotification, object: nil)
    return true
}

@objc private func onAppBecomeActive() {
    // 用户正在使用你的App,设备处于活跃状态
    print("用户正在使用iPhone,当前App已激活")
}

@objc private func onAppResignActive() {
    // 用户离开你的App,设备可能锁屏或切换到其他应用
    print("用户停止使用当前App,设备进入非活跃状态")
}

方案2:iOS 16+ 用DeviceActivityMonitor(精准合规首选)

iOS 16之后Apple推出了DeviceActivityMonitor框架,专门用于监控设备的使用状态(包括锁屏、解锁、App使用时长等),属于官方合规API,能通过App Store审核,是目前后台检测设备活跃状态的最优解。不过需要用户授权「屏幕使用时间」权限,且需遵守后台运行限制。

实现步骤:

  1. Info.plist中添加NSFamilyUsageDescription,说明申请屏幕使用时间权限的原因(比如“为了提供个性化的使用提醒服务”);
  2. 实现监控逻辑:
import DeviceActivity

class DeviceUsageMonitor: NSObject, DeviceActivityMonitorDelegate {
    private let monitor = DeviceActivityMonitor()
    
    override init() {
        super.init()
        monitor.delegate = self
    }
    
    func requestAuthorization() {
        DeviceActivityAuthorizationCenter.shared.requestAuthorization { [weak self] status in
            guard let self = self, status == .granted else { return }
            // 配置监控时间段(这里设置为全天监控)
            let dailySchedule = DeviceActivitySchedule(
                intervalStart: DateComponents(hour: 0),
                intervalEnd: DateComponents(hour: 23, minute: 59),
                repeats: true
            )
            // 开始监控
            try? self.monitor.startMonitoring(dailySchedule)
        }
    }
    
    // 设备进入活跃状态(解锁后开始使用)
    func monitor(_ monitor: DeviceActivityMonitor, didStartActivities activities: Set<DeviceActivityName>) {
        print("用户正在使用iPhone,设备已解锁并处于活跃状态")
    }
    
    // 设备停止活跃(锁屏或长时间未操作)
    func monitor(_ monitor: DeviceActivityMonitor, didStopActivities activities: Set<DeviceActivityName>) {
        print("用户停止使用iPhone,设备已锁屏或进入非活跃状态")
    }
}

方案3:CoreMotion运动检测(辅助判断)

如果你的App有运动相关的场景,可以借助CMMotionManager在后台监听设备的运动状态(比如拿起设备、晃动等),间接判断用户可能正在使用设备。但这只是辅助手段,不能精准对应“正在使用”,且需要配置后台运动权限。

代码示例(核心部分):

import CoreMotion

class MotionDetector: NSObject {
    private let motionManager = CMMotionManager()
    
    func startMonitoring() {
        guard motionManager.isDeviceMotionAvailable else { return }
        // 设置更新频率
        motionManager.deviceMotionUpdateInterval = 1.0
        // 后台需要配置UIBackgroundModes的motion权限
        motionManager.startDeviceMotionUpdates(to: .main) { [weak self] motion, error in
            guard let motion = motion else { return }
            // 通过加速度等数据判断设备是否被拿起/操作
            let acceleration = motion.userAcceleration
            if abs(acceleration.x) > 0.1 || abs(acceleration.y) > 0.1 || abs(acceleration.z) > 0.1 {
                print("设备有运动,用户可能正在使用iPhone")
            }
        }
    }
}

最后总结

  • 若需精准且合规的后台检测,iOS 16+ 优先选择DeviceActivityMonitor
  • 低版本iOS只能依赖App前后台状态通知,或结合运动检测做辅助判断;
  • 绝对避免使用私有API或Darwin通知,这类方案100%无法通过App Store审核;
  • 所有后台检测都必须遵守iOS隐私规则,必须向用户清晰说明权限用途,不能滥用权限。

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

火山引擎 最新活动