2012-08-24 110 views
38

當我的應用程序是運行並接收推送通知,如果我點擊該通知,應用啓動 - 但是它不與提示用戶我建立了Alert-View,詢問他們是否想查看Notification的內容。它剛剛啓動,並坐在那裏。處理推送通知時,應用程序無法運行

的推送通知做的工作完美當應用程序運行 - 無論是作爲活躍APP或者在後臺 - 但沒有正常工作時,應用程序是運行。

我試圖註銷launchOptions NSDictionary在application: didFinishLaunchingWithOptions:看看是什麼加載它的帶來 - 但它出現爲「(空)」。所以它基本上不包含任何內容 - 這不合理,因爲它不應該包含通知的負載?

任何人有任何想法如何使推送通知的工作,當他們到達時,應用程序沒有運行?

編輯:這裏是我使用的application: didReceiveRemoteNotification只是爲了看看什麼是什麼代碼:

if (UIApplicationStateBackground) { 

    NSLog(@"==========================="); 
    NSLog(@"App was in BACKGROUND..."); 
} 
else if (UIApplicationStateActive == TRUE) { 
    NSLog(@"==========================="); 
    NSLog(@"App was ACTIVE"); 
} 
else { 
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber: 99]; 
    UIAlertView *BOOM = [[UIAlertView alloc] initWithTitle:@"BOOM" 
                message:@"app was INACTIVE" 
                delegate:self 
             cancelButtonTitle:@"a-ha!" 
             otherButtonTitles:nil]; 
    [BOOM show]; 
    NSLog(@"App was NOT ACTIVE"); 
} 

所以這是應該採取應用程序的所有國家的照顧 - 但它不是。推送通知只適用於應用程序運行時 - 無論是在後臺還是在前臺...

======================== ========================

UPDATE/EDIT#2: 根據「@dianz」建議(下文)我修改了代碼我application: didFinishLaunchingWithOptions的,包括以下內容:

UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
if (localNotif) { 
    NSString *json = [localNotif valueForKey:@"data"]; 

    UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"appDidFinishWithOptions" 
                message:json 
               delegate:self 
             cancelButtonTitle:@"cool" 
             otherButtonTitles:nil]; 
    [bam show]; 

} 

這確實讓AlertView框出現,但似乎沒有有效載荷:該AlertView的標題顯示出來(「appDidFinishWithOptions」),但JSON的NSString出現EMPTY ...將繼續調整...

======================

編輯#3 - 其現在的工作幾乎 100%
所以,在didFinishLaunchingWithOptions

UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
    if (localNotif) { 
     // Grab the pushKey: 
     pushKey = [localNotif valueForKey:@"pushKey"]; 
     // "pushKey" is an NSString declared globally 
     // The "pushKey" in the "valueForKey" statement is part of my custom JSON Push Notification pay-load. 
     // The value of pushKey will always be a String, which will be the name of the 
     // screen I want the App to navigate to. So when a Notification arrives, I go 
     // through an IF statement and say "if pushKey='specials' then push the          
     // specialsViewController on, etc. 

     // Here, I parse the "alert" portion of my JSON Push-Notification: 
     NSDictionary *tempDict = [localNotif valueForKey:@"aps"]; 
     NSString *pushMessage = [tempDict valueForKey:@"alert"]; 


     // Finally, ask user if they wanna see the Push Notification or Cancel it: 
     UIAlertView *bam = [[UIAlertView alloc] initWithTitle:@"(from appDidFinishWithOptions)" 
                 message:pushMessage 
                delegate:self 
              cancelButtonTitle:@"Cancel" 
              otherButtonTitles:@"View Info", nil]; 
     [bam show]; 

    } 

我接下來實現了alertView: clickedButtonAtIndex方法,以查看用戶在AlertView上選擇的內容並據此進行操作。

這與邏輯didReceiveRemoteNotification一起完美工作。然而,當應用程序沒有運行,並且我發送推送通知時,如果我一到它就不點擊推送通知警報,而是等待它淡出(發生這種情況在3-4秒之後),然後然後我點擊應用程序的圖標 - 該圖標現在的BADGE爲1 - 應用程序啓動,但在啓動時我沒有收到推送通知警報。它只是坐在那裏。

想我需要弄清楚排列在下...

+2

所以是你能得到通知時,你沒有點擊推送通知,並直接點擊應用程序圖標? –

+1

