Wenn E-Mails zugestellt werden: Bekämpfung des Verlusts von Push-Benachrichtigungen in iOS

Der E-Mail-Client ist für den Benutzer eine einfache Anwendung. Yandex.Mail-Entwickler scherzen sogar, dass die Anwendung nur drei Bildschirme enthält: eine Liste von Buchstaben; einen Brief senden; über Bildschirm.

Aber viele interessante Dinge passieren unter der Haube. Wie viele mobile Apps verwendet Mail Push-Benachrichtigungen, um mit Benutzern zu interagieren. Wie bei vielen iOS-Anwendungen verliert Mail aufgrund der Art des Apple Push Notification Service einige Benachrichtigungen.

Asya Sviridenko , Leiterin der Yandex.Mail iOS-Gruppe, wird beweisen, dass es trotz der Einschränkungen des Systems möglich und notwendig ist, mit dem Verlust von Push-Benachrichtigungen umzugehen, wenn diese für Ihre Anwendung kritisch sind. Dies gilt für Mail, da der Benutzer die Anwendung über Push-Benachrichtigungen über neue Briefe installiert. Wenn für Ihre Anwendung die Zustellung von Push-Benachrichtigungen nicht so wichtig ist, ist es immer noch interessant herauszufinden, welche Fahrräder das Handy Yandex.Mail angehäuft hat.


Es geht um Remote-Benachrichtigungen, dh Benachrichtigungen, die vom Server über APNs (Apple Push Notification Service) eingehen. Wir werden nicht auf lokale Benachrichtigungen eingehen und über Folgendes sprechen:

  • Wie sieht die API für die Arbeit mit Push-Benachrichtigungen aus? Betrachten Sie ein Push-Benachrichtigungs-Zustellungsschema und wo Verluste in diesem Schema auftreten können.
  • Wie haben Sie sich entschieden, mit Verlusten in Yandex.Mail umzugehen - der Warteschlange für Push-Benachrichtigungen?
  • Wie man sich anmeldet und welche anderen Schwierigkeiten auftreten können.

Was wir haben und wo wir verlieren


Jetzt ist die API für die Arbeit mit Push-Benachrichtigungen leistungsfähig genug, um viele interessante Dinge zu tun. Das war aber nicht immer der Fall.



Bisher sahen Push-Benachrichtigungen genau so aus - es war ein unglückliches blaues Dashboard, das auf dem Bildschirm auftauchte, die Arbeit mit der aktuellen Anwendung blockierte, nichts zuließ und dann für immer verschwand, und es gab keine weiteren Erinnerungen daran.

Seitdem ist genug Zeit vergangen.



Für uns als Entwickler begann alles in iOS 3, als Push-Benachrichtigungen für Bibliotheken von Drittanbietern verfügbar wurden.

Das Benachrichtigungscenter wurde in iOS 5 angezeigt, und Push-Benachrichtigungen wurden nicht mehr ausgeführt. Jetzt verbleiben sie im Benachrichtigungscenter, wo sie erneut angezeigt werden können.

IOS 6 führte Do Not Disturb ein . Der Benutzer hat die Möglichkeit, den Zeitraum festzulegen, in dem er keine Benachrichtigungen erhalten möchte.

Diese Änderungen betrafen hauptsächlich, wie der Benutzer mit Push-Benachrichtigungen arbeiten kann, wie sie sein Leben komfortabler gestalten können und nicht, wie Entwickler Benachrichtigungen beeinflussen können.

Für Entwickler war iOS 8 und das Aufkommen der Benachrichtigungsaktion ein wichtiger Meilenstein, mit dem Aktionen, die für eine bestimmte Anwendung spezifisch sind, durch Push-Benachrichtigungen ausgeführt werden konnten.

IOS 10 führt die Notification Service Extension und die Notification Content Extension ein . Mit der ersten Option können Sie die Push-Benachrichtigung ändern, bevor sie dem Benutzer angezeigt wird. Die zweite Möglichkeit besteht darin, eine Benutzeroberfläche per Push-Benachrichtigung unter Push-Benachrichtigung anzuzeigen, in der Sie beispielsweise detailliertere Informationen anzeigen können. In iOS 10 war diese Benutzeroberfläche nicht anklickbar. Sie können sie ansehen und nicht berühren.

