web-dev-qa-db-ja.com

iOS 11上のアプリに配信されないサイレントプッシュ

IOS 11 Beta 2では、アプリの状態(バックグラウンド/フォアグラウンド)に関係なく、サイレント通知はapplication:didReceiveRemoteNotification:fetchCompletionHandlerに配信されません。

UIApplicationDelegeteメソッドapplication:didReceiveRemoteNotification:fetchCompletionHandlerを実装し、次のようなサイレントプッシュを送ります。

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 

しかし、デリゲートメソッドはiOS 11では呼び出されません。

他のバージョンのiOSでは問題なく動作します。ドキュメントセクション サイレント通知の設定 では、他に何もするべきであるとは言及されていません。

これはiOS 11のバグですか?それともiOS 11の新しい機能を見逃したのですか?

サイレントプッシュを送信するために必要とされるべきではないUserNotificationフレームワークについて話したり使用したりしていないことに注意してください。

これは問題を説明する サンプルプロジェクト です(あなた自身のバンドルIDを設定する必要があります)。

サンプルプロジェクトをランチして上記のペイロードをアプリに送信すると、macOSコンソールを使用してPushがデバイスに正しく配信されるがアプリには配信されないことを確認できます。

アップデート10.08

動作はランダムであるようです。デバイスを再起動した後にペイロードが正しく配信されても​​、しばらくすると機能しなくなることがあります。

次のスクリーンショットでわかるように、1とマークされたプッシュはデバイスにのみ配信され、プッシュ2(デバイスの再起動後)もアプリに配信されます。

enter image description here

アップデート14.08 - iOS 11 Beta 6

それでも同じ動作です。もう1つうまくいくはずのことではありませんが、次のとおりです。アプリケーションのスキームが「実行可能ファイルが起動されるのを待つ」に設定されている場合、サイレントプッシュはアプリを起動してバックグラウンドで起動するはずです。

enter image description here

アップデート21.08 - iOS 11 Beta 7

それでも同じ動作で、バグレポートはAppleからのアップデートではありません。

アップデート29.08 - iOS 11 Beta 8

それでも同じ問題です。私が今使っている再現の手順は次のとおりです。

  • Xcodeプロジェクトスキームで、「実行可能ファイルが起動されるのを待つ」を選択します。
  • didReceiveRemoteNotification: fetchCompletionHandlerにブレークポイントを追加します
  • 端末でアプリを起動する
  • 上記のサイレントプッシュを送信する

予期されるもの:アプリは中断状態からバックグラウンドに移行し、didReceiveRemoteNotification: fetchCompletionHandlerが呼び出されます

実際:何も起こりません

アップデート06.09 - iOS 11 Beta 10

私はまだ同じバグのある行動をしています。アップルからのチケットは次の答えで更新されました:

Apple Developer Relations September 6 2017、10:42 PM Engineeringがこの問題に関して以下のフィードバックを提供しています。

サンプルアプリケーションを実行して動作をテストできました。説明されているようにこれをテストしても、問題は発生しませんでした。

バックグラウンドで実行されているときにプッシュがアプリに届くことは保証されていません。ここにあるログは、アプリが起動するのに十分に使用されているとは思わないことを示しています。

状況が良いときにプッシュを配信するのを見ます。

これは正しく機能していると考えています。

アップデート11.09

私のAppleバグレポートはクローズされ、オープンのままの33278611の複製としてマークされました

アップデート13.09 - iOS 11 GM

Kam800のコメント(下記参照)のおかげで、私はより多くのテストをし、それらの観察を思いついた。

IOS 11のdasd DuetActivitySchedulerDaemonには、データプッシュを完全に破棄するかデータプッシュ配信を遅らせる新しいデーモンがあるようです。

配達延期

コンソールログ

