web-dev-qa-db-ja.com

iPhoneで画面のロック/ロック解除イベントを検出するにはどうすればよいですか?

IPhoneで画面のロック/ロック解除イベントを検出するにはどうすればよいですか?ユーザーがロックを解除したときに、iPhoneアプリからの通知アラートを表示したいと思います。 (Androidの画面ロック解除用のブロードキャストレシーバーと同じように。)

16
Vikas S Singh

実際には、アプリケーションを終了してiPhoneをロックし、しばらくしてiPhoneのロックを解除してから、アプリケーションを終了すると、通知が表示されるか、アプリケーションの起動を警告します。

あなたはiPhoneでそれをすることはできません。

3
Oliver

これをチェックしてください。ロック/ロック解除イベントを検出したかったので、ダーウィンの通知で解決しました。デバイスが"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);  
}   
24
Rohit Kashyap

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")
}
1
Vadim

AppDelegateに次のメソッドを実装する必要があるかもしれません。

アプリケーションがバックグラウンドにあることをデリゲートに通知します。

- (void)applicationDidEnterBackground:(UIApplication *)application

アプリケーションがアクティブになったことをデリゲートに通知します。

- (void)applicationDidBecomeActive:(UIApplication *)application

アプリケーションが非アクティブになりそうであることをデリゲートに通知します。

- (void)applicationWillResignActive:(UIApplication *)application
1
Nekto
  1. アプリをAppStoreに送信するときにcom.Apple.springboard.lockcompleteまたはcom.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
}
0
Alen Liang