en
de

Apple Watch revisited – mit watchOS 2 native Apps entwickeln

4 Januar 2016
| |
Lesezeit: 10 Minutes

Anfang 2015 hatten wir hier im Blog die erste Version von Apples watchOS unter die Lupe genommen – jetzt, gut ein Jahr später, ist die Smartwatch schon einige Zeit im Handel und die zweite Version von watchOS ist auf den Uhren angekommen. Doch was bedeutet das Update des Betriebssystems für Entwickler und Anwender? Und wie entwickelt es sich mit einer Apple-Watch am Arm? Das soll dieser Artikel beleuchten.

Als Beispiel dient wieder die Einkaufslisten-App GrocerieZ, die eine einfache Liste von zu kaufenden Artikeln auf iPhone und Watch anzeigt und zwischen den beiden Geräten synchronisiert. Im Gegensatz zu Version 1 der App soll die Liste dieses Mal sowohl vom iPhone, als auch von der Apple Watch aus befüllt werden können. Zusätzlich zum „Glance“ (dt. „Check“), der die aktuelle Anzahl noch zu kaufender Artikel anzeigt, wird zudem eine eigene „Complication“ genutzt, um App-Infos direkt aufs Zifferblatt zu bringen. „Complications“ sind Zusatzfunktionen einer Uhr. Der Begriff „Komplikation“ stammt aus der traditionellen Uhrmacherei und bezeichnet zusätzliche Funktionen einer Uhr, die über die reine Anzeige der Uhrzeit hinausgehen.

GrocierieZ auf iPhone und Apple Watch

Die Einkaufsliste auf dem iPhone (links) und auf der Watch (rechts oben). Der Glance (unten rechts) zeigt die aktuelle Anzahl Artikel auf der Liste an.

Die Apple Watch wird selbständig(er)

Die für Entwickler wohl wichtigste Änderung mit watchOS 2 stellt zweifelsfrei dar, dass – wie bereits im Vorfeld vermutet – Apps nun endlich nativ für die Apple Watch entwickelt werden können und nicht für jede Aktion mit dem iPhone kommunizieren müssen. Die benötigten Komponenten ändern sich dabei nicht: Es muss nach wie vor eine iPhone-Anwendung geben, über die die Watch-App überhaupt erst in den Store und auf die Uhr gelangt. Zudem wird eine Watch-Extension für die Anwendungslogik benötigt, und schließlich die Watch App, die Storyboards und Grafik-Assets beinhaltet. Lag die Extension bei watchOS 1 jedoch noch auf dem iPhone, läuft sie mit watchOS 2 auf der Uhr und ermöglicht dadurch ein gutes Stück Unabhängigkeit für die Smartwatch, die damit nun sowohl die UI-Komponenten, als auch die Anwendungslogik ihrer Apps beherbergt. Als Folge dieses Umzugs steht dem Entwickler nun in der Watch-Extension nicht mehr das iOS SDK, sondern das watchOS SDK zur Verfügung, was zur Folge hat, dass beispielsweise iCloud-Technologien nicht länger aus der Extension heraus angesprochen werden können. Die folgenden Abbildungen stellen die unterschiedlichen Architekturen von watchOS 1 und 2 gegenüber:

Architektur watchOS 1

Architektur unter watchOS 1: Die Watch Extension liegt auf dem iPhone, es gibt eine gemeinsame Datenhaltung. Die Kommunikation zwischen iPhone und Uhr erfolgt ohne Zutun des Entwicklers über WatchKit.

Architektur watchOS 2

Architektur unter watchOS 2: Die Watch Extension liegt auf der Uhr, es gibt eine getrennte Datenhaltung. Die Kommunikation wird vom Entwickler über das Watch Connectivity Framework gesteuert.

