joa*_*oao 162 push-notification apple-push-notifications uiapplicationdelegate ios ios6
是否可以知道应用程序是否通过推送通知启动/打开?
我猜这个发布活动可以在这里找到:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions != nil) {
// Launched from push notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当应用程序处于后台时,如何检测到它是从推送通知中打开的?
sha*_*gao 183
请参阅此代码:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground )
{
//opened from a push notification when the app was on background
}
}
Run Code Online (Sandbox Code Playgroud)
与...一样
-(void)application:(UIApplication *)application didReceiveLocalNotification (UILocalNotification *)notification
Run Code Online (Sandbox Code Playgroud)
M.O*_*man 126
迟到但也许有用
当应用程序未运行时
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
叫做 ..
你需要检查推送通知的地方
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
NSLog(@"app recieved notification from remote%@",notification);
[self application:application didReceiveRemoteNotification:notification];
} else {
NSLog(@"app did not recieve notification");
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ner 30
我们遇到的问题是在启动应用程序后正确更新视图.这里有复杂的生命周期方法序列令人困惑.
生命周期方法
我们对iOS 10的测试揭示了针对各种情况的以下生命周期方法序列:
DELEGATE METHODS CALLED WHEN OPENING APP
Opening app when system killed or user killed
didFinishLaunchingWithOptions
applicationDidBecomeActive
Opening app when backgrounded
applicationWillEnterForeground
applicationDidBecomeActive
DELEGATE METHODS WHEN OPENING PUSH
Opening push when system killed
[receiving push causes didFinishLaunchingWithOptions (with options) and didReceiveRemoteNotification:background]
applicationWillEnterForeground
didReceiveRemoteNotification:inactive
applicationDidBecomeActive
Opening push when user killed
didFinishLaunchingWithOptions (with options)
didReceiveRemoteNotification:inactive [only completionHandler version]
applicationDidBecomeActive
Opening push when backgrounded
[receiving push causes didReceiveRemoteNotification:background]
applicationWillEnterForeground
didReceiveRemoteNotification:inactive
applicationDidBecomeActive
Run Code Online (Sandbox Code Playgroud)
问题
好的,现在我们需要:
棘手的是,当应用程序实际变为活动状态时,必须更新视图,这在所有情况下都是相同的生命周期方法.
我们解决方案的草图
以下是我们解决方案的主要组成部分:
notificationUserInfo在AppDelegate上存储实例变量.notificationUserInfo = nil在applicationWillEnterForeground和didFinishLaunchingWithOptions.notificationUserInfo = userInfo在didReceiveRemoteNotification:inactiveapplicationDidBecomeActive总是调用自定义方法openViewFromNotification并传递self.notificationUserInfo.如果self.notificationUserInfo为nil则提前返回,否则根据找到的通知状态打开视图self.notificationUserInfo.说明
当从push打开didFinishLaunchingWithOptions或者applicationWillEnterForeground总是在之前调用时didReceiveRemoteNotification:inactive,所以我们首先在这些方法中重置notificationUserInfo,这样就没有陈旧状态了.然后,如果didReceiveRemoteNotification:inactive被调用,我们知道我们正在从推动开始,所以我们设置self.notificationUserInfo然后选择通过applicationDidBecomeActive将用户转发到右视图.
最后一种情况是,如果用户在应用程序切换器中打开了应用程序(即,当应用程序位于前台时双击主页按钮),然后接收推送通知.在这种情况下只didReceiveRemoteNotification:inactive调用,并且WillEnterForeground和didFinishLaunching都不会被调用,所以你需要一些特殊的状态来处理这种情况.
希望这可以帮助.
Mob*_*Vet 24
这是一个很好的帖子......但它仍然缺少问题的实际解决方案(如各种评论中所指出的).
最初的问题是关于检测应用程序何时从推送通知启动 /打开,例如用户点击通知.这些答案实际上都没有涵盖这个案例.
当通知到达时,可以在呼叫流程中看到原因, application:didReceiveRemoteNotification...
当接收到通知被调用和时再通知是由用户点击.正因为如此,你只能看着UIApplicationState用户点击它就无法分辨.
此外,您不再需要处理应用程序的"冷启动"状态,application:didFinishLaunchingWithOptions...因为application:didReceiveRemoteNotification...在iOS 9+(也可能是8)启动后再次调用.
那么,如何判断用户是否启动了事件链?我的解决方案是标记应用程序开始退出后台或冷启动的时间,然后检查该时间application:didReceiveRemoteNotification....如果它小于0.1秒,那么你可以非常肯定点击触发了启动.
Swift 2.x
class AppDelegate: UIResponder, UIApplicationDelegate {
var wakeTime : NSDate = NSDate() // when did our application wake up most recently?
func applicationWillEnterForeground(application: UIApplication) {
// time stamp the entering of foreground so we can tell how we got here
wakeTime = NSDate()
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// ensure the userInfo dictionary has the data you expect
if let type = userInfo["type"] as? String where type == "status" {
// IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
if application.applicationState != UIApplicationState.Background && NSDate().timeIntervalSinceDate(wakeTime) < 0.1 {
// User Tap on notification Started the App
}
else {
// DO stuff here if you ONLY want it to happen when the push arrives
}
completionHandler(.NewData)
}
else {
completionHandler(.NoData)
}
}
}
Run Code Online (Sandbox Code Playgroud)
斯威夫特3
class AppDelegate: UIResponder, UIApplicationDelegate {
var wakeTime : Date = Date() // when did our application wake up most recently?
func applicationWillEnterForeground(_ application: UIApplication) {
// time stamp the entering of foreground so we can tell how we got here
wakeTime = Date()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// ensure the userInfo dictionary has the data you expect
if let type = userInfo["type"] as? String, type == "status" {
// IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
if application.applicationState != UIApplicationState.background && Date().timeIntervalSince(wakeTime) < 0.1 {
// User Tap on notification Started the App
}
else {
// DO stuff here if you ONLY want it to happen when the push arrives
}
completionHandler(.newData)
}
else {
completionHandler(.noData)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经在iOS 9+上对这两种情况(背景中的应用程序,应用程序没有运行)进行了测试,它就像一个魅力.0.1s也很保守,实际值是~0.002s所以0.01也很好.
Vla*_*iak 19
Swift 2.0用于"未运行"状态(本地和远程通知)
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Handle notification
if (launchOptions != nil) {
// For local Notification
if let localNotificationInfo = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
if let something = localNotificationInfo.userInfo!["yourKey"] as? String {
self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
}
} else
// For remote Notification
if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as! [NSObject : AnyObject]? {
if let something = remoteNotification["yourKey"] as? String {
self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
}
}
}
return true
}
Run Code Online (Sandbox Code Playgroud)
}
onm*_*133 19
当应用程序终止时,用户点击推送通知
public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] != nil {
print("from push")
}
}
Run Code Online (Sandbox Code Playgroud)
当应用程序处于后台时,用户点击推送通知
如果用户从系统显示的警报中打开您的应用程序,系统可能会在您的应用程序即将进入前台时再次调用此方法,以便您可以更新用户界面并显示与通知相关的信息.
public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
if application.applicationState == .Inactive {
print("from push")
}
}
Run Code Online (Sandbox Code Playgroud)
根据您的应用程序,它也可以向您发送静音推送content-available内部aps,所以也要注意这一点:)请参阅/sf/answers/2364529331/
Mad*_*dhu 15
在application:didReceiveRemoteNotification:检查是否已收到通知时,您的应用程序是在前台或后台.
如果是在后台收到,请从通知中启动应用程序.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
NSLog(@"Notification received by running app");
} else {
NSLog(@"App opened from Notification");
}
}
Run Code Online (Sandbox Code Playgroud)
Lon*_*Guy 12
对于swift:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background {
//opened from a push notification when the app was on background
}
}
Run Code Online (Sandbox Code Playgroud)
如果您SceneDelegate的应用程序中有,那么当您的应用程序被终止/终止并且您通过点击通知打开应用程序时,您应该使用下面的代码来管理本地/远程通知
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//Handle Notification Response
guard let notifiResponse = connectionOptions.notificationResponse else { return }
if notifiResponse.notification.request.trigger is UNTimeIntervalNotificationTrigger { //Local Notification
Messaging.messaging().appDidReceiveMessage(notifiResponse.notification.request.content.userInfo)
print("Receive Local Notifications")
}
else if notifiResponse.notification.request.trigger is UNPushNotificationTrigger{ //Remote Notification
print("Receive Remote Notifications")
}
}
Run Code Online (Sandbox Code Playgroud)
AppDelegate当您的应用程序处于后台/前台状态时,使用您来管理本地/远程通知。
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if response.notification.request.trigger is UNTimeIntervalNotificationTrigger{
print("Receive Local Notifications")
}
else if response.notification.request.trigger is UNPushNotificationTrigger{
print("Receive Remote Notifications")
}
let userInfo = response.notification.request.content.userInfo
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent Notifications")
if notification.request.trigger is UNTimeIntervalNotificationTrigger{
print("Receive Local Notifications")
}
else {
print("Receive Remote Notifications")
}
completionHandler([.banner, .list, .sound])
}
}
Run Code Online (Sandbox Code Playgroud)
为 Xamarin 用户发布此内容。
检测应用程序是否通过推送通知启动的关键是AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)方法和传入的选项字典。
如果它是本地通知,选项字典中将包含此键: UIApplication.LaunchOptionsLocalNotificationKey。
如果是远程通知,那就是UIApplication.LaunchOptionsRemoteNotificationKey。
当键为 时LaunchOptionsLocalNotificationKey,该对象就是类型UILocalNotification。然后,您可以查看该通知并确定它是哪个特定通知。
专业提示:UILocalNotification其中没有标识符,同样的方式UNNotificationRequest。将包含 requestId 的字典键放入 UserInfo 中,以便在测试 时UILocalNotification,您将拥有一个特定的 requestId 可用于某些逻辑的基础。
我发现即使在 iOS 10+ 设备上,当使用UNUserNotificationCenter's AddNotificationRequest&创建位置通知UNMutableNotificationContent时,当应用程序未运行(我杀死了它)并通过点击通知中心中的通知启动时,字典仍然包含物体UILocalNotificaiton。
这意味着我检查基于通知的启动的代码将在 iOS8 和 iOS 10+ 设备上运行
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
_logger.InfoFormat("FinishedLaunching");
if(options != null)
{
if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
{
//was started by tapping a local notification when app wasn't previously running.
//works if using UNUserNotificationCenter.Current.AddNotificationRequest OR UIApplication.SharedApplication.PresentLocalNotificationNow);
var localNotification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;
//I would recommended a key such as this :
var requestId = localNotification.UserInfo["RequestId"].ToString();
}
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107219 次 |
| 最近记录: |