default 13:11:47.177547 +0200   dasd    DuetActivitySchedulerDaemon CANCELED: com.Apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>!   lifecycle   com.Apple.duetactivityscheduler
default 13:11:47.178186 +0200   dasd    DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private>   default com.Apple.duetactivityscheduler
default 12:49:04.426256 +0200   dasd    DuetActivitySchedulerDaemon Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017   default com.Apple.duetactivityscheduler
default 13:21:40.593012 +0200   dasd    DuetActivitySchedulerDaemon Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>)  scoring com.Apple.duetactivityscheduler
default 13:21:40.594528 +0200   dasd    DuetActivitySchedulerDaemon Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private>  default com.Apple.duetactivityscheduler

延期された配達問題

  • データプッシュ配信が延期されてアプリが起動されると、データプッシュは配信日に到達したときにのみ配信されます。これは将来的に数分になります。これは、データプッシュを使用して新しいアプリのコンテンツを次回の起動に備えて保持するという目的を完全に無効にします。私はここでもまたAppleの文書を引用する。

「サイレント通知は、アプリケーションが実行されていない場合でも、アプリケーションを最新の状態に保つのに役立つため、ユーザーエクスペリエンスが向上します。」

  • 2つのデータプッシュが中断されたアプリに送信されると、それらはアプリを直接ウェイクアップするのではなく、iOS 11によって延期されます。配達時間に達すると、最後のdata Pushだけが配達されます。以前のプッシュは失われ、デリゲートメソッドを介して配信されないため、データが失われます。

配達はキャンセルされました

コンソールログ

default 13:35:05.347078 +0200   dasd    DuetActivitySchedulerDaemon com.Apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
 ], FinalDecision: Must Not Proceed}    scoring com.Apple.duetactivityscheduler

配達の問題をキャンセルしました

この場合、データPushは完全に失われ、iOS 11では正しく配信されていましたがiOS 11では配信されませんでした。

アップデート19.09 - iOS 11 GM

また、アプリケーションがフォアグラウンドにあり、通知がアプリに配信されない場合は、コンソールに次のログが表示されます。

default 08:28:49.354824 +0200   apsd    apsd    <private>: Received message for enabled topic '<private>' onInterface: NonCellular with payload '<private>' with priority 10 for device token: NO   courier-oversized   com.Apple.apsd

fault   08:33:18.128209 +0200   dasd    Foundation  <NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNull'. Allowed classes are '{(
    NSArray,
    NSData,
    NSString,
    NSNumber,
    NSDictionary,
    NSUUID,
    _DASActivity,
    NSSet,
    _DASFileProtection,
    NSDate,
    NWParameters,
    NWEndpoint
)}'.    general com.Apple.foundation.xpc
152
Jan

だからiOS 11.1 beta 1のリリースノートは言う

iOS 11.1 Beta 1がリリースされたばかりで、「通知の解決済みの問題•サイレントプッシュ通知がより頻繁に処理されます。(33278611)

私はいくつかのテストをしました、そしてそれは確かに固定されているようです:

中断状態

一時停止モードでアプリを起動してサイレントプッシュを送信すると、アプリはバックグラウンドに戻り、didReceiveRemoteNotification:fetchCompletionHandlerデリゲートが呼び出されます。

前景状態

同様に、アプリケーションがフォアグラウンドにあり、サイレントプッシュが送信されると、デリゲートは期待どおりに呼び出されるようです。これは以前のiOS 11バージョンではランダムに動作していなかったので、もっとテストした後に確認します。

29
Jan

私もこの問題に見舞われたので、ここに私の2セントを加えたいと思いました、そして私は、Appleがこの問題に関していくつかのレーダーを閉じてそれらが再現できなかったと言って気付いた。私が見つけた興味深いことは、それがデバッガに接続されている間にアプリがバックグラウンドである場合、プッシュが配信されることです。

デバッガを終了し、電話を抜いてアプリを起動し、サイレントなプッシュペイロードを送信すると、アプリが起動しなくなります。コンソールログに、システムがアプリケーションへのペイロードの配信をキャンセルしていることがわかります。

問題を再現した小さなサンプルアプリでレーダーを送信しました。私はまた、私のチケットで作業している人が、この問題を再現するためにデバッガに接続されているアプリケーションを実行してはならないことをレーダーで明確に指摘しました。これがリンクです: https://bugreport.Apple.com/web/?problemID=34461063