Dadurch, dass die Watch-Extension nun auf der Watch liegt, ändert sich die Kommunikation zwischen iPhone-App und Extension für die Entwickler drastisch: Es kann nicht weiter per App Group auf eine gemeinsame Datenbank zugegriffen werden. Stattdessen herrscht nun getrennte Datenhaltung; um die Synchronisation müssen sich die Entwickler selbst kümmern. Einerseits erscheint es logisch, die Uhr mit einer eigenen Datenbank zu versorgen, damit sie nicht doch wieder für jede Aktion die Verbindung zum iPhone benötigt. Andererseits erfordert dieser Umstand einen recht hohen Entwicklungsaufwand beim Umstieg auf das Betriebssystem watchOS 2, und in der Summe einen größeren Speicherbedarf für die Apps. Hier sind Entwickler gut beraten, sich ausgiebig Gedanken darüber zu machen, welche Daten tatsächlich auf der Watch benötigt werden, und nicht blind sämtliche Daten vom iPhone auf die Smartwatch zu übertragen. Die Watch ist für die aktuellsten Informationen gedacht, längeres Blättern in Historien ist nach wie vor auf dem iPhone angesiedelt. Dieses Konzept wird beispielsweise auch vom Apple-eigenen Kalender umgesetzt, der auf der Uhr stets nur den aktuellen Monat anzeigt.

Neue Wege beim Datenaustausch

