如何检测 iPhone 上的屏幕锁定/解锁事件?

发布于 2024-12-11 12:39:45 字数 94 浏览 5 评论 0 原文

如何检测 iPhone 上的屏幕锁定/解锁事件?当用户解锁时,我想显示来自我的 iPhone 应用程序的通知警报。 (就像 Android 中用于屏幕解锁的广播接收器一样。)

How can I detect screen lock/unlock events on the iPhone? When the user unlocks it, I want to show a notification alert from my iPhone app. (For Just like Broadcast Receiver for screen unlock in Android.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

許願樹丅啲祈禱 2024-12-18 12:39:45

看看这个,我想检测锁定/解锁事件,我通过达尔文通知解决了它。
您可以通过“com.apple.springboard.lockcomplete”检测设备锁定时的事件。

//call back
static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
    // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification

    NSString *lockState = (NSString*)name;
    NSLog(@"Darwin notification NAME = %@",name);

    if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"])
    {
        NSLog(@"DEVICE LOCKED");
    }
    else
    {
        NSLog(@"LOCK STATUS CHANGED");
    }   
}


-(void)registerforDeviceLockNotif
{
    //Screen lock notifications
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    NULL, // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockcomplete"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    NULL, // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockstate"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);  
}   

Check this out, I wanted to detect the lock/unlock events, I solved it by Darwin notifications.
You can detect the event when the device is locked by "com.apple.springboard.lockcomplete".

//call back
static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
    // the "com.apple.springboard.lockcomplete" notification will always come after the "com.apple.springboard.lockstate" notification

    NSString *lockState = (NSString*)name;
    NSLog(@"Darwin notification NAME = %@",name);

    if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"])
    {
        NSLog(@"DEVICE LOCKED");
    }
    else
    {
        NSLog(@"LOCK STATUS CHANGED");
    }   
}


-(void)registerforDeviceLockNotif
{
    //Screen lock notifications
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    NULL, // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockcomplete"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                    NULL, // observer
                                    displayStatusChanged, // callback
                                    CFSTR("com.apple.springboard.lockstate"), // event name
                                    NULL, // object
                                    CFNotificationSuspensionBehaviorDeliverImmediately);  
}   
三生路 2024-12-18 12:39:45

要在 swift 5 中检测应用程序内部的锁定/解锁,只有这对我有用:

override func viewDidLoad() {
    super.viewDidLoad()

     NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.willEnterForegroundNotification, object: nil)
     NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}

@objc func applicationDidBecomeActive(notification: NSNotification) {
    print("ACTIVE")
}
@objc func applicationDidEnterBackground(notification: NSNotification) {
    print("BACKGROUND")
}

To detect lock/unlock inside app in swift 5 only this worked for me:

override func viewDidLoad() {
    super.viewDidLoad()

     NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.willEnterForegroundNotification, object: nil)
     NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
}

@objc func applicationDidBecomeActive(notification: NSNotification) {
    print("ACTIVE")
}
@objc func applicationDidEnterBackground(notification: NSNotification) {
    print("BACKGROUND")
}
懒猫 2024-12-18 12:39:45
  1. 向 App Store 提交应用时,不能使用 com.apple.springboard.lockcompletecom.apple.springboard.lockstate,您的应用将被拒绝因为它是私有 API。

  2. com.apple.springboard.lockcomplete 通知并不总是在 com.apple.springboard.lockstate 通知之后出现,它可能会提前或稍后发生。您需要设置一个计时器来等待该事件。

以下是在 Swift 5 中检测屏幕锁定和解锁状态的方法:

struct NotificationName {
    // Listen to CFNotification, and convert to Notification
    public static let lockComplete = Notification.Name("NotificationName.lockComplete")
    public static let lockState = Notification.Name("NotificationName.lockState")

    // Handle lockComplete and lockState Notification to post locked or unlocked notification.
    public static let locked = Notification.Name("NotificationName.locked")
    public static let unlocked = Notification.Name("NotificationName.unlocked")
}

