web-dev-qa-db-ja.com

didReceiveRemoteNotificationバックグラウンド時

この種の質問は何度も聞かれましたが、特定の状況が続いています。

アプリケーションがアクティブで、プッシュメッセージを受信すると、カスタムペイロードなどを正常に解析できます。

ただし、アプリケーションがバックグラウンドにあり、プッシュが到着すると、ユーザーはdidReceiveRemoteNotificationを呼び出してdidFinishLaunchingWithOptionsを呼び出すために、[表示/開く]ボタンをクリックする必要があります。

バックグラウンドにいるときにユーザーにUIAlertを要求するか、ローカル設定に基づいてプッシュメッセージを抑制するかをアプリケーションに決定させる必要があります。

助けていただければ幸いです

51
Erwin

アプリは、可能なすべてのプッシュ通知配信状態を処理する必要があります。

  • アプリが起動されました

  • アプリがバックグラウンドからフォアグラウンドに移動したばかりです

  • アプリは既にフォアグラウンドで実行されていました

配信時にプッシュ通知を表示するために使用されるプレゼンテーション方法を選択することはできません。プッシュ通知は、通知自体にエンコードされます(オプションのアラート、バッジ番号、サウンド)。ただし、おそらくアプリとプッシュ通知のペイロードの両方を制御しているため、アラートビューとメッセージがユーザーに既に表示されているかどうかをペイロードで指定できます。アプリが既にフォアグラウンドで実行されている場合にのみ、ユーザーがアラートを介して、またはホーム画面から定期的にアプリを起動しただけではないことがわかります。

次のコードを使用して、didReceiveRemoteNotificationでアプリがフォアグラウンドになったかどうかを確認できます。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateActive )
        // app was already in the foreground
    else
        // app was just brought from background to foreground
    ...
}
150
Bogatyr

パス content-available = 1ペイロードを使用して、バックグラウンドでもdidReceiveRemoteNotificationを呼び出します。例えば.

{
    "alert" : "",
    "badge" : "0",
    "content-available" : "1",
    "sound" : ""
}
14
Sandeep Kumar

アプリがバックグラウンドにあるときに受信したプッシュ通知を管理するには、いくつかのことを行う必要があります。

