是否可以知道应用程序是否是通过推送通知启动/打开的?
我猜这个发布活动可以在这里找到:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions != nil) {
// Launched from push notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}
但是,当应用程序处于后台时,如何检测到它是从推送通知中打开的?
24 回答
我还没试过,但也许你可以给自己发一个通知? http://nshipster.com/nsnotification-and-nsnotificationcenter/
请参阅此代码:
与...一样
迟到但也许有用
当应用程序未运行时
叫做 ..
你需要检查推送通知的地方
我们遇到的问题是在启动应用程序后正确更新视图 . 这里有复杂的生命周期方法序列令人困惑 .
Lifecycle Methods
我们对iOS 10的测试揭示了针对各种情况的以下生命周期方法序列:
The problem
好的,现在我们需要:
确定用户是否通过推送打开应用程序
根据推送状态更新视图
清除状态,以便后续打开不会将用户返回到相同位置 .
棘手的是,当应用程序实际变为活动状态时,必须更新视图,这在所有情况下都是相同的生命周期方法 .
Sketch of our solution
以下是我们解决方案的主要组成部分:
在AppDelegate上存储
notificationUserInfo
实例变量 .在
applicationWillEnterForeground
和didFinishLaunchingWithOptions
中设置notificationUserInfo = nil
.在
didReceiveRemoteNotification:inactive
中设置notificationUserInfo = userInfo
从
applicationDidBecomeActive
始终调用自定义方法openViewFromNotification
并传递self.notificationUserInfo
. 如果self.notificationUserInfo
为nil则提前返回,否则根据self.notificationUserInfo
中找到的通知状态打开视图 .Explanation
当从
didFinishLaunchingWithOptions
或applicationWillEnterForeground
开始打开时,总是在didReceiveRemoteNotification:inactive
之前立即调用,所以我们首先在这些方法中重置notificationUserInfo,这样就没有陈旧状态了 . 然后,如果didReceiveRemoteNotification:inactive
被调用,我们知道我们正在从推动开始,所以我们设置self.notificationUserInfo
然后由applicationDidBecomeActive
选中以将用户转发到右视图 .最后一种情况是,如果用户在应用程序切换器中打开了应用程序(即,当应用程序位于前台时双击主页按钮),然后接收推送通知 . 在这种情况下,只调用
didReceiveRemoteNotification:inactive
,并且WillEnterForeground和didFinishLaunching都不会被调用,所以你需要一些特殊的状态来处理这种情况 .希望这可以帮助 .
这是一个很好的帖子...但它仍然缺少问题的实际 solution (如各种评论中所指出的) .
当通知到达时,可以在呼叫流程中看到原因,
application:didReceiveRemoteNotification...
当用户点击通知时再次收到通知 AND 时调用 . 因此,你只能通过查看
UIApplicationState
来判断用户是否点击它 .此外,您不再需要在
application:didFinishLaunchingWithOptions...
中处理应用程序'cold start'的情况,因为在iOS 9中启动后再次调用application:didReceiveRemoteNotification...
(也可能是8) .那么,如何判断用户是否启动了事件链?我的解决方案是标记应用程序开始退出后台或冷启动的时间,然后在
application:didReceiveRemoteNotification...
中检查该时间 . 如果它小于0.1秒,那么你可以非常肯定点击触发了启动 .Swift 2.x
Swift 3
我已经在iOS 9上测试了这两种情况(应用程序在后台,应用程序没有运行),它就像一个魅力 . 0.1s也很保守,实际值是~0.002s所以0.01也很好 .
Swift 2.0用于“未运行”状态(本地和远程通知)
}
在
application:didReceiveRemoteNotification:
中,检查当您的应用位于前台或后台时是否收到通知 .如果是在后台收到,请从通知中启动应用程序 .
When app is terminated, and user taps on push notification
When app is in background, and user taps on push notificaion
根据您的应用程序,它也可以在
aps
内向content-available
发送静音推送,所以请意识到这一点:)见https://stackoverflow.com/a/33778990/1418457For swift:
是的,您可以通过 appDelegate 中的此方法进行检测:
对于本地通知:
如果有人想要快速回答3
我将从我为自己创建的状态图开始,以更准确地可视化它并考虑所有其他状态:https://docs.google.com/spreadsheets/d/e/2PACX-1vSdKOgo_F1TZwGJBAED4C_7cml0bEATqeL3P9UKpBwASlT6ZkU3iLdZnOZoevkMzOeng7gs31IFhD-L/pubhtml?gid=0&single=true
使用此图表,我们可以看到实际需要什么才能开发出几乎适用于所有可能用例的强大通知处理系统 .
Complete solution ↓
在 didReceiveRemoteNotification 中存储 notification 有效负载
Clear 已在 applicationWillEnterForeground 和 didFinishLaunchingWithOptions 中存储通知
要处理控制中心/通知中心拉动的情况,您可以使用标志 willResignActiveCalled 并将其初始设置为 false ,在 applicationWillResignActive 方法中将其设置为 true ,
在 didReceiveRemoteNotification 方法中,仅当willResignActiveCalled为false时才保存通知(userInfo) .
在 applicationDidEnterBackground 和 applicationDidBecomeActive 方法中重置 willResignActiveCalled to false .
注意:在对Eric的回答的评论中提出了类似的答案,但是,状态表有助于找到我在我的应用程序中所做的所有可能的场景 .
如果没有处理任何特定情况,请查看下面的完整代码并在下面发表评论:
AppDelegate
NotificationUtils :在这里您可以编写所有代码以导航到应用程序的不同部分,处理数据库(CoreData / Realm)并执行收到通知时需要完成的所有其他操作 .
只有一种可靠的方法,它只适用于 iOS 10+ :
使用
UNUserNotificationCenter
实现UNUserNotificationCenterDelegate
方法:直接从文档中获取
如果应用程序正在运行并收到远程通知,则应用程序会调用此方法来处理通知 .
您对此方法的实现应使用通知采取适当的操作过程 .
过了一会儿
如果在推送通知到达时应用程序未运行,则该方法将启动应用程序并在启动选项字典中提供相应的信息 .
该应用程序不会调用此方法来处理该推送通知 .
相反,你的实施
要么
方法需要获取推送通知有效负载数据并进行适当响应 .
您可以使用:
处理远程推送通知 .
点击这里documentation
这个问题的问题是“打开”应用程序的定义不明确 . 应用程序要么从未运行状态冷启动,要么从非活动状态重新激活(例如从另一个应用程序切换回它) . 这是我区分所有这些可能状态的解决方案:
MXDefaults
只是NSUserDefaults
的一个小包装 .对于
swift
当应用程序在后台作为 shanegao 时,您可以使用
但是如果你想启动应用程序并且当应用程序关闭并且你想调试应用程序时你可以转到 Edit Scheme 并在左侧菜单中选择 Run 然后在启动时选择 Wait for executable to be launched 然后在你点击推送通知时启动应用程序
Edit Scheme > Run > Wait for executable to be launched
为Xamarin用户发布此信息 .
检测应用程序是否通过推送通知启动的关键是
AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)
方法,以及传入的选项字典 .如果是本地通知,则选项字典将包含此密钥:
UIApplication.LaunchOptionsLocalNotificationKey
.如果是远程通知,则为
UIApplication.LaunchOptionsRemoteNotificationKey
.当键为
LaunchOptionsLocalNotificationKey
时,对象的类型为UILocalNotification
. 然后,您可以查看通知并确定它是哪个特定通知 .专业提示:
UILocalNotification
中没有标识符,与UNNotificationRequest
的方式相同 . 在包含requestId的UserInfo中放置一个字典键,这样在测试UILocalNotification
时,您将有一个特定的requestId可用于基于某些逻辑 .我发现即使在iOS 10设备上使用
UNUserNotificationCenter
的AddNotificationRequest
&UNMutableNotificationContent
创建位置通知时,当应用程序未运行时(我将其杀死),并通过点击通知中心的通知启动,即字典仍然包含UILocalNotificaiton
对象 .这意味着我检查基于通知的启动的代码将适用于iOS8和iOS 10设备
对于Swift用户:
如果你想在推送或其他类似的东西上启动一个不同的页面,你需要在
didFinishLaunchingWithOptions
中检查它:IN SWIFT:
我正在运行推送通知(带背景提取) . 当我的应用程序在后台并收到推送通知时,我发现appDelegate中的didReceiveRemoteNotification将被调用两次;一次用于收到通知,另一次用于点击通知提醒 .
要检测是否单击了通知警报,只需检查appDelegate中didReceiveRemoteNotification中的applicationState原始值== 1 .
我希望这有帮助 .
Swift 3.0
在AppDelegate中,在函数'didFinishLaunchingWithOptions'处理远程通知并延迟一些并打开Viewcontroller . 成功加载应用后,您可以使用延迟来处理通知 .