iOS 后台任务检测屏幕打开或关闭

iOS background task detect screen is on or off

我正在开发一个记录屏幕 on/off 事件的应用程序。这是一种智能手机使用分析应用程序。该应用程序所做的就是写下这样的日志:

2015 July 25 at 03:54:12 PM - Screen on
2015 July 25 at 03:59:38 PM - Screen off
2015 July 25 at 04:20:52 PM - Screen on
2015 July 25 at 04:22:32 PM - Screen off
...
2015 July 26 at 10:20:32 AM - Screen on
2015 July 26 at 10:22:11 AM - Screen off
2015 July 26 at 11:30:38 AM - Screen on
2015 July 26 at 10:31:02 AM - Screen off
...

我在 Android 上找到了一些方法,使用广播接收器捕获系统发送的事件。但是在 iOS 中似乎有一个问题,因为 iOS 只允许后台服务 运行 几分钟,我什至不确定我是否可以检测到 "screen on/off" 事件 iOS.

我对此做了一些研究并找到了一些文章,但这些都没有太大帮助:

我的问题是“是否可以在 iOS(最新版本 - 8.4)中制作这样的应用程序?

谢谢。

使用后台服务可能无法在已发布的非越狱 iOS 设备中满足您的所有要求。我可以看到通知,我只是不确定背景。

既然其他人一直说这是不可能的,我在这里更深入地挖掘一下,看看到底能做多少。

因为iOS目前仅限于少数后台模式(事件在后台传递的情况),或者在用户导航离开后几分钟内授予您的应用程序的模式从您的应用程序来看,主要问题是诱使系统允许您的应用程序在需要时在后台获取时间。

Programming Guide to Background Execution中描述了几种后台模式。例如,如果您可以定期发送推送通知以唤醒应用 "download content",您可能能够定期获得一些时间 系统认为这样做合适

背景 Daemon is a possible solution, but only for your own use, but not via the App Store. The official take on this is in the App Store Review Guidelines -- 相关部分是 2.8(大概你会通过让应用程序安装它来启动你的守护进程 "behind the scenes"):

2.8 Apps that install or launch other executable code will be rejected

可能有一些系统日志是iOS自己保留的;如果你可以访问这些,你就会拥有你的数据。但是,我怀疑这是否可以从非越狱 phone.

以编程方式获得

我能够测试一些 Swift (2.0) 代码,这些代码使用了在 Stack Overflow 讨论之一中提到的 Darwin Notifications,您的原始问题导致:Lock / Unlock Events for iPhone。我实际上并没有 运行 在后台,但我确实验证了事件 最终 交付,即使应用程序没有 运行ning 当实际锁定事件发生。当我的应用程序打开时,会调用通知。因此,如果您能够从系统中获取时间,那么当 Apple 的算法决定给您时间时,您会收到(延迟的)通知。

允许监听的代码片段(我把它塞进了一些随机应用程序)如下:

import UIKit
import CoreFoundation

class MainViewController: UIViewController, UIWebViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // CoreFoundation compatible types
        var cfstr: CFString = "com.apple.iokit.hid.displayStatus" as NSString
        var notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()

        CFNotificationCenterAddObserver(notificationCenter, nil,
            { (noti: CFNotificationCenter!, aPtr: UnsafeMutablePointer<Void>, aStr: CFString!, bPtr: UnsafePointer<Void>, aDict: CFDictionary!) -> () in
                print("got notification") }, cfstr, nil, CFNotificationSuspensionBehavior.DeliverImmediately)

    }
    // [... more stuff ...]
}

如果您可以使用 C 或 objective C 代码,我想这段代码可能会对您有所帮助。

   notify_register_dispatch("com.apple.iokit.hid.displayStatus", &notify_token, dispatch_get_main_queue(), ^(int token) {
    uint64_t state = UINT64_MAX;
    notify_get_state(token, &state);
    //notify_cancel(token);
    debug("com.apple.iokit.hid.displayStatus = %llu", state);
});

前提是您能够 运行 您的应用程序处于后台模式。 状态将提供屏幕开启关闭状态