まず、サーバー側で、プッシュ通知ペイロードに{"aps":{"content-available" : 1... / $body['aps']['content-available'] =1;を設定する必要があります。

第二に、Xcodeプロジェクトでは、「リモート通知」を改善する必要があります。これは、プロジェクトのターゲット->機能に移動し、機能スイッチを有効にして、リモート通知チェックボックスをオンにすることで作成されます。

3番目に、didReceiveRemoteNotificationを使用する代わりに、application:didReceiveRemoteNotification:fetchCompletionHandler:を呼び出す必要があります。これにより、通知を受信した時点で、バックグラウンドで必要なタスクを実行できます。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 
{

 if(application.applicationState == UIApplicationStateInactive) {

     NSLog(@"Inactive - the user has tapped in the notification when app was closed or in background");
     //do some tasks
    [self manageRemoteNotification:userInfo];
     completionHandler(UIBackgroundFetchResultNewData);
 }
 else if (application.applicationState == UIApplicationStateBackground) {

     NSLog(@"application Background - notification has arrived when app was in background");
     NSString* contentAvailable = [NSString stringWithFormat:@"%@", [[userInfo valueForKey:@"aps"] valueForKey:@"content-available"]];

     if([contentAvailable isEqualToString:@"1"]) {
         // do tasks
         [self manageRemoteNotification:userInfo];
         NSLog(@"content-available is equal to 1");
         completionHandler(UIBackgroundFetchResultNewData);
     }
 }
 else {
     NSLog(@"application Active - notication has arrived while app was opened");
        //Show an in-app banner
         //do tasks
        [self manageRemoteNotification:userInfo];
         completionHandler(UIBackgroundFetchResultNewData);
     }
 }

最後に、この通知タイプを設定するときに、通知設定にUIRemoteNotificationTypeNewsstandContentAvailabilityを追加する必要があります。

これとは別に、通知が到着したときにアプリが閉じられた場合は、didFinishLaunchingWithOptionsでこれを管理する必要があり、ユーザーがプッシュ通知をタップした場合のみ:方法は次のとおりです。

if (launchOptions != nil)
{
    NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    if (dictionary != nil)
    {
        NSLog(@"Launched from Push notification: %@", dictionary);
        [self manageRemoteNotification:dictionary];
    }
}

プッシュ通知をタップしてアプリを起動すると、launchOptionsは!= nilになります。アイコンをタップしてアクセスすると、launchOptionsは== nilになります。

役に立つことを願っています。 ここではAppleが説明しています

13
AlbertoC

念頭に置いておくべきことは、PushメッセージがユーザーのiPhoneに到着し、アイコンバッジ番号(OSによって処理される)を除いて「キャンセル」をクリックすると、 -このプッシュイベントについて知って、さらにアクションを実行するバックグラウンドアプリ。

8
Di Wu

警告の言葉

アプリロジックは、プッシュ通知のカスタムデータに基づいた動作だと思います。これは、プッシュ通知の対象ではありません。アプリケーションのdidbecomeactiveで代わりに行うべきことは、必要なデータをサーバーに要求し、とにかくペイロードとして送信して、ペイロードではなくそのデータに依存することです。

ドキュメントにも記載されている それがベストプラクティスであるためです。 Appleは、プッシュ通知が100%の時間に受信されることを保証しません。

重要:通知の配信は「ベストエフォート」であり、保証されていません。新しいデータが利用可能であることをユーザーに通知することのみを目的として、アプリにデータを配信することを意図していません。

ただし、バッジをクリックしてアプリを開くユーザーに依存せずに、たとえばバッジが変更されたかどうかを示すには、次のようにします。

A。サーバーから送信されたプッシュ通知のペイロードに(正しい)バッジ番号を追加します。たとえば、次のようになります。

{
    "aps" : {
        "alert" : "You got your emails.",
        "badge" : 9
    }
}

B。たとえば、NSUserDefaultsに保存することで、バッジ番号をアプリで永続的に追跡します。

次に、applicationDidBecomeActiveapplicationIconBadgeNumberUIApplicationプロパティを以前に保存したバッジカウントと比較し、それが増減しているかどうかを確認し、それに基づいて更新を行います。

 - (void)applicationDidBecomeActive:(UIApplication *)application
    {

        NSNumber *badgecount = [[NSUserDefaults standardUserDefaults] objectForKey:@"badgecount"];
        if (!badgecount) badgecount = @(0);

        if ([UIApplication sharedApplication].applicationIconBadgeNumber != [badgecount integerValue]) {
            //store the new badge count
            badgecount = [NSNumber numberWithInteger:[UIApplication sharedApplication].applicationIconBadgeNumber];
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setObject:badgecount forKey:@"badgecount"];
            [defaults synchronize];

            // do some stuff here because it's different
        }

    }
2
morksinaanab

最近のiOS-8と思う-リモート通知をバックグラウンドモードとして有効にしている場合、1つの秘isは、前景をフラグとして入力しているかどうかを追跡することです。

@interface AppDelegate ()

@property (assign, atomic, getter=isEnteringForeground) BOOL enteringForeground;

@end

- (void) applicationWillEnterForeground: (UIApplication *) application
{
    self.enteringForeground = YES;
}

- (void) applicationDidBecomeActive: (UIApplication *) application
{
    self.enteringForeground = NO;
}

- (void) application: (UIApplication *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^) (UIBackgroundFetchResult)) completionHandler
{
    const BOOL launchedFromBackground = !(application.applicationState == UIApplicationStateActive);
    const BOOL enteringForeground = self.enteringForeground;

    if (launchedFromBackground && enteringForeground) {
        // The user clicked a Push while the app was in the BG
    }
}
0
mszaro