是否可以区分锁定设备和将应用程序发送到后台?

发布于 2024-12-12 02:18:29 字数 908 浏览 0 评论 0原文

我有一个应用程序,当使用“主页”按钮发送到后台时需要执行某些操作,而当使用顶部硬件按钮锁定设备时需要执行其他操作。解决这些需求的标准方法是由 UIApplication 发出的通知和委托方法。在 iOS 4 上,它们看起来像这样:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
// Unlocking the device
Did become active.

换句话说,很容易区分锁定和后台。在 iOS 5 上,行为发生了变化:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
Did enter background.
// Unlocking the device
Will enter foreground.
Did become active.

请注意,即使在锁定(解锁)设备时,现在也会发送 didEnterBackgroundwillEnterForeground 通知,因此无法区分锁定和锁定。背景。此更改是否记录在某处?这是一种回归吗?您知道区分这两种情况的另一种方法吗?

I have an app that needs to do something when it’s sent to background using the Home button and something else when the device is locked using the top hardware button. The standard way of solving these requirements are the notifications and delegate methods sent out by UIApplication. On iOS 4 they look like this:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
// Unlocking the device
Did become active.

In other words, it’s quite easy to tell between locking and backgrounding. On iOS 5 the behaviour changed:

// Pressing the home button
Will resign active.
Did enter background.
// Tapping app icon on Springboard
Will enter foreground.
Did become active.

// Pressing the lock button
Will resign active.
Did enter background.
// Unlocking the device
Will enter foreground.
Did become active.

Notice that the didEnterBackground and willEnterForeground notifications are now sent out even when (un)locking the device, making it impossible to tell between locking and backgrounding. Is this change documented somewhere? Is it a regression? Do you know another way to distinguish the two cases?

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

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

发布评论

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

评论(5

凶凌 2024-12-19 02:18:29

iOS 6

在我通过模拟器进行的初步测试中,使用

[[UIApplication sharedApplication] applicationState]

任一

- (void)applicationWillEnterForeground:(UIApplication *)application

- (void)applicationDidEnterBackground:(UIApplication *)application

命令检查应用程序状态都可以让您区分调用锁定设备和仅切换回主屏幕。锁定屏幕将返回 1 (UIApplicationStateInactive),而按下主页按钮将注册为 2 (UIApplicationStateBackground)。

它看起来是一致的,并且应该在 iOS 设备上工作,就像在模拟器中一样可靠。

iOS 7

iOS 6 方法在 iOS 7 中不再有效。为了现在执行此操作,您必须利用 CFNotificationCenter 并侦听 darwin 通知(标记为:com.apple.springboard.lockcomplete)。您可以在此处找到包含示例项目的 github 存储库:https://github。 com/binarydev/ios-home-vs-lock-button

iOS 7 修复的功劳归于 wqq

iOS 6

In my preliminary testing via the simulator, checking the application state with

[[UIApplication sharedApplication] applicationState]

in either

- (void)applicationWillEnterForeground:(UIApplication *)application

- (void)applicationDidEnterBackground:(UIApplication *)application

allows you to differentiate between a call to lock the device and just switching back to the homescreen. A lock screen will return 1 (UIApplicationStateInactive), whereas a home button press will register as a 2 (UIApplicationStateBackground).

It seems consistent and should work on an iOS device just as reliably as it does in the simulator.

iOS 7

The iOS 6 method no longer works in iOS 7. In order to do this now, you have to utilize CFNotificationCenter and listen for a darwin notification (labeled: com.apple.springboard.lockcomplete). You can find the github repo with the sample project here: https://github.com/binarydev/ios-home-vs-lock-button

Credit for the iOS 7 fix goes out to wqq

舟遥客 2024-12-19 02:18:29

我对此进行了相当多的研究,所以如果有人知道我不知道的事情,我很乐意在这里犯错,但从技术上讲,没有记录的方法来区分锁定设备和发送到后台。

不过,您可以检查的一件事是从前台转换到后台期间的 UIApplicationState。锁定设备将给出UIApplicationStateInactive,将应用程序移至后台将给出UIApplicationStateBackground。但是,由于这种行为没有正式记录,因此将来可能会发生变化。

一个基本的例子:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    NSLog(@"Device state: %@", state);
    switch (state) {
        case UIApplicationStateActive:
            /* ... */
            break;
        case UIApplicationStateInactive:
            /* Device was/is locked  */
            break;
        case UIApplicationStateBackground:
            /* User pressed home button or opened another App (from an alert/email/etc) */
            break;
    }
}

UIApplicationState - 应用程序的运行状态

typedef 枚举 {
    UIApplicationStateActive,   
    UIApplicationStateInactive,
    UI应用程序状态背景
}

UIApplicationState

常量

UIApplicationStateActive - 应用程序
正在前台运行并且当前正在接收事件。可用的
在 iOS 4.0 及更高版本中。

UIApplicationStateInactive - 应用程序正在运行
前台但未接收事件。结果可能会发生这种情况
中断或因为应用程序正在转换到或
从背景。

UIApplicationStateBackground - 应用程序是
在后台运行。


根据 UIApplicationDelegate 协议参考< /a>:

applicationWillResignActive:
didEnterBackground:
// ...
willEnterForeground:
applicationDidBecomeActive:

是在这两种情况下唯一被调用的方法。


根据 iOS 4.3 到 iOS 5.0 API 差异,这些是有关 UIApplicationUIApplicationDelegate 的唯一更改,因此我找不到他们记录这些通知更改的位置:

UIApplication.h
Added -[UIApplication setNewsstandIconImage:]
Added UIApplication.userInterfaceLayoutDirection
Added UIApplicationDelegate.window
Added UIApplication(UINewsstand)
Added UIApplicationLaunchOptionsNewsstandDownloadsKey
Added UIRemoteNotificationTypeNewsstandContentAvailability
Added UIUserInterfaceLayoutDirection
Added UIUserInterfaceLayoutDirectionLeftToRight
Added UIUserInterfaceLayoutDirectionRightToLeft

I have looked into this quite a bit so I would love to be wrong here if someone knows something I don't, but technically, there is no documented way to tell the difference between locking the device, and sending to background.

One thing you can check however, is the UIApplicationState during the transition from foreground to background. Locking a device will give UIApplicationStateInactive and moving the App to the background will give UIApplicationStateBackground. But, since this behaviour is not officially documented it may change in the future.

A basic example:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIApplicationState state = [[UIApplication sharedApplication] applicationState];
    NSLog(@"Device state: %@", state);
    switch (state) {
        case UIApplicationStateActive:
            /* ... */
            break;
        case UIApplicationStateInactive:
            /* Device was/is locked  */
            break;
        case UIApplicationStateBackground:
            /* User pressed home button or opened another App (from an alert/email/etc) */
            break;
    }
}

UIApplicationState - The running states of an application

typedef enum {
    UIApplicationStateActive,   
    UIApplicationStateInactive,
    UIApplicationStateBackground
}

UIApplicationState

Constants

UIApplicationStateActive - The application
is running in the foreground and currently receiving events. Available
in iOS 4.0 and later.

UIApplicationStateInactive - The application is running in the
foreground but is not receiving events. This might happen as a result
of an interruption or because the application is transitioning to or
from the background.

UIApplicationStateBackground - The application is
running in the background.


According to the UIApplicationDelegate Protocol Reference:

applicationWillResignActive:
didEnterBackground:
// ...
willEnterForeground:
applicationDidBecomeActive:

are the only methods that ever get called in both situations.


According to the iOS 4.3 to iOS 5.0 API Diff, these are the ONLY changes regarding UIApplication or UIApplicationDelegate, so I couldn't find where they documented any of these notification changes:

UIApplication.h
Added -[UIApplication setNewsstandIconImage:]
Added UIApplication.userInterfaceLayoutDirection
Added UIApplicationDelegate.window
Added UIApplication(UINewsstand)
Added UIApplicationLaunchOptionsNewsstandDownloadsKey
Added UIRemoteNotificationTypeNewsstandContentAvailability
Added UIUserInterfaceLayoutDirection
Added UIUserInterfaceLayoutDirectionLeftToRight
Added UIUserInterfaceLayoutDirectionRightToLeft
耳钉梦 2024-12-19 02:18:29

这更多的是一种解决方法/黑客,但根据我的经验,它非常可靠。
当设备屏幕锁定时(不仅仅是主页按钮,如果这是一个词:)) - 绑定网络 (UDP) 套接字被破坏。
我使用的是 GCDAsyncUDPSocket(之前也是 AsyncUDPSocket),当设备关闭时,它们都会可靠地触发网络/损坏的管道错误。
就我而言,无论如何我都需要 UDP 套接字,对于其他应用程序来说,它可能有点难闻,但是,如果您确实需要在这里进行区分,则仅在 UDP 套接字上绑定/侦听而不进行任何操作并不算太糟糕。

这张纸条会[自毁];是 5 分钟(这样苹果就不会发现)。

This is more of a workaround/hack, but according to my experience it's very reliable.
When the device is screen-locked (not just home button-ed, if that's a word :)) - bound network (UDP) sockets are broken.
I was using GCDAsyncUDPSocket (also AsyncUDPSocket before) and they both fire a network/broken pipe error reliably when the device is turned off.
In my case I need the UDP socket anyway, for other apps it might be a bit smelly, however, just binding/listening on a UDP socket without any action is not too terrible if you really need to differentiate here.

This note will [self destruct]; is 5 minutes (so Apple won't find out).

浅语花开 2024-12-19 02:18:29

Apple 开发者论坛上有一个关于此问题的帖子(仅限注册开发者,抱歉)。要点是新行为是设计使然。有人请求提供新的 API 功能来区分这两种用例,但目前还没有任何效果。

There’s a thread about this issue on Apple Developer Forums (registered developers only, sorry). The gist is that the new behaviour is by design. There are requests for a new API feature to distinguish between the two use cases, but nothing working yet.

三岁铭 2024-12-19 02:18:29

Apple 的 iOS 编程指南是这样说的:

按睡眠/唤醒按钮是另一种类型的中断,
导致您的应用程序暂时停用。当用户按下
此按钮,系统禁用触摸事件,将应用程序移动到
背景但设置应用程序的 applicationState 属性的值
UIApplicationStateInactive (与
UIApplicationStateBackground),最后锁定屏幕。

http://developer.apple.com/ Library/ios/#DOCUMENTATION/iPhone/conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

所以,你应检查 applicationDidEnterBackground: 中的 UIApplicationapplicationState 属性。如果是 UIApplicationStateBackground,则用户按下了主页按钮。但如果是 UIApplicationStateInactive,则用户锁定了设备。

Here is what Apple's iOS Programming Guide says:

Pressing the Sleep/Wake button is another type of interruption that
causes your app to be deactivated temporarily. When the user presses
this button, the system disables touch events, moves the app to the
background but sets the value of the app’s applicationState property
to UIApplicationStateInactive (as opposed to
UIApplicationStateBackground), and finally locks the screen.

http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

So, you should check the UIApplication's applicationState property in applicationDidEnterBackground:. If it is UIApplicationStateBackground the user pressed the home button. But if it is UIApplicationStateInactive the user locked the device.

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