うまくいけば、これはこの問題に関していくらかの進歩をもたらすでしょう。

16
Bill Dunay

IOS 11の新しい動作のように見えます。iOS 11 beta 10は、この問題に関するいくつかの説明的なログを提供します。

default 23:18:51.806011 +0200   dasd    com.Apple.pushLaunch.com.acme.Acme:F7E7D0:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
    {name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
    {name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
 ] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default 23:18:51.806386 +0200   dasd    'com.Apple.pushLaunch.com.acme.Acme:F7E7D0' has compatibility score of 1.000000 with 'com.Apple.CFNetwork-cc-111-79:E7272D'. Relaxing scores.
default 23:18:51.806855 +0200   dasd    'com.Apple.pushLaunch.com.acme.Acme:F7E7D0' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0

サイレントプッシュはすべてiOSに配信されるように見えますが、dasdデーモンは、サイレントプッシュをアプリに配信する必要があるかどうかを判断するために、いくつかのポリシーを使用します(バッテリレベルなど)。私は昨日の夜に1つのサイレントプッシュを受け取ることができましたが、そのとき私のiPhoneは充電器に接続されていました - おそらくBatteryLevelPolicyスコアはその1つのサイレントプッシュを受け取るのに十分に高かった。

AppleはこのiOS側の動作に関する公式な情報を提供していません。サーバ側のスロットル調整に関する情報しかありません。

サイレント通知は、アプリをバックグラウンドで起動させ続けるためのものではなく、優先度の高い更新を目的としたものでもありません。 APNはサイレント通知を低い優先順位として扱い、総数が過剰になると、配信を完全に抑制することがあります。実際の制限は動的であり、状況に応じて変わる可能性がありますが、1時間に数回を超える通知を送信しないようにしてください。

私は私のアプリを修正するので、私は私の指を交差させ、彼らはその振る舞いを変更しました:)一方、この変更は良いです - 多くのことのうちの1つ。

11
kam800

iOS 11.1ベータリリースノートには以下が含まれます。通知解決された問題サイレントプッシュ通知はより頻繁に処理されます。 (33278611)

7
Andrew Gould

Apple Developer Relationsが私のレーダーにコメントを追加しました:

この問題は最新のiOS 11.2 Betaで解決されると考えています。

最新のiOSベータ版でテストしてください。それでも問題が解決しない場合は、関連するログや調査に役立つ可能性のある情報でバグレポートを更新してください。

https://developer.Apple.com/download/

現在iOS 11.2ベータ版をインストールしています - サイレントプッシュ動作をテストします

6

iOS 11.1 Beta 2にも含まれています

Notifications
Resolved Issues
• Silent Push notifications are processed more frequently. (33278611)

リリースノートで - 今それをテストします。

アップデート - 11.10.2017 - iOS 11.1 Beta 2

「現実世界のシナリオ」で2日間アプリを使用した後、iOSのこのバージョンには実際の改善が見られます。私は慎重にこれが修正されていると信じ始めています。

5

iOS 11.4.1、Swift 4

私は(CloudKitから)到着していないサイレントプッシュに関する問題を抱えていました、そして私は皆がここで言及したすべてを試みました。それから私はこのように私のCKNotificationInfo()オブジェクトに空白のalertBodyを設定することを試みることにしました:

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""

これはプッシュがより高い優先順位で送信されるようにしました(しかしそれらはまだ静かなプッシュでした)そして私はもはやプッシュが無視されていたという私のデバイスログのエラーを得ませんでした。

それが誰かに役立つことを願っています。 :)

3
Clifton Labrum

回避策として、 "notification"キーを追加し、 "title"の内側に値として空の文字列を追加します。これはappDelegateでdidReceiveコールバックを起こすことです。

2
elkorb

IOS 10までプッシュ通知を受け取り、application:didReceiveRemoteNotification:fetchCompletionHandlerが正しく呼び出されるまで、私は自分のアプリで同様の問題を抱えていました。ただし、iOS 11に更新されるとプッシュ通知が機能しなくなりました。