func addNotificationObservers() {
    let lockCompleteString = "com.apple.springboard.lockcomplete"
    let lockString = "com.apple.springboard.lockstate"

    // Listen to CFNotification, post Notification accordingly.
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                    nil,
                                    { (_, _, _, _, _) in
                                        NotificationCenter.default.post(name: NotificationName.lockComplete, object: nil)
                                    },
                                    lockCompleteString as CFString,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                    nil,
                                    { (_, _, _, _, _) in
                                        NotificationCenter.default.post(name: NotificationName.lockState, object: nil)
                                    },
                                    lockString as CFString,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

    // Listen to Notification and handle.
    NotificationCenter.default.addObserver(self,
                                            selector: #selector(onLockComplete),
                                            name: NotificationName.lockComplete,
                                            object: nil)

    NotificationCenter.default.addObserver(self,
                                            selector: #selector(onLockState),
                                            name: NotificationName.lockState,
                                            object: nil)
}

// nil means don't know; ture or false means we did or did not received such notification.
var receiveLockStateNotification: Bool? = nil
// when we received lockState notification, use timer to wait 0.3s for the lockComplete notification.
var waitForLockCompleteNotificationTimer: Timer? = nil
var receiveLockCompleteNotification: Bool? = nil

// When we received lockComplete notification, invalidate timer and refresh lock status.
@objc
func onLockComplete() {
    if let timer = waitForLockCompleteNotificationTimer {
        timer.invalidate()
        waitForLockCompleteNotificationTimer = nil
    }

    receiveLockCompleteNotification = true
    changeIsLockedIfNeeded()
}

// When we received lockState notification, refresh lock status.
@objc
func onLockState() {
    receiveLockStateNotification = true
    changeIsLockedIfNeeded()
}

func changeIsLockedIfNeeded() {
    guard let state = receiveLockStateNotification, state else {
        // If we don't receive lockState notification, return.
        return
    }

    guard let complete = receiveLockCompleteNotification else {
        // If we don't receive lockComplete notification, wait 0.3s.
        // If nothing happens in 0.3s, then make sure we don't receive lockComplete, and refresh lock status.
        waitForLockCompleteNotificationTimer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false, block: { _ in
            self.receiveLockCompleteNotification = false
            self.changeIsLockedIfNeeded()
        })
        return
    }

    // When we determined lockState and lockComplete notification is received or not.
    // We can update the device lock status by 'complete' value.
    NotificationCenter.default.post(
        name: complete ? NotificationName.locked : NotificationName.unlocked,
        object: nil
    )

    // Reset status.
    receiveLockStateNotification = nil
    receiveLockCompleteNotification = nil
}
  1. You can't use com.apple.springboard.lockcomplete or com.apple.springboard.lockstate when submitting your app to App Store, your app will be rejected because it's private API.

  2. The com.apple.springboard.lockcomplete notification NOT always comes after the com.apple.springboard.lockstate notification, it may happen early or later. You need to set a timer to wait for that event.

So here is how you can detect screen lock and unlock status, in Swift 5:

struct NotificationName {
    // Listen to CFNotification, and convert to Notification
    public static let lockComplete = Notification.Name("NotificationName.lockComplete")
    public static let lockState = Notification.Name("NotificationName.lockState")

    // Handle lockComplete and lockState Notification to post locked or unlocked notification.
    public static let locked = Notification.Name("NotificationName.locked")
    public static let unlocked = Notification.Name("NotificationName.unlocked")
}

func addNotificationObservers() {
    let lockCompleteString = "com.apple.springboard.lockcomplete"
    let lockString = "com.apple.springboard.lockstate"

    // Listen to CFNotification, post Notification accordingly.
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                    nil,
                                    { (_, _, _, _, _) in
                                        NotificationCenter.default.post(name: NotificationName.lockComplete, object: nil)
                                    },
                                    lockCompleteString as CFString,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
                                    nil,
                                    { (_, _, _, _, _) in
                                        NotificationCenter.default.post(name: NotificationName.lockState, object: nil)
                                    },
                                    lockString as CFString,
                                    nil,
                                    CFNotificationSuspensionBehavior.deliverImmediately)

    // Listen to Notification and handle.
    NotificationCenter.default.addObserver(self,
                                            selector: #selector(onLockComplete),
                                            name: NotificationName.lockComplete,
                                            object: nil)

    NotificationCenter.default.addObserver(self,
                                            selector: #selector(onLockState),
                                            name: NotificationName.lockState,
                                            object: nil)
}

// nil means don't know; ture or false means we did or did not received such notification.
var receiveLockStateNotification: Bool? = nil
// when we received lockState notification, use timer to wait 0.3s for the lockComplete notification.
var waitForLockCompleteNotificationTimer: Timer? = nil
var receiveLockCompleteNotification: Bool? = nil