Für die Kommunikation zwischen Uhr und Telefon stellt Apple mit watchOS 2 das neue Watch Connectivity Framework zur Verfügung. Es ermöglicht das Austauschen von Daten im Property-List-Format, sowie die Übertragung von Dateien. Hierfür muss auf beiden Geräten eine WCSession (siehe: https://developer.apple.com/library/ios/documentation/WatchConnectivity/Reference/WCSession_class/) gestartet und ein Delegate implementiert werden, dessen Methoden bei eingehenden Nachrichten aufgerufen werden. Dabei sind verschiedene Arten der Kommunikation vorgesehen:

  • Background Transfer: Der Transfer im Hintergrund eignet sich für wenig zeitkritische Daten bzw. wird angewandt, wenn gerade nicht beide Apps aktiv sind. Der Zeitpunkt der Datenübertragung wird dabei vom Betriebssystem gewählt. Es kann wahlweise ein sogenannter „Application Context“ gesetzt werden, der stets nur einen aktuellen Status der App widerspiegelt und bei erneutem Setzen überschrieben wird. Beim Transfer von „User Info“ werden die gesendeten Daten in eine Warteschlange eingefügt und nach und nach übertragen, d. h. es findet kein Überschreiben von Informationen statt. Als dritte Option können Dateien per „File Transfer“ übertragen werden.
  • Interactive Messaging: Der direkter Datenaustausch zwischen den Geräten (wichtig z. B. für Spiele, bei denen beide Geräte in Echtzeit zusammenarbeiten), ist nur möglich, wenn beide Anwendungen aktiv sind. Der Status der jeweiligen Gegenstelle muss dafür über die Reachability-Eigenschaft der WCSession abgefragt werden. Direktnachrichten können im Gegensatz zum Datentransfer im Hintergrund auch durch Übergabe eines Reply-Handlers direkt beantwortet werden.

Alternativ zum Sync mit dem iPhone kann die Watch sich dank watchOS 2 nun auch mittels NSURLSession (siehe: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSession_class/) Daten von Servern herunterladen. Die nötigen WLAN-Zugangsdaten werden wie gehabt ohne Zutun des Nutzers vom gekoppelten iPhone bezogen.

Komplikationen für alle!

Wer mit dem Fachjargon der Uhrentechnik nicht vertraut ist, der mag etwas verwundert geschaut haben, als die Complications (dt.: Komplikationen) zum ersten Mal als Feature von watchOS 2 für die Entwickler angepriesen wurden. Es handelt sich dabei um kleine Module, die auf dem Zifferblatt angezeigt werden können (vgl. die Anzeige von Datum oder Mondphase auf mechanischen Armbanduhren). Apple gibt den Entwicklern nun ClockKit an die Hand, womit diese eigene kleinste UI-Bausteine entwerfen können, welche die wichtigsten Informationen aus der App kompakt auf dem Zifferblatt darstellen. Ganz nebenbei dient eine solche Complication auch als Shortcut zur eigentlichen App, die durch Antappen der Complication in den Vordergrund geholt wird. Schon allein aus diesem Grunde sollte man sich als Entwickler mit ClockKit beschäftigen.

Wer erwartet hatte, die Complications frei im Interface Builder designen zu können, wurde jedoch enttäuscht. So hatte ich als Complication analog zum Glance-Interface geplant, einen kleinen Einkaufswagen darzustellen, in dessen Bauch die Anzahl noch zu kaufender Artikel angezeigt wird. Das Erstellen der Complications erfolgt jedoch komplett über Code durch Befüllen eines von zahlreichen Templates. Da auf den unterschiedlichen Zifferblättern verschieden viel Platz vorhanden ist, gibt es zunächst eine Reihe von Complication-Familien:

Complication-Familien

Die Complication-Familien im Überblick

Für jede dieser Familien gibt es eine Reihe von Templates. So kann beispielsweise „Modular large“, die größte Complication, zwei- oder dreizeilig sein, optional ein Bild im Titel oder ein Bild pro Zeile anzeigen, oder kann gar als Tabelle mit 3 Zeilen und 3 Spalten gestaltet werden. Für „Modular small“ und „Modular large“ steht u. a. ein Template zur Verfügung, bei dem Text oder ein Bild in einem prozentual ausgefüllten Ring dargestellt werden können.

Die Templates werden dabei nicht mit einfachen Strings und Bildern befüllt, sondern mit Hilfe der ClockKit-Klassen CLKTTextProvider (siehe: https://developer.apple.com/library/watchos/documentation/ClockKit/Reference/CLKTextProvider_class/index.html und CLKImageProvider (siehe: https://developer.apple.com/library/watchos/documentation/ClockKit/Reference/CLKImageProvider_class/index.html). Diese formatieren die ihnen übergebenen Rohdaten dem verfügbaren Platz entsprechend.

Auf die Wirkung von Farbe darf sich der Entwickler bei der Gestaltung von Complications übrigens nicht verlassen: Bilder werden stets als Template-Images behandelt, d. h. ihre Farbinformationen werden ignoriert und die Alphawerte innerhalb des Bildes als Schablone verwendet. Für diese kann der Entwickler zwar Farben definieren, auf den meisten Watch Faces werden die Bilder jedoch in der vom Benutzer festgelegten Zifferblatt-Farbe eingefärbt. Lediglich die Watch Faces „Utility“ und „Modular“ (mit Farb-Einstellung „Multicolor“) zeigen Complications in den vom Entwickler definierten Farben an.

Für GrocerieZ habe ich zunächst das UtilitarianSmall-Template mit Icon und Text umgesetzt. Neben dem Einkaufswagen-Icon wird die aktuelle Anzahl von Artikeln auf der Liste angezeigt:

GrocerieZ-Complication

Das „Utility“-Zifferblatt mit GrocerieZ-Complication (oben links)

Zeitreise auf dem Zifferblatt

Eine weitere Neuerung von watchOS 2 stellt „Time Travel“ dar, das es dem Benutzer ermöglicht, durch Drehen an der Digital Crown auf dem Zifferblatt in der Zeit vor- und zurückzureisen. Dabei wird nicht nur die angezeigte Zeit verstellt, auch die angezeigten Complications stellen die zum gewählten Zeitpunkt passenden Infos dar. So werden beispielsweise in der Kalender-Complication Ereignisse aus der Vergangenheit angezeigt, und die Wetter-Complication zeigt die erwartete Temperatur für einen Zeitpunkt in der Zukunft an. Damit sich jedoch beim Drehen am Rad in der eigenen Complication überhaupt etwas tut, sind zunächst einige Vorbereitungen zu treffen.

Time Travel

Time Travel auf der Uhr: Aktuell steht ein Artikel auf der Liste (Mitte), vor 1:21 Stunden waren es noch drei (links). Die GrocerieZ-Complication unterstützt die „Zeitreise“ in die Zukunft nicht und ist deshalb im rechten Screenshot (6 Minuten in der Zukunft) ausgegraut

Wer Complications unterstützen möchte, benötigt hierfür einen eigenen ComplicationController, der das CLKComplicationDataSource-Protokoll implementiert. Die enthaltenden Methoden werden von watchOS bei Bedarf aufgerufen und legen beispielsweise fest, ob und in welche Richtungen Time Travel möglich sein soll, bis zu welchem Datum gereist werden kann, und ob die Complication auch auf einer gesperrten Uhr angezeigt werden soll. Darüber hinaus wird ein Complication-Platzhalter angefordert, der z. B. beim Konfigurieren der Watch Faces oder bei fehlenden Daten angezeigt wird. Die aktuelle Complication wird beispielsweise über folgende Methode zurückgegeben:

    func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
        // Get the complication family we are currently asked for
        switch complication.family {
        case .UtilitarianSmall:
            // Create a template: Utilitarian small flat displays an image and a text in one row
            let template = CLKComplicationTemplateUtilitarianSmallFlat()
            template.imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Utilitarian")!)
            template.textProvider = CLKSimpleTextProvider(text: String(extensionDelegate.items.count))
            // Create a timeline entry with the current date and the created template and call the handler with it
            let entry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(entry)
            break
        default:
            handler(nil)
            break
        }
    }

Die Zeit, die eine Watch-App mit dem Aktualisieren ihrer Complication verbringen darf, ist limitiert. Apple hat den Entwicklern hierfür die Möglichkeit eingeräumt, einen Zeitpunkt anzugeben, zu dem die oben genannte Methode erneut aufgerufen werden soll. Das Update kann aber auch händisch im Code angestoßen werden. Im Fall der GrocerieZ-App ist es beispielsweise nicht sinnvoll, die Complication zeitgesteuert zu aktualisieren. Hier wird ein Update immer dann getriggert, wenn ein Artikel zur Liste hinzugefügt oder abgehakt wurde.

Für Time Travel fragt watchOS zu gegebener Zeit eine Anzahl Einträge vor oder nach einem gegebenen Datum an. Zurückgegeben wird eine Liste von CLKComplicationTimelineEntry-Objekten, die sowohl ein befülltes Complication-Template, als auch den zugehörigen Zeitstempel enthalten. Wie Entwickler diese Daten zusammenstellen, ist komplett ihnen überlassen. Es findet beispielsweise für die Reise in die Vergangenheit kein Caching von bisher angezeigten Complications statt. Im Falle von GrocerieZ wird deshalb die Historie der Anzahl der Artikel auf der Liste gesondert gespeichert. Jedes Mal, wenn ein Artikel hinzukommt oder verschwindet, wird ein entsprechender Eintrag mit Zeitstempel und der aktuellen Anzahl von Artikeln abgelegt. Die angeforderte Liste von Timeline-Einträgen wird dann wie folgt ermittelt:

    func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: (([CLKComplicationTimelineEntry]?) -> Void)) {
        let items = extensionDelegate.history
        var entries = [CLKComplicationTimelineEntry]()
        for item in items {
            // Return only items before the given date
            if (date.compare(item.date) == .OrderedDescending) {
                // Create a timeline entry for the item's date, the template is created using a custom helper method
                entries.append(CLKComplicationTimelineEntry(date: item.date, complicationTemplate: getUtilitarianSmallFlatTemplateForHistoryEntry(item)))
                // Don't return more entries than you were asked for
                if (entries.count == limit) {
                    break;
                }
            }
        }
        // Call the handler with your timeline entry array
        handler(entries)
    }