你有這個工作。 ?我的意思是當應用程序處於非運行狀態時如何處理推送通知?如果如果您收到很多通知並且您沒有打開該應用程序,那麼您也不會點擊系統的通知面板。你如何保留這些推動以便以後檢索。 –

+0

你碰巧得到最後的排列工作嗎? –

回答

33

當您的應用程序未運行或死亡,並且您點擊推送通知時,此功能將觸發;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

所以你應該處理它這個樣子,

UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
if (localNotif) { 
    NSString *json = [localNotif valueForKey:@"data"]; 
    // Parse your string to dictionary 
} 
+1

我在'application:didFinishLaunchingWithOptions:'中做了一些類似於此的事情。我寫道:'NSDictionary * launchDic = [launchOptions objectForKey:@「UIApplicationLaunchOptionsRemoteNotificationKey」]; NSLog(@「contains:%@」,launchDic);' - 我從NSLog得到的輸出是「(NULL)」。但我會嘗試使用'UILocalNotification'變量,就像你擁有它,而不是一個NSDictionary變量。也許這會有所作爲。我會發布我的結果有點... – sirab333

+0

有趣的 - 請參閱我的問題中的「編輯」再次(頂部)更新您的建議剛剛做了什麼... – sirab333

+0

嘗試登錄localNotif? – dianz

1

試着要去didReceiveRemoteNotification方法和處理它。在那裏,您可以通過執行applicationState的條件來檢查應用程序狀態,例如檢查它是否爲UIApplicationStateActive或其他。

+0

我處理'applicationState' - 我的事業,我不想我的問題是太久之前沒有提到它 - 但我會添加代碼,以我的問題上去頂,很酷吧? – sirab333

7

我試圖@ dianz的回答,這不是爲我工作,但我得到了答案幫助。

對我而言;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

NSDictionary *apnsBody = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
if (apnsBody) { 
    // Do your code with apnsBody 
} 
11
更好

,如果你重寫didReceiveRemoteNotification 在這裏你去

NSDictionary * pushNotificationPayload = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 
if(pushNotificationPayload) { 
    [self application:application didReceiveRemoteNotification:pushNotificationPayload]; 
} 

這將再次觸發didReceiveRemoteNotification方法,因爲它在應用程序運行時運行您push notification代碼將執行相同。

+2

您是否能夠正常工作。 ?我的意思是當應用程序處於非運行狀態時如何處理推送通知?如果如果您收到很多通知並且您沒有打開該應用程序,那麼您也不會點擊系統的通知面板。你如何保留這些推動以便以後檢索。 –

+0

謝謝你! :-) – ArturOlszak

+0

在哪裏寫這段代碼? –

0

試試這個

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 

    //register notifications 
    if([application respondsToSelector:@selector(registerUserNotificationSettings:)]) // ios 8 
    { 
     [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]]; 
     [application registerForRemoteNotifications]; 
    } 
    else // ios 7 
    { 
     [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge]; 
    } 

    // open app from a notification 
    NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 

    if (notification) 
    { 
     //your alert should be here 
    } 

    // Set icon badge number to zero 
    application.applicationIconBadgeNumber = 0; 

    return YES; 
} 
2

雖然這已經回答了,沒有提供答案的實際工作正常。這是我能夠工作的實現。

此代碼放在application:didFinishLaunchingWithOptions:

斯威夫特:

if let options = launchOptions, notification = options[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject] { 
    // NOTE: (Kyle Begeman) May 19, 2016 - There is an issue with iOS instantiating the UIWindow object. Making this call without 
    // a delay will cause window to be nil, thus preventing us from constructing the application and assigning it to the window. 
    Quark.runAfterDelay(seconds: 0.001, after: { 
     self.application(application, didReceiveRemoteNotification: notification) 
    }) 
} 

的Objective-C:

if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { 
    [self application:application didReceiveRemoteNotification:launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]]; 
} 

一對夫婦的注意事項:

  • 可能由於iOS隊列分配的方式,在被殺死後啓動應用程序時,根UIApplication.sharedApplication().window對象爲零。增加1毫秒的延遲解決了這個問題。沒有測試Objective-C

  • 需要投到[NSObject:AnyObject]以避免類型衝突,但我沒有嘗試過這麼多;在您自己的項目中實施時請記住它。 Objective-C不需要這個。

  • 夸克只是一個有趣的小型圖書館,用在我所有包含有用和常用的擴展和方法的項目中。只需使用適合您應用需求的任何形式的延遲。