プッシュ通知ペイロードでcontent-available:1およびmutable-content:1を使用していたにもかかわらず、コードの問題がありましたが、Background Fetchオプションがオンになっていませんでした。しかし、それはiOS 10まで完全に働いていました。

Make sure you turned ON both these capabilities.

バックグラウンドフェッチ機能をオンにした後、それは今働いています

2
Sudeep george

この答えを書いている時点で、私は Bill Dunayの 答えとまったく同じ問題に直面しています。

私の要件は、アプリがフォアグラウンドにあるときはサイレント通知を受け取ることであり、アプリがバックグラウンドにあるとき、または実行されていないときには何もしないことです。そして私の回避策はこれでした。バッジを使用していないので、ゼロに設定しても問題にはなりません。

{
    "aps" : {
        "badge" : 0,
        "sound" : ""
    },
    "mydata": {  
        "foo": "bar"  
    }  
}

私は故意に "content-available"を使用していないことに注意してください。これを設定すると、iOS最適化ロジックは通知の配信を遅延/キャンセルします。

1
Rammohan Raja

そのため、これは確かにiOS 11のバグであり、iOS 11 beta 3で修正されました。サイレントPushがフォアグラウンドまたはバックグラウンドの両方で受信されたときに、application:didReceiveRemoteNotification:fetchCompletionHandlerが正しく呼び出されるようになりました。

UPDATE

いいえ、それは修正されておらず、iOSベータ3と4でまだ起こっています

1
Jan

私はいくつかの通知について同じ問題を抱えています(必ずしも黙っているわけではありません)。

すべての更新と回答を確認した後、2つの更新を追加することができます。

  • 通知を受け取っているときにUIApplication.shared.isRegisteredForRemoteNotificationsメソッドにアクセスすると、Xcodeに何も報告せずにアプリケーションが停止することがわかりました。メソッドにアクセスする通知を受け取ったら、コードを実行しているかどうかを確認してください。 ( isRegisteredForRemoteNotificationsでUIをsemaphore_wait_trap でロックしています)。

    • "title-loc-args" : [3333]が文字通り3333を受け入れず、文字列"title-loc-args" : ["3333"]として受け入れたために、コンソールでプッシュ通知の解析エラーが発生したことを発見しました。これは私が上記のメソッドにアクセスした後に私のインターフェース全体を失速させました、それはiOS 11でのみ、それはiOS 12で動作します。
  • 私は、まったく同じコードで、iOS 12.0(16A5366a)でも問題なく動作することもわかりました。しかし、iOS 11ではそうなっています。

1
Rageofflames

私の場合、サーバーサイトで仕事が行われた後にサイレント通知がuiの更新に使用されたため、関連性のないコンテンツをアプリに含めるのは面倒でした。サイレント通知のペイロードにはタイトルと本文も含まれているため、アクティブでも非アクティブでも通知を受け取るためにこれらのメソッドを実装します。課金はしません。

これを機能させるために、デリゲートを追加し、UNUserNotificationCenterDelegatename__プロトコルとwillPresent notification(iOS 10+)メソッドを使用して拡張機能を作成します。これは毎回正しいペイロードでトリガーされます。アプリがアクティブなときに通知を表示しないようにするには、バッジまたは音声で補完を呼び出します。私はこのようなものになった

    import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    // MARK: - Lifecycle
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }

    //this was only method to handle notifications before
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        //process silent notification
        completionHandler(UIBackgroundFetchResult.newData)
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //proces notification when app is active with `notification.request.content.userInfo`
        if UIApplication.shared.applicationState == .active {
            completionHandler(.badge)
        }else {
            completionHandler(.alert)
        }
    }
}

アプリがバックグラウンドでサイレント通知が行われているときにこれらの状態を機能させるには、通知センターからapplicationDidBecomeActivename__で直接通知を受け取るメソッドを呼び出しません。

UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
            debugLog(message: "unprocessed notification count: \(notifications.count)")
            if notifications.count > 0 {
                notifications.forEach({ (notification) in
                    DispatchQueue.main.async {
                        //handle `notification.request.content.userInfo`
                    }
                })
            }
        }
0
Ondřej H