Texteingabe per Sprache

Die Texteingabe auf der Watch ist ein Feature, das nur mit einem echten Gerät getestet werden kann und deshalb in unserem letzten Artikel ausgespart wurde. In Version 2 von GrocerieZ kann per Stimme ein Artikel zur Liste hinzugefügt werden. Die Integration der Spracheingabe in die App erfolgt denkbar einfach; es muss lediglich ein vorgefertigter modaler InputController aufgerufen werden, der nach dem Diktat ein String-Ergebnis zurück liefert. Die Eingabesprache kann der Benutzer übrigens per Force Touch auf dem Dictation-Screen selbst wählen, standardmäßig wird die momentane System-Sprache der Watch verwendet.

Artikel hinzufügen per Spracheingabe

Artikel hinzufügen auf der Watch: Per Force Touch gelangt der Nutzer ins Kontextmenü. Nach Tap auf „Add Item“ öffnet sich der System-Dialog zur Spracheingabe.

So einfach das Einbinden von Dictation auch ist, das Ergebnis ist zuweilen noch recht enttäuschend. So dauert die Auswertung teils mehrere Sekunden und der erkannte Text wird manchmal nicht direkt angezeigt. Ab und zu ändert sich das erkannte Wort noch, nachdem man die Erkennung bereits bestätigt hatte, was auf Dauer zu Verwunderung bist Frust beim Watch-Anwender führen könnte. Der Entwickler ist darum wohl gut beraten, von der Option Gebrauch zu machen, dem Controller vorgefertigte Strings zu übergeben, die dann per Tap ausgewählt werden können. Im Falle der Einkaufsliste wäre es z. B. gut denkbar, vormals häufig gekaufte Artikel anzuzeigen, da die Wahrscheinlichkeit recht hoch ist, dass diese zu einem späteren Zeitpunkt wieder in die Liste aufgenommen werden sollen.

