Wie man NFC für iOS 11 implementiert - Teil 2: Background Tag Reading

13. Dezember 2018

Zeitgleich mit der Einführung des iPhone XS, iPhone XS Max und iPhone XR hat Apple eine Funktion namens "Background Tag Reading" eingeführt, die exklusiv für die neuen iPhones verfügbar ist. Im Vergleich zum bereits vorgestellten Konzept in Teil 1 kann das System nun NFC-Daten im Hintergrund scannen und lesen, die dann an eine geeignete Anwendung weitergeleitet werden. So kann man z.B. ganz bequem mit der EnBW mobility+ App den Ladevorgang fürs Elektroauto beginnen, ohne vorher die App zu öffnen. Das entsperrte Handy initiiert die NFC-Lesesitzung, sobald man es an die Ladesäule hält, und leitet einen direkt an die richtige Stelle in der App. Dadurch wird der NFC-Tag-Leseprozess deutlich vereinfacht. Entsprechend verbessert sich auch das Nutzererlebnis beim Lesen von NFC-Daten auf der iOS-Plattform.

Voraussetzungen

Damit NFC-Daten im Hintergrund gescannt werden können, gilt es, einige Bedingungen zu erfüllen: Zunächst müssen wir sicherstellen, dass keine aktive NFC-Lesesitzung einer anderen Anwendung existiert und die Kamera des Geräts momentan nicht verwendet wird. Darüber hinaus muss das Gerät des Benutzers seit dem Anschalten mindestens einmal entsperrt worden sein. Zu guter Letzt ist sicherzustellen, dass der Flugzeugmodus ausgeschaltet ist, so dass der eingebaute NFC-Empfänger bereit steht, eintreffende Daten zu verarbeiten.

Vorgehensweise

Wenn alle genannten Voraussetzungen erfüllt sind, verarbeitet das System eingehende NDEF-Nachrichten, indem es den dazugehörigen Payload analysiert. Wichtig ist: Das System akzeptiert nur den ersten URI-Eintrag, der entweder einen Universallink oder eines der vordefinierten URL-Schemata enthalten muss. Insbesondere unterstützt iOS keine benutzerdefinierten URL-Schemata. Genauere Informationen zu den Unterschieden von benutzerdefinierten URL-Schemata und universellen Links finden sich am Ende dieses Artikels.

Notwendige Schritte

Um das Lesen von Hintergrund-Tags innerhalb der jeweiligen iOS-Anwendung zu unterstützen, muss man zunächst die Domains aller Universal-Links, die unterstützt werden sollen, mit seiner Anwendungs-ID (App-ID) registrieren. Dazu navigiert man in seinem Xcode-Projekt zu "Capabilities" und sucht nach dem Abschnitt "Associated Domains", wie im folgenden Screenshot dargestellt. Bitte beachten: Die Anzahl der registrierten Domains ist begrenzt und sollte eine Anzahl von 20 bis 30 Domains nicht überschreiten.

domains einfügen

Du fragst dich sicher, ob man eine beliebige Domain mit seiner App registrieren kann? Kurz gesagt: Ja. Hierbei ist allerdings zu berücksichtigen, dass das System universelle Links nur dann als Inhalt einer NDEF-Nachricht an eine Applikation weiterleitet, wenn man nachweisen kann, dass man auch Eigentümer der registrierten Domain ist. Die eigene Identität wird durch die Platzierung einer so genannten apple-app-side-association Datei auf dem eignen Webserver nachgewiesen, die einen Verweis auf die "Team-" und "Bundle-ID" enthält. * und ? dienen als Platzhalter, um alle Pfade anzugeben, die bei der zugehörigen Domain registriert werden sollen; das Schlüsselwort NOT erlaubt das explizite Ausschließen von Pfaden der Anwendungs-ID. Nachfolgend sieht man ein Beispiel einer apple-app-side-association Datei, wie sie auf dem Webserver platziert werden könnte.

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "TEAM_ID.BUNDLE_ID",
                "paths": [ "NOT /e/*", "*", "/", "/archives/201?/*"]
            }
        ]
    }
}

Schließlich muss man im AppDelegateseiner iOS-App die Methode application(_:continue:restorationHandler:) implementieren, um eingehende Payloads zu verarbeiten. Dafür prüfen wir zunächst, ob die Aktivität vom Typ NSUserActivityTypeBrowsingWeb ist, da NDEF-Nachrichten nur von Universal Links stammen können, die als URI-Record an die Anwendung übermittelt werden. Wenn das zutrifft, überprüfen wir den Inhalt der NDEF-Nachricht und stellen sicher, dass der erste Eintrag nicht leer ist. Schließlich erhalten wir die zugehörige URL, indem wir auf userActivity.webpageURL zugreifen. Anhand der URL kann man entscheiden, welche Inhalte in der Anwendung angezeigt werden sollen.

func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    // Step 1: Verify whether the activity was initiated by a browsing session
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb else { return false }

    // Step 2: Confirm that the NSUserActivity object contains a valid NDEF message
    let ndefMessage = userActivity.ndefMessagePayload
    guard !ndefMessage.records.isEmpty else { return false }
    guard ndefMessage.records[0].typeNameFormat != .empty else { return false }

    // Step 3: Handle URL
    guard let url = userActivity.webpageURL else { return false }
    print(url.absoluteString)
    return true
}

Fazit

Wir haben gesehen, dass das Auslesen von NFC-Tags mit der Einführung von "Background Tag Reading" deutlich vereinfacht wurde. War zuvor noch das Öffnen einer dedizierten Applikation erforderlich, um eine NFC-Lesesitzung zu starten, muss sich das iPhone nun lediglich im entsperrten Zustand in der Nähe des NFC-Tags befinden. Zu beachten ist, dass "Background-Tag-Reading" die Verwendung von Universalen Links erfordert. Leider ist das Auslesen von NFC-Daten im Hintergrund lediglich den neueren Geräten des iPhone-Lineup vorbehalten. Wünschenswert wäre, dass Apple diese Funktionalität in Zukunft auch auf weiteren Geräten bereitstellt.

Erläuterung zu Universal Links (TL;DR)

Der Nachteil von benutzerdefinierten URL-Schemata ist, dass sie nur verfügbar sind, solange die zugehörige Anwendung auf dem Gerät des Benutzers installiert ist. Sobald das System auf ein benutzerdefiniertes URL-Schema stößt, betrachtet es die Liste aller registrierten URL-Schemata und versucht, die Anwendung zu identifizieren, zu der das URL-Schema gehört. Wenn keine Anwendung gefunden wurde, wird das angeforderte URL-Schema ignoriert und vom System unbearbeitet gelassen.

Universal Links erweitern benutzerdefinierte URL-Schemata so, dass sie die Anfrage an einen Server weiterleiten, sobald keine Anwendung gefunden werden konnte. Auf diese Weise kann der Server den Benutzer auf den App Store verweisen, aus dem die gewünschte Anwendung installiert werden kann.