0

斯威夫特3的Xcode 8.3.2

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
    // your code here 

    // Check if app was not running in background and user taps on Push Notification 
    // This will perform your code in didReceiveRemoteNotification where you should handle different application states 
    if let options = launchOptions, let notification = options[UIApplicationLaunchOptionsKey.remoteNotification] as? [NSObject : AnyObject] { 
     self.application(application, didReceiveRemoteNotification: notification) 
    } 

    return true 
} 
1

我有同樣的問題,但我終於可以用通知服務擴展處理推送通知時無效(不運行) 。這個解決方案是Apple Team Support推薦的,它只適用於iOS 10,我實現了它,它運行良好!我離開的鏈接:

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ModifyingNotifications.html

這是程序:

  1. 創建爲您的應用新的Notification服務擴展。打開您的項目並按下文件 - 新建 - 目標,然後在iOS部分選擇「通知服務擴展」選項。輸入擴展名和所需的信息。之後,Xcode將添加Objective C語言的兩個文件:.h和.m文件。

注:考慮您將使用三個標識符: 1)標識爲您的應用程序(你已經有了) 2)標識爲您的擴展(你將創建) 3)標識符爲應用程序組。 (你將創建)

  • 必須啓用應用組創建資源,你可以保存和讀取您的應用程序和擴展信息。點擊「顯示項目導航器」。進入目標列表中選擇您的主項目。然後,點擊「Capabilities」並打開名爲「App Groups」的選項。請添加App Group的標識符以識別共享資源。您應該爲您創建的擴展目標執行相同的步驟(選擇擴展名的目標 - 功能 - 打開「應用程序組」 - 爲App組添加相同的標識符)

  • 您應該添加標識符你的擴展到蘋果開發者網站以標識通知服務擴展,你也應該製作新的臨時配置文件(開發,AdHoc和/或生產)並將其與新的臨時配置文件相關聯。

  • 在兩個標識符(應用程序和擴展名)上,您都應該編輯它們並在其中啓用「應用程序組」服務。您應該將應用標識符組添加到應用程序組服務中。

  • 注:標識符App和標識符擴展應該有APP集團 相同的標識符。

  • 下載Xcode中上新的臨時配置文件,並將它們與通知服務擴展關聯。請確保你一切都安好。

  • 之後,進入您的應用和擴展程序的「功能」,打開「應用程序組」部分並更新它們。三個步驟 - 1)將App Groups權利添加到您的權利文件中,2)將App Groups功能應用於您的App ID,3)將App Groups添加到您的App ID - 應該被選中。

  • 回來到項目導航並選擇擴展的文件夾。打開.m文件。您將看到一個名爲didReceiveNotificationRequest的方法:(UNNotificationRequest *)請求。到這個方法將創建與SuiteName不同NSUserDefaults的正好等於標識符的應用程序組是這樣的:

    * NSUserDefaults的defaultsGroup = [[ALLOC NSUserDefaults的] initWithSuiteName:@ 「標識符的應用程序組」];

  • 在這種方法中,獲取通知的主體並將其保存到NSMutableArray中,然後將其保存到共享資源中。就像這樣:

  • - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler{ 
        self.contentHandler = contentHandler; 
        self.bestAttemptContent = [request.content mutableCopy]; 
    
        NSMutableArray *notifications = [NSMutableArray new]; 
        NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; 
        notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; 
        if (notifications != nil){ 
         [notifications addObject:self.bestAttemptContent.userInfo]; 
        }else{ 
         notifications = [NSMutableArray new]; 
         [notifications addObject:self.bestAttemptContent.userInfo]; 
        } 
        [defaultsGroup setObject:notifications forKey:@"notifications"];  
    } 
    
  • 最後,爲您的主項目的應用代表,在你的didFinishLaunchingWithOptions方法,恢復陣列到分享資源此代碼:
  • NSUserDefaults *defaultsGroup = [[NSUserDefaults alloc] initWithSuiteName: @"Identifier for app group"]; 
    NSMutableArray *notifications = [[defaultsGroup objectForKey:@"notifications"] mutableCopy]; 
    
  • 享受它!
  • 我希望每一步都清楚。我將寫一篇文章來實現這個解決方案,在圖像中添加圖片。另一點你應該考慮的是它不適用於無聲推送通知。

    相關問題