IOS 11 führte die Datenschutzeinstellungen für Benachrichtigungen ein . Jetzt kann der Benutzer in die Einstellungen gehen und angeben, ob der Inhalt der eingehenden Benachrichtigungen angezeigt werden soll. Dies ist ein großer Schritt in Richtung Sicherheit. Es waren nur 8 Versionen von iOS erforderlich, um zu verstehen, dass nicht alle Benutzer möchten, dass persönliche Informationen plötzlich auf dem auf dem Tisch liegenden iPhone angezeigt werden.

In iOS 12 wurde es möglich, Push-Benachrichtigungen nach Thread-ID zu gruppieren , und die Benutzeroberfläche, die wir in iOS 10 mithilfe der Benachrichtigungsinhaltserweiterung erhalten haben, ist anklickbar. Jetzt können Sie dort Schaltflächen und Gestensteuerelemente hinzufügen - alles, was dem Benutzer bei der Interaktion mit der Benutzeroberfläche hilft.

Push-Benachrichtigungen heute


Wie Sie sehen können, haben Push-Benachrichtigungen einen langen Weg zurückgelegt, und heute können Sie mit ihrer Hilfe wirklich viele Dinge tun.

SMS und Lokalisierung


Nach wie vor können wir Textnachrichten in einer Push-Benachrichtigung senden. Jetzt können Sie zusätzlich Schlüssel für die Lokalisierung angeben.

"aps" : { "alert" : { "title" : "New Mail", "subtitle-loc-key" : "alert_subtitle_localization_key", "loc-key" : "alert_body_localization_key", } } 

Wenn Sie in der Nutzlastbenachrichtigung subtitle-loc-key und loc-key angeben, werden die erforderlichen Werte beim Eintreffen der Push-Benachrichtigung auf dem Gerät in der Datei Localizable.string der Anwendung gefunden, und dem Benutzer wird eine lokalisierte Nachricht angezeigt.

Ton und kritischer Alarm


Nach wie vor können Sie Nutzlastbenachrichtigungen Sounds hinzufügen.

 "aps" : { "sound" : { "critical" : 1, "name" : "bingbong.aiff", "volume" : 1.0, } } 

IOS 12 hat eine kritische Warnung. Dies sind Sounds, die auch dann abgespielt werden, wenn sich der Benutzer im Modus „Nicht stören“ befindet.

In der Regel benötigt der Benutzer beispielsweise nachts keine Anwendung mit einem Zeitschriftenabonnement, um zu melden, dass eine neue Nummer veröffentlicht wurde. Daher beschränkt Apple Anwendungen, die kritische Warnungen verwenden können. Wenn Ihre Anwendung mit Gesundheit, Sicherheit funktioniert oder Sie der Meinung sind, dass eine kritische Warnung den Benutzern bei der Interaktion mit Ihrer Anwendung wirklich helfen kann, schreiben Sie an Apple. Vielleicht können Sie diese Funktionalität nutzen.

Stille Benachrichtigungen