// When we received lockComplete notification, invalidate timer and refresh lock status.
@objc
func onLockComplete() {
    if let timer = waitForLockCompleteNotificationTimer {
        timer.invalidate()
        waitForLockCompleteNotificationTimer = nil
    }

    receiveLockCompleteNotification = true
    changeIsLockedIfNeeded()
}

// When we received lockState notification, refresh lock status.
@objc
func onLockState() {
    receiveLockStateNotification = true
    changeIsLockedIfNeeded()
}

func changeIsLockedIfNeeded() {
    guard let state = receiveLockStateNotification, state else {
        // If we don't receive lockState notification, return.
        return
    }

    guard let complete = receiveLockCompleteNotification else {
        // If we don't receive lockComplete notification, wait 0.3s.
        // If nothing happens in 0.3s, then make sure we don't receive lockComplete, and refresh lock status.
        waitForLockCompleteNotificationTimer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false, block: { _ in
            self.receiveLockCompleteNotification = false
            self.changeIsLockedIfNeeded()
        })
        return
    }

    // When we determined lockState and lockComplete notification is received or not.
    // We can update the device lock status by 'complete' value.
    NotificationCenter.default.post(
        name: complete ? NotificationName.locked : NotificationName.unlocked,
        object: nil
    )

    // Reset status.
    receiveLockStateNotification = nil
    receiveLockCompleteNotification = nil
}
幻想少年梦 2024-12-18 12:39:45

可能您需要在 AppDelegate 中实现以下方法:

告诉代理应用程序现在位于后台。

- (void)applicationDidEnterBackground:(UIApplication *)application

告诉代理应用程序已变为活动状态。

- (void)applicationDidBecomeActive:(UIApplication *)application

告诉代理应用程序即将变为非活动状态。

- (void)applicationWillResignActive:(UIApplication *)application

May be you need to implement following methods in AppDelegate:

Tells the delegate that the application is now in the background.

- (void)applicationDidEnterBackground:(UIApplication *)application

Tells the delegate that the application has become active.

- (void)applicationDidBecomeActive:(UIApplication *)application

Tells the delegate that the application is about to become inactive.

- (void)applicationWillResignActive:(UIApplication *)application
若水微香 2024-12-18 12:39:45

实际上我想要的是如果我退出应用程序并锁定iPhone,
一段时间后我解锁了 iPhone,然后退出应用程序
显示通知或提醒启动应用程序。

您无法在 iPhone 上执行此操作。

Actually I want the if I exit the application and lock the iPhone ,
and after some time I have unlock the iPhone , then exit Applications
show the notifications or Alert the Start-up the Applications.

You can't do that on the iPhone.

撧情箌佬 2024-12-18 12:39:45

最初的问题已经很老了,所以对于任何偶然发现这个问题的人来说:

在具有 Face ID 和 Touch ID 的现代设备上,您可以使用 AppDelegate 方法 applicationProtectedDataDidBecomeAvailable(_:) (docs)和 applicationProtectedDataWillBecomeUnavailable(_:) (文档)。

当设备存储被解密或加密时,将调用这些函数。它们的目的是让应用程序知道何时可以读取存储中的数据或何时变得不可用。但是,由于当今几乎所有 iPhone 上都启用了设备加密,因此您还可以使用它们来检测屏幕锁定和解锁事件。

但是,这当然只有在您的应用程序正在运行时才有效。

The original question is quite old, so for anybody who stumbles on this:

On modern devices with Face ID and Touch ID, you can use the AppDelegate methods applicationProtectedDataDidBecomeAvailable(_:) (docs) and applicationProtectedDataWillBecomeUnavailable(_:) (docs).

These are called when the device storage is decrypted or encrypted. They are intended to let the app know when data from the storage can be read or becomes unavailable. However, because device encryption is active on almost any iPhone today, you can also use these to detect screen lock and unlock events.

However, this of course only works as long as your app is actively running.

念三年u 2024-12-18 12:39:45

从当前视图控制器中,您应该为 UIApplicationDidEnterBackgroundNotification 添加一个观察者,并在关闭视图控制器期间删除观察者
[[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];

From the current view controller your should add an observer for UIApplicationDidEnterBackgroundNotification and remove the observer during dismissing the view controller
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文