Fazit

Mit watchOS 2 ermöglicht Apple den Entwicklern endlich, echte Watch-Apps für die Apple Smartwatch zu bauen, die watchOS 1 einmal mehr wie eine Übergangslösung aussehen lassen. Für watchOS 1 entwickelte Apps müssen beim Umstieg auf watchOS 2 bezüglich der Kommunikation zwischen den Geräten grundlegend umgebaut werden, was angesichts der geänderten Architektur nachvollziehbar ist. Die Umstellung bedeutet jedoch einen großen Mehraufwand für die Entwickler, insbesondere wenn es darum geht, die Datenstände auf beiden Geräten synchron zu halten. Wer auf eine gemeinsame Datenbasis aufsetzen will, muss leider ohne die Features von watchOS 2 auskommen und wird vermutlich früher oder später zum Umstieg gezwungen.

Complications bieten eine schöne und sinnvoller Erweiterung von Watch-Apps, die potentiell dem Glance den Rang abläuft und mit der sich Watch-Entwickler auf jeden Fall beschäftigen sollten. Das Entwickeln für Apple Watch erfordert jedoch momentan noch einiges an Geduld. So braucht es mitunter mehrere Anläufe, bis die eigene App tatsächlich auf der Watch startet. Bei Problemen ist häufig ein kompletter Reboot nötig, der bei der Uhr durchaus an die zwei Minuten dauern kann. Dies sind sicherlich Probleme, die mit zukünftigen Hardware-Generationen nach und nach ausgemerzt werden. Läuft die eigene Anwendung dann schließlich auf der Uhr, macht es jedoch viel Freude, die eigene App-Idee am Handgelenk zu erleben.

 

Weiteres zur App-Entwicklung gibt es u.a. bei der Success-Story der myBosch App auf der Zühlke Webseite!

Kommentare (0)

×

Updates

Schreiben Sie sich jetzt ein für unsere zwei-wöchentlichen Updates per E-Mail.

This field is required
This field is required
This field is required

Mich interessiert

Select at least one category
You were signed up successfully.