Der Benutzer sieht keine stillen Benachrichtigungen. Sie kommen direkt zur Anwendung, aktivieren sie und ermöglichen es Ihnen, einige Aktionen auszuführen, um die Anwendung auf den neuesten Stand zu bringen: Senden Sie eine Anforderung an den Server, fordern Sie Daten im Hintergrund an, aktualisieren Sie Daten aus der Datenbank, aktualisieren Sie die Benutzeroberfläche, damit der Benutzer sie sieht, wenn er die Anwendung betritt aktualisierte Daten.

 "aps" : { "content-available" : 1 //   alert, sound  badge   payload } 

Damit die Push-Benachrichtigung stumm geschaltet wird, müssen Sie in der Nutzlast Folgendes angeben: "content-available" : 1 . Geben Sie keine Warn-, Ton- und Ausweisschlüssel in der Nutzlast an - sie sind für Push-Benachrichtigungen, die dem Benutzer nicht angezeigt werden, völlig unbrauchbar.

Benachrichtigungsgruppierung


Um Nachrichten zu gruppieren, müssen Sie "Thread-ID" in der Nutzlast angeben. Es kann mehrere Werte in derselben Anwendung haben, wenn Sie auf unterschiedliche Weise gruppieren möchten: nach Konten, nach Empfängern, nach Themen.

 "aps" : { "thread-id" : "any_thread_identifier" } 

Dies ist sehr praktisch, da Push-Benachrichtigungen jetzt nicht den gesamten Speicherplatz auf dem gesperrten Bildschirm einnehmen, sondern in Gruppen zusammengefasst sind. Wenn Sie diese Funktion noch nicht verwenden, können Sie beginnen.

Ändern Sie die Benachrichtigung, bevor Sie sie anzeigen


Push-Benachrichtigungen können geändert werden, bevor sie angezeigt werden. Dazu müssen Sie der Anwendung die Benachrichtigungsinhaltserweiterung hinzufügen und die didReceive Methode überschreiben. Bei dieser Methode können Sie den Benachrichtigungsinhalt abrufen und ändern.

 "aps" : { "mutable-content" : 1 } override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else { contentHandler(request.content); return } mutableContent.subtitle = "Got it!" contentHandler(mutableContent) } 

Sie können beispielsweise einen Link zu Medieninhalten in der Benachrichtigung senden, den Inhalt in der Erweiterung herunterladen und den heruntergeladenen an die Benachrichtigung anhängen. Rufen Sie danach die Fertigstellung mit einem neuen Kontext auf und zeigen Sie dem Benutzer eine erweiterte Push-Benachrichtigung. Sie können den Titel, den Untertitel usw. ändern.

Ein weiterer interessanter Fall ist, dass Sie eine Push-Benachrichtigung mit einem verschlüsselten Kontext senden können, wenn die Daten zusätzlich geschützt werden sollen und Apple sie nicht gesehen hat. In der Benachrichtigungsinhaltserweiterung können Sie sie entschlüsseln und dem Benutzer bereits entschlüsselte Daten anzeigen.

Versteckter Benachrichtigungsinhalt


In iOS 11 wurde es möglich, den Inhalt von Push-Benachrichtigungen auszublenden, und wir als Entwickler können dies in keiner Weise beeinflussen. Wenn der Benutzer den "Benachrichtigungsinhalt ausblenden" angekreuzt hat, wird er auf die eine oder andere Weise ausgeblendet. Alles, was wir tun können, ist über die UNNotificationCategory, einen Platzhalter anzugeben, der anstelle des Inhalts angezeigt wird (standardmäßig ist es eine Benachrichtigung), und festzulegen, ob Titel oder Untertitel angezeigt werden sollen.

 let commentCategory = UNNotificationCategory(identifier: "comment-category", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: NSString.localizedUserNotificationString(forKey:"COMMENT_KEY",arguments: nil), options: [.hiddenPreviewsShowTitle]) 

Benachrichtigungsschritte ohne Starten der Anwendung


Um Push-Benachrichtigungsaktionen auszuführen, ohne die Anwendung selbst zu starten, müssen Sie eine Kategorie erstellen und eine Aktion hinzufügen. Die Kategoriekennung wird an das Kategoriefeld der Nutzlastbenachrichtigung übergeben. Sie können verschiedene Aktionen mit verschiedenen Arten von Benachrichtigungen verbinden.

 "aps" : { "category" : "message" } let action = UNNotificationAction(identifier:"reply", title:"Reply", options:[]) let category = UNNotificationCategory(identifier: "message", actions: [action], minimalActions: [action], intentIdentifiers: [], options: []) UNUserNotificationCenter.current().setNotificationCategories([category]) 

Reichhaltige Benachrichtigungen


In dieser Erweiterung können Sie zusätzliche Aktionen verarbeiten, die Sie der Push-Benachrichtigung hinzugefügt haben, und die benutzerdefinierte Benutzeroberfläche anzeigen.

Dazu müssen Sie der Anwendung die Benachrichtigungsinhaltserweiterung hinzufügen, eine Klasse definieren, die von UNNotificationContentExtension erbt, und dann wie mit einem normalen UIViewController damit arbeiten.

 class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var userLabel: UILabel? func didReceive(_ notification: UNNotification) { let content = notification.request.content self.title = content.title let userInfo = content.userInfo self.userLabel?.text = userInfo["video-user"] as? String } } 

Wenn Sie benutzerdefinierte Aktionen verarbeiten, ist es wichtig zu beachten, dass diese Aktionen es wert sind, die Benutzeroberfläche zu aktualisieren, die Sie dem Benutzer anzeigen. Sie müssen nicht versuchen, Geschäftslogik in dieser Erweiterung zu implementieren. Senden Sie eine Anforderung per Aktion mit einer Push-Benachrichtigung in der Hauptanwendung an den Server, und nicht hier. Dieser Ort ist nur für die Benutzeroberfläche.

Push-Benachrichtigungs-Zustellungsschema


Sehen Sie, wie viel Sie mit Push-Benachrichtigungen in iOS tun können. Von Version zu Version haben wir immer mehr neue Funktionen, aber das Push-Benachrichtigungs-Zustellungsschema ist jetzt genau das gleiche wie in iOS 3.



Man würde denken, dass das Push-Benachrichtigungs-Zustellungsschema von Anfang an in Ordnung war, aber es ist nicht so.

Das Push-Benachrichtigungs-Zustellungsschema enthält drei Hauptknoten:

  • Anbieter, der Push-Benachrichtigungen für Nutzdaten generiert;
  • APNs - Apple Push Notification Service, der eine Benachrichtigung liefert;
  • iOS-Gerät und Ihre Anwendung.

Ich werde den Teil überspringen, wie man sich registriert, einen Token erhält und wohin man ihn sendet. Angenommen, wir haben das alles. Was passiert als nächstes?

  • Der Anbieter generiert eine Nutzlast und sendet sie an APNs.
  • APNs senden es an das Gerät.
  • Der Benutzer sieht eine Push-Nachricht auf seinem Gerät.

Mail und viele andere Anwendungen verwenden ein erweitertes Push-Benachrichtigungs-Zustellungsschema. Die Benachrichtigungsdiensterweiterung wurde hinzugefügt, die Push-Benachrichtigungen mit "mutable-content" : 1 empfängt "mutable-content" : 1 . Der Anbieter ist in einen Server unterteilt, der sich mit der Backend-Logik der Anwendung befasst, und der Anbieter selbst, der Nutzdaten generiert und Abonnements verarbeitet.

In Yandex heißt der Anbieter, der Nutzdaten bildet, XIVA. XIVA ist eine Abonnementdatenbank. Mail verwendet XIVA, um mit Push-Benachrichtigungen als Bibliothek eines Drittanbieters zu arbeiten.

In Mail ist die Arbeit mit Abonnements nicht trivial organisiert. Wir unterschreiben nicht nur den Antrag für Benachrichtigungen, wir haben mehrere Konten. Wir können verschiedene Konten signieren oder innerhalb eines Kontos auswählen, für welche Ordner der Benutzer Benachrichtigungen erhalten möchte und für welche nicht. XIVA befasst sich mit all dem. Einige andere Yandex-Dienste funktionieren auch über XIVA: Alle Informationen zu Anwendungen, Benachrichtigungen, Abonnements und Token werden in XIVA gespeichert.

Wo sind die Verluste?


Das Push-Benachrichtigungs-Zustellungsschema enthält vier Pfeile. Bei drei dieser Übergänge können Verluste auftreten.

Zwischen dem Server und XIVA können im folgenden Fall Verluste auftreten. Der Benutzer hat einen Brief erhalten, der Server weiß davon, generiert eine Benachrichtigung und sendet sie an XIVA. XIVA kann diese Informationen jedoch verlieren, wenn ein Benutzer in der Anwendung einen bestimmten Ordner abonniert hat, während er offline war. Dann erhält XIVA keine Informationen über das Abonnement des Ordners. Wenn die Nutzdaten eintreffen, wird es einfach gelöscht und der Benutzer sieht die Benachrichtigung nicht.

Zwischen XIVA und APNs kann ein Netzwerkverlust auftreten. Wir können das Netzwerk kaum beeinflussen, daher werden wir uns nicht mit diesem Punkt befassen.

Zwischen APNs und Erweiterung oder zwischen APNS und iOS, wenn Sie keine Erweiterung verwenden. Dies ist die häufigste Art von Verlust. Solche Verluste treten auf, weil APNs nicht mehr als einen Push pro Anwendung auf dem Gerät speichern. Wenn der Benutzer, während er offline ist, mehrere Benachrichtigungen erhält, wird beim Online-Gehen nur die letzte Nachricht angezeigt.

Dies sind die gleichen Verluste, die es uns nicht ermöglichen, die Lieferung zu garantieren und uns auf Push-Benachrichtigungen zu verlassen. Apple schreibt eindeutig, dass die Lieferung nicht garantiert ist.

Zwischen der Erweiterungsanwendung und iOS können keine Verluste auftreten , und Apple garantiert dies. Wenn Sie die Erweiterung verwenden und die Methode didReceiveContent mit Abschluss überschreiben, wird die Benachrichtigung trotzdem angezeigt, auch wenn Sie diesen Abschluss nicht aufrufen. Dies ist wichtig zu beachten. Sie können es nicht anrufen oder haben keine Zeit, es anzurufen, aber dann wird die Benachrichtigung ohne Änderungen in der Form angezeigt, in der sie von APNs stammt.

Wir werden untersuchen, wie wir mit Verlusten zwischen APNs und Extension umgehen. Wenn Sie jedoch die Zustellbarkeit von Push-Benachrichtigungen verbessern müssen, sehen Sie sich das gesamte Schema an. Überprüfen Sie, ob auf der Serviceseite Verluste auftreten, ob Ihr Anbieter normal mit APNs interagiert und so weiter. Überprüfen und messen Sie die gesamte Kette und ziehen Sie dann Schlussfolgerungen, wo die Verluste am meisten auftreten und welcher Teil dieser Schaltung geändert werden sollte.

Push-Benachrichtigungswarteschlange


Um mit Verlusten im Bündel von APNs und Erweiterungen umzugehen, haben wir die Push-Benachrichtigungswarteschlange aufgerufen.

Wenn Sie die ganze Geschichte auf einen Satz komprimieren, ist dies:
Wenn Sie die Push-Benachrichtigung verpasst haben, können Sie sie erneut anfordern.



In unserem Benachrichtigungsschema sind alle Teilnehmer: XIVA, APNs, Erweiterung. Das vereinfachte Schema funktioniert folgendermaßen:

  • XIVA nummeriert die Push-Benachrichtigungen, die an APNs gesendet werden sollen, und sendet erst dann Informationen.
  • Die Nebenstelle erhält eine Push-Benachrichtigung Nummer 1 und nach einiger Zeit die Nummer 3. Sie versteht, dass einige Daten fehlen.
  • Sendet eine Anfrage an XIVA mit der zuletzt empfangenen Position, diff und fordert Sie auf, die fehlenden Daten erneut zu senden.
  • XIVA sendet die Push-Benachrichtigung erneut, da die Nutzdatenbank und die Abonnementdatenbank gespeichert werden. Alle Abonnements werden für einige Zeit gespeichert und können erneut angefordert werden.
  • Wir fragen erneut, wir erhalten eine Push-Benachrichtigung und wir haben alle Nachrichten auf dem Client, die der Client hätte erhalten sollen.

Das erste erwartete Problem sind doppelte Benachrichtigungen. Wenn wir eine Nachricht von XIVA erneut anfordern, wissen wir nicht, was sich in der Warteschlange zum Senden befindet, da wir nicht direkt, sondern über APNs mit ihr kommunizieren. Angenommen, wir haben festgestellt, dass einige Benachrichtigungen fehlten, und eine Anfrage an XIVA gesendet. XIVA wird über Payload-APNs mit einer versäumten Benachrichtigung gesendet. Aber bevor wir es erhielten, erhielten wir eine weitere Nutzlast und auch mit einem Pass. Sie fragten erneut - XIVA schickte erneut.

Damit Benachrichtigungen nicht dupliziert werden, verwenden wir apns -apse-id . Mit dieser Einstellung kann die iOS-Seite Push-Benachrichtigungen mit derselben ID reduzieren. Wenn mehrere Push-Benachrichtigungen mit derselben Apns-Collapse-ID auf dem Gerät eingegangen sind, werden sie von iOS reduziert und der Benutzer sieht nur eine Benachrichtigung.

XIVA


Ich werde Ihnen sagen, wie alles unter XIVA funktioniert, da es immer neugierig ist, was im Backend passiert.

XIVA existierte vor der Push-Benachrichtigungswarteschlange und war eine Abonnementdatenbank. Es ist wichtig, dass in der Datenbank alles von Benutzern gespeichert wurde:

  • Der Schlüssel war <service, user> .
  • Die Nutzlast wurde als Wert gespeichert (Daten zu Briefen bei Mail).

XIVA hat Daten aus der Datenbank entnommen und an APNs oder einen anderen Dienst gesendet, da dies nicht nur mit iOS funktioniert. Wir haben beschlossen, es wiederzuverwenden.

Wir sind zum XIVA-Entwicklungsteam gekommen und haben wirklich nach einer Push-Benachrichtigungswarteschlange gefragt. Grundsätzlich hatte XIVA bereits alles dafür: Die Datenbank TTL für Nutzdaten, dh sie werden nicht sofort gelöscht, sie können weitergeleitet werden. Es fehlte lediglich die Möglichkeit, die Push-Benachrichtigungswarteschlange als Teil der aktuellen XIVA-Implementierung zu konfigurieren - die End-to-End-Nummerierung.

Für die Pass-Through-Nummerierung sollten Push-Benachrichtigungen nach Gerät und Anwendungsname nummeriert werden. Das heißt, eine End-to-End-Nummerierung ist für ein bestimmtes Gerät und für eine bestimmte Anwendung erforderlich, um sich auf der Clientseite darauf verlassen zu können. Wir haben dies wie folgt gemacht: Die XIVA-Datenbank wurde wiederverwendet, aber es wurden Nutzdaten mit einem anderen Schlüssel darauf geschrieben. Jetzt fungiert apns_queue als Dienst, device_id + app_name als Benutzer - device_id + app_name die Daten, die auf dem Client nummeriert werden key: <apns_queue, device_id + app_name> .

Jetzt nimmt XIVA Daten aus der Hauptdatenbank und stellt sie in die Warteschlange, wenn sie gesendet werden müssen. Zu diesem Zeitpunkt erhalten Nutzdaten eine neue Nummerierung, da sie sich jetzt in derselben Datenbank befinden, jedoch mit einem anderen Schlüssel. Bereits von dort nimmt XIVA sie heraus und sendet sie über APNs. Insgesamt erhält der Client die erforderliche Nutzlastnummerierung.

Der Client verwendet die Notification Service Extension.

 public override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { // . . . } 

Wir definieren die didReceive Methode didReceive und sehen, was vom Server kam. Wir fügen allen Push-Benachrichtigungen "mutable-content" : 1 , damit sie in die Erweiterung fallen, da wir sie sonst bei Berechnungen nicht berücksichtigen können.

Weiter im Code innerhalb der Methode gibt es kontinuierliche Überprüfungen: ob die erforderliche Nutzlast kam, ob sie sie analysieren konnten. Wenn nicht analysiert, stammt diese Nachricht nicht von XIVA. Wenn die Nachricht nicht von XIVA stammt, können wir nicht weiter damit arbeiten und rufen einfach die Fertigstellung mit der Benachrichtigung auf, die von APNs kam. Wir führen keine Berechnungen durch.

 guard let payload = try? self.payloadParser.parsePayload(from: request.content.userInfo) else { //  ,     xiva contentHandler(request.content); return } 

Wir protokollieren, prüfen, ob sich die Geräte-ID geändert hat, da wir wissen, dass dies unter iOS möglich ist. Ehrlich gesagt haben wir keine Änderung in der Geräte-ID festgestellt, aber nur für den Fall, dass wir sie verarbeiten, denn wenn sie sich ändert, können wir den Zahlen von XIVA nicht vertrauen.

 self.logger.logNotificationReceived(with: payload) if lastPositionDeviceId != deviceId { // deviceId ,    lastNotificationPosition = nil lastPositionDeviceId = deviceId } 

Weiter prüfen wir, ob wir die XIVA-Daten in dieser Nutzlast empfangen können, ob sie es sind oder nicht. Wenn nicht, rufen Sie contentHandler erneut auf.

 guard let xivaInfo = payload.xivaInfo else { contentHandler(request.content); return } 

Wenn Daten vorhanden sind, überprüfen Sie, ob die Geräte-ID Daten empfangen hat. XIVA sendet einen Hash des Geräts an die Nutzdaten. Wenn dieser überprüft wird und übereinstimmt, fahren wir fort. Nein, wir rufen contentHandler auf.

 guard isHashCompatible(deviceId: deviceId, deviceIdHash: xivaInfo.deviceIdHash) else { // payload device_id   device_id  contentHandler(request.content); return } 

Im nächsten Block wird geprüft, ob eine Position gespeichert ist:

  • Wenn wir nicht über die zuletzt gespeicherte Position verfügen, haben wir entweder noch keine Benachrichtigungen erhalten und die Erweiterung nicht eingegeben oder sind aus irgendeinem Grund abgebrochen. Dann gibt es nichts mehr zu verschieben, um das verpasste Diff zu finden, und wir rufen erneut die Fertigstellung auf.
  • Wenn ja, fahren Sie fort.

 guard let lastPos = lastNotificationPosition else { //      lastNotificationPosition = xivaInfo.notificationPosition contentHandler(request.content); return } 

Wir zählen die Anzahl der versäumten Benachrichtigungen. Wenn das Fehlen einer Null in Ordnung ist, haben wir nichts verpasst.

 let missedMessages = xivaInfo.notificationPosition - lastPos - 1 guard missedMessages > 0 else { //   push–     contentHandler(request.content); return } 

Ansonsten nehmen wir von XIVA die Positionsdaten - aus derselben fortlaufenden Nummerierung. Weiter prüfen wir, ob die Menge der versäumten einen bestimmten Sollwert nicht überschreitet.

 lastNotificationPosition = xivaInfo.notificationPosition guard missedMessages <= repeatMaxCount else { //    ,   contentHandler(buildNewNotification()); return } 

Warum wird das benötigt? Angenommen, der Benutzer war lange Zeit offline und während dieser Zeit wurden hundert Nachrichten gesammelt. Wir werden die ganzen hundert anfordern (es ist einfach für uns), XIVA wird die ganzen hundert senden und der Benutzer wird alle Benachrichtigungen erhalten. Selbst wenn wir sie nach Thread-ID gruppieren (und sie gruppieren), wird diese Erweiterung für jede Benachrichtigung aufgerufen, alle Prüfungen werden bestanden. Es ist unwahrscheinlich, dass der Benutzer alle hundert Benachrichtigungen benötigt. Daher generieren wir eine Benachrichtigung, in der wir schreiben, dass Sie 100 Nachrichten verpasst haben, zur Anwendung gehen und nachsehen. Und wir zeigen dem Benutzer genau diese Nachricht, da wir Push-Benachrichtigungen ersetzen können.

Wenn alle Prüfungen bestanden sind, senden wir eine Anfrage an XIVA: die letzte Position, die zu uns gekommen ist, und die Anzahl der verpassten Nachrichten. Und schau:

  • Wenn die XIVA erfolgreich antwortet: "Alles ist in Ordnung, ich werde die Daten senden", zeigen wir dem Benutzer die aktuelle Benachrichtigung und warten, bis die XIVA alles andere sendet und der Benutzer alle Nachrichten sieht, die verpasst wurden.
  • Wenn XIVA mit einem Fehler antwortet, zeigen wir dem Benutzer eine benutzerdefinierte Benachrichtigung an, dass er Nachrichten verpasst hat, die in der Anwendung angezeigt werden können.

 self.requestMissedNotifications(lastPosition: xivaInfo.notificationPosition, gap: missedMessages) { result in result.onValue { _ in self.logger.logNotificationProcessed(with: .success) contentHandler(request.content) }.onError { error in self.logger.logNotificationProcessed(with: .failure(error)) contentHandler(buildNewNotification()) } } 

Die Implementierung auf dem Client besteht daher aus einer Vielzahl von Überprüfungen, bei denen wir herausfinden, ob wir mit den empfangenen Daten arbeiten können.

Protokollierung und andere Schwierigkeiten


Wie Sie wissen, müssen Sie sich anmelden, um sicherzustellen, dass der Ansatz gut funktioniert. Wir haben begonnen, Statistiken über eine neue Methode zur Zustellung von Benachrichtigungen zu sammeln und zu vergleichen, wie sich die Zustellbarkeit geändert hat.

Einschränkungen der Push-Extension


Das erste, was uns begegnet ist, sind die Einschränkungen für Push-Erweiterungen.

Nicht immer angerufen . Wenn Sie die Benachrichtigungszeichnung in den Anwendungseinstellungen deaktivieren (die Möglichkeit, eine Benachrichtigung zu erhalten, bleibt aktiviert, aber alle möglichen Renderings sind deaktiviert), wird die Erweiterung nicht aufgerufen - die gesamte Logik mit Nachzählungen und vor allem die Protokollierung werden nicht aufgerufen. Wir können nicht herausfinden, was für uns am wichtigsten ist - ob der Benutzer eine Benachrichtigung erhalten hat.

Die Push-Erweiterung ist zeitlich begrenzt . In der Apple-Dokumentation heißt es, dass Sie innerhalb von 30 Sekunden den Abschluss mit einer geänderten Benachrichtigung anrufen müssen, andernfalls wird die erste Benachrichtigung angezeigt.

Ich frage mich, wie wir es herausgefunden haben. Wir haben eine Funktion implementiert, die wir "schöne" Push-Benachrichtigungen nannten, Medienelemente an Benachrichtigungen anhängten, den Titel und den Untertitel änderten. Während des Tests stellte sich heraus, dass einige Push-Benachrichtigungen schön wurden, während der Rest als hässliche Entenküken zurückblieb.

Wir begannen, den Unterschied zwischen diesen Push-Benachrichtigungen zu untersuchen und stellten fest, dass es keinen Unterschied gab, nur für einige, die wir als Abschluss bezeichneten, für andere jedoch nicht. , , push- , APNs.

. Apple , , push-extension, , , . , 12 .

Apple Developer Forum , , . , — 10 .

, . AppMetrica. , AppMetrica , Extension . , - .

: Extension .


push-extension UserDefaults. , , AppMetrica.

. . , , . , . , XIVA ( ), , .

, Notification Extension iOS 10 , Extension, , .

AppMetrica : , push-extension . AppMetrica push-, , . , AppMetrica Push SDK .

, . — , . , .



— , , .

, push-, , — .

, , . , …


: , , . , ? - , push-? , ? user experience ?

, 2–3–20 ?

, , , , , , , . , push-. , .

Zusammenfassung


Push- iOS . , .. , .

push- ( ) . . XIVA. , , . , , . !

push-extension. , . , .

, . , , , , - . , push- . , , , App Store, , !

AppsConf , 21 22 , .. 50 , . 1 , — .

Source: https://habr.com/ru/post/de462507/


All Articles