watchOS- und Wear-OS-Companion-Apps anbinden | Mironsoft
AI generated
RN
native
React Native · Wearables
watchOS- und Wear-OS-Companion-Apps
realistisch an React Native anbinden

React Native rendert nicht auf der Apple Watch oder einer Wear-OS-Uhr, Watch-Apps sind immer eigenständige native Targets. Dieser Artikel zeigt die Kommunikationsstrategie über WatchConnectivity und die Wearable Data Layer API sowie die realistischen Grenzen der Code-Wiederverwendung.

13 Min. Lesezeit WatchConnectivity Data Layer API Native Targets

1. Realistische Einordnung: React Native rendert nicht auf der Uhr

Eine verbreitete Fehleinschätzung bei React-Native-Projekten lautet, man könne die bestehende App einfach auch auf die Apple Watch oder eine Wear-OS-Uhr bringen, indem man den React-Native-Renderer dort ebenfalls laufen lässt. Technisch ist das ausgeschlossen: Weder watchOS noch Wear OS bieten eine Laufzeitumgebung, in der die JavaScript-Engine und der React-Native-Renderer einer Telefon-App ausgeführt werden könnten. Eine Watch-App ist immer eine eigenständige, vollständig native Anwendung mit eigenem App-Target, eigenem Lebenszyklus und eigenem, deutlich enger begrenztem Speicher- und Rechenbudget.

Das bedeutet nicht, dass React-Native-Teams keine Watch-Anbindung realisieren können, sondern dass die Watch-App architektonisch als eigenständiges Projekt behandelt werden muss, das über definierte Kommunikationskanäle mit der React-Native-App auf dem Telefon Daten austauscht. Realistische Erwartungen an Umfang und Aufwand sind hier entscheidend: Eine Watch-Companion-App zeigt in der Regel eine stark reduzierte Teilmenge der Telefon-App-Funktionalität, keine vollständige Parallel-Implementierung.

2. watchOS-Companion-Architektur: Ein eigenständiges SwiftUI-Target

Eine watchOS-App wird als zusätzliches Target im selben Xcode-Projekt angelegt, das die iOS-App enthält, läuft aber als eigener Prozess auf einer eigenen Runtime und wird komplett in SwiftUI implementiert. Seit den neueren watchOS-Versionen sind eigenständige Watch-Apps ohne zwingende iOS-Begleit-App möglich, für eine React-Native-Companion-App bleibt aber das klassische Modell relevant, bei dem die Watch-App als Erweiterung zur bestehenden iOS-App im selben App-Store-Eintrag ausgeliefert wird.

Wichtig für die Planung: Die watchOS-App teilt sich keinen Prozessspeicher mit der iOS-App, jede Datenübertragung läuft explizit über eine der von Apple bereitgestellten Kommunikations-APIs, es gibt keinen direkten Funktionsaufruf von der Watch-App in den React-Native-JavaScript-Kontext der Telefon-App hinein. Diese Isolation ist bewusst so gestaltet, damit die Watch-App auch dann funktionsfähig bleibt, wenn das iPhone gerade nicht in Reichweite oder die Telefon-App nicht aktiv im Speicher ist.

3. Wear-OS-Companion-Architektur: Kotlin und Jetpack Compose for Wear

Auf Android-Seite läuft eine Wear-OS-App als separates APK innerhalb desselben App-Bundles, implementiert in Kotlin mit Jetpack Compose for Wear OS als aktuellem UI-Framework, während ältere Projekte teilweise noch klassische View-basierte Wear-Layouts nutzen. Wear OS unterscheidet zusätzlich zwischen einer vollwertigen App, die eigenständig auf der Uhr läuft, und leichtgewichtigeren Formaten wie Tiles für Schnellzugriffe oder Complications für Zifferblatt-Integrationen, die jeweils eigene, noch stärker eingeschränkte APIs mitbringen.

Ähnlich wie bei watchOS läuft eine Wear-OS-App als eigener Prozess, unabhängig davon, ob das gekoppelte Smartphone gerade erreichbar ist. Google unterstützt zusätzlich Standalone-Wear-Apps, die auch ohne Companion-Smartphone-App auf der Uhr funktionieren und Konnektivität direkt über WLAN oder LTE der Uhr herstellen, was für eine reine Begleit-App zu einer React-Native-Telefon-App in der Regel aber nicht der relevante Anwendungsfall ist.

4. WatchConnectivity: Kommunikationskanäle zwischen iPhone und Apple Watch

Das Framework WatchConnectivity stellt über eine WCSession-Instanz mehrere Übertragungswege bereit, die sich in Dringlichkeit und Zuverlässigkeit unterscheiden. sendMessage liefert Daten in Echtzeit, verlangt aber, dass die Gegenstelle gerade erreichbar ist, andernfalls schlägt der Aufruf fehl. Für Daten, die auch bei nicht erreichbarer Gegenstelle zuverlässig ankommen sollen, eignet sich transferUserInfo, das die Übertragung in eine Warteschlange einreiht und automatisch nachholt, sobald die Verbindung wieder besteht.

Für den in Companion-Apps häufigsten Fall, den aktuellen Gesamtzustand synchron zu halten, etwa den zuletzt bekannten Bestellstatus, ist updateApplicationContext meist die richtige Wahl: Es überschreibt frühere, noch nicht zugestellte Kontext-Updates, sodass immer nur der jeweils letzte Stand übertragen wird, statt eine Warteschlange veralteter Zwischenzustände abzuarbeiten. Diese drei APIs ergänzen sich, und die Wahl der richtigen hängt vom konkreten Datentyp und der geforderten Aktualität ab.


// ios/WatchBridge.swift
import WatchConnectivity
import ExpoModulesCore

public class WatchBridge: Module {
  public func definition() -> ModuleDefinition {
    Name("WatchBridge")

    Function("syncState") { (payload: [String: Any]) in
      guard WCSession.default.activationState == .activated else { return }
      try WCSession.default.updateApplicationContext(payload)
    }
  }
}

5. Wear-OS Data Layer API: MessageClient, DataClient und CapabilityClient

Das Android-Gegenstück heißt Wearable Data Layer API und bietet mit MessageClient ein Analogon zu sendMessage für einmalige, zeitnahe Nachrichten zwischen Telefon und Uhr. Für persistente, automatisch synchronisierte Datenobjekte, die auch über Verbindungsabbrüche hinweg konsistent bleiben, ist DataClient die passende API, vergleichbar mit updateApplicationContext unter watchOS, nur mit granularerer Kontrolle über einzelne Datenpfade statt eines einzigen Gesamtkontexts.

Zusätzlich stellt CapabilityClient fest, welche verbundenen Geräte gerade welche Fähigkeiten anbieten, etwa ob überhaupt eine Wear-OS-App auf einer gekoppelten Uhr installiert ist, bevor man versucht, Daten dorthin zu senden. Diese Erreichbarkeitsprüfung ist in der Praxis wichtig, weil eine React-Native-App sonst versucht, Daten an ein Gerät zu senden, das die Companion-App gar nicht installiert hat, was ansonsten stillschweigend fehlschlägt oder unnötige Fehlerbehandlung im JavaScript-Layer erzwingt.


// android/src/main/java/com/example/watch/WatchBridgeModule.kt
package com.example.watch

import com.google.android.gms.wearable.PutDataMapRequest
import com.google.android.gms.wearable.Wearable
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition

class WatchBridgeModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("WatchBridge")

    AsyncFunction("syncState") { orderStatus: String ->
      val context = appContext.reactContext ?: return@AsyncFunction
      val request = PutDataMapRequest.create("/order-status").apply {
        dataMap.putString("status", orderStatus)
      }
      Wearable.getDataClient(context).putDataItem(request.asPutDataRequest())
    }
  }
}

6. Die Brücke: Ein natives Modul zwischen React Native und Watch-APIs

Die praktische Anbindung läuft über ein natives Modul in der React-Native-App, das auf iOS die WCSession-Delegate-Methoden implementiert und auf Android den MessageClient beziehungsweise DataClient kapselt, jeweils mit einer schlanken JavaScript-Schnittstelle zum Senden und Empfangen von Zustandsänderungen. Ändert sich etwa der Warenkorb-Inhalt oder der Bestellstatus in der React-Native-App, ruft die Fachlogik eine Funktion wie WatchBridge.syncState(payload) auf, die intern die passende native API anspricht.

In die umgekehrte Richtung, von der Watch-App zurück zur React-Native-App, empfängt dasselbe native Modul eingehende Nachrichten über die jeweilige Delegate-Callback-Methode und reicht sie über einen Event-Emitter an den JavaScript-Layer weiter, wo sie wie ein reguläres App-Event, etwa ein Tastendruck oder eine Nutzeraktion auf der Uhr, verarbeitet werden. Diese Zweiwege-Bridge muss für jede Plattform separat implementiert werden, da die zugrunde liegenden APIs konzeptionell ähnlich, aber technisch komplett unterschiedlich sind.


// app/services/watchBridge.ts
import { requireNativeModule } from "expo-modules-core";

const WatchBridge = requireNativeModule("WatchBridge");

export function syncOrderStatusToWatch(status: string): void {
  WatchBridge.syncState({ status });
}

7. Praxisbeispiel: Bestellstatus und Schnell-Reorder auf der Uhr

Ein realistischer Anwendungsfall für einen Shop mit React-Native-App ist eine Watch-Ansicht, die den Status der zuletzt aufgegebenen Bestellung anzeigt, etwa Versandt, In Zustellung oder Zugestellt, zusammen mit einem einzelnen Button für einen Schnell-Reorder der letzten Bestellung. Die eigentliche Bestelllogik, inklusive Zahlungsabwicklung, bleibt bewusst auf dem Telefon, die Uhr löst lediglich eine Anfrage aus, die über die Bridge an die React-Native-App weitergereicht und dort vollständig verarbeitet wird.

Diese bewusste Funktionsreduktion ist typisch für erfolgreiche Watch-Companion-Apps: Statt zu versuchen, den vollständigen Checkout-Flow auf einem kleinen Bildschirm mit stark eingeschränkter Eingabe nachzubilden, beschränkt sich die Watch-App auf schnelle Statusabfragen und eine einzelne, klar definierte Aktion, während alle komplexeren Interaktionen weiterhin über das Telefon laufen, wo Tastatur, größerer Bildschirm und die vollständige React-Native-Oberfläche zur Verfügung stehen.

8. Grenzen der Code-Wiederverwendung

Die UI-Schicht lässt sich zwischen React-Native-App und Watch-App grundsätzlich nicht teilen, weder Komponenten noch Styling-Logik, weil SwiftUI und Jetpack Compose for Wear konzeptionell und technisch nichts mit React-Native-Komponenten gemein haben. Wiederverwendbar sind dagegen reine Datenmodelle und einfache Geschäftsregeln, sofern man sie in einem plattformspezifischen, aber von der React-Native-Bridge unabhängigen Swift- beziehungsweise Kotlin-Package auslagert, das sowohl von der Telefon-App-Bridge als auch von der Watch-App eingebunden wird.

In der Praxis bedeutet das für die meisten Teams: Ein gemeinsames Swift-Package mit reinen Datenstrukturen und Validierungslogik für die iOS-Seite, ein entsprechendes Kotlin-Modul für die Android-Seite, aber vier separate UI-Implementierungen insgesamt, React-Native für das Telefon, SwiftUI für die Apple Watch, Jetpack Compose für Wear OS, und gegebenenfalls eine gemeinsame API-Schicht auf dem Server, die alle vier Clients gleichermaßen bedient.

9. Testing und Auslieferung der Watch-Companion-App

Eine watchOS-App wird über ein eigenes Scheme in Xcode gebaut und getestet, entweder im Watch-Simulator gekoppelt mit dem iOS-Simulator oder auf einer echten Apple Watch, die mit dem Test-iPhone gekoppelt ist. Für die App-Store-Freigabe wird die Watch-App als Teil desselben App-Store-Eintrags wie die iOS-App eingereicht, muss aber eigene Screenshots und teilweise eigene Review-Kriterien erfüllen, insbesondere hinsichtlich sinnvoller Eigenständigkeit der Watch-Funktionen.

Auf Android-Seite wird die Wear-OS-App als zusätzliches APK innerhalb desselben Android App Bundles gebaut und über die Play Console verteilt, getestet zunächst im Wear-OS-Emulator und später auf echter Hardware über dieselbe interne Test-Track-Infrastruktur wie die Telefon-App. Beide Plattformen verlangen, dass die Watch-App auch bei fehlender Netzwerkverbindung zur Telefon-App zumindest einen sinnvollen Leerzustand anzeigt, statt komplett leer oder abstürzend zu erscheinen.

Aspekt watchOS Wear OS
UI-Framework SwiftUI Jetpack Compose for Wear OS
Kommunikations-API WatchConnectivity (WCSession) Wearable Data Layer API
Echtzeit-Nachricht sendMessage MessageClient
Persistenter Zustand updateApplicationContext DataClient
Eigenständiger Betrieb Ab neueren watchOS-Versionen möglich Standalone-Apps offiziell unterstützt

Mironsoft

React-Native-App-Entwicklung und Magento-Anbindung

Eine mobile App zum Magento-Shop, die wirklich rund läuft?

Wir entwickeln React-Native-Apps, die sauber an die Magento REST- oder GraphQL-API angebunden sind, von der ersten Codezeile bis zur Veröffentlichung im App Store und bei Google Play.

App-Konzeption

Architektur und Feature-Umfang einer Magento-angebundenen App gemeinsam planen.

Magento-API-Integration

Produktkatalog, Warenkorb und Checkout sauber an die Shop-API anbinden.

Store-Veröffentlichung

App Store- und Google-Play-Freigabeprozess ohne Stolperfallen begleiten.

10. Zusammenfassung

watchOS- und Wear-OS-Companion-Apps: Das Wichtigste auf einen Blick

Kernaussage

React Native rendert nicht auf der Uhr, Watch-Apps sind immer eigenständige native Targets.

Kommunikation

WatchConnectivity unter iOS, Wearable Data Layer API unter Wear OS.

Wiederverwendbar

Reine Datenmodelle und Geschäftsregeln über plattformspezifische Shared Packages.

Nicht wiederverwendbar

Die komplette UI-Schicht, SwiftUI und Jetpack Compose bleiben getrennt.

11. FAQ: watchOS- und Wear-OS-Companion-Apps: Das Wichtigste auf einen Blick

1Kann ich meine React-Native-App direkt auf der Apple Watch ausführen?
Nein, weder watchOS noch Wear OS bieten eine Laufzeitumgebung für die React-Native-JavaScript-Engine, eine Watch-App muss immer vollständig nativ gebaut werden.
2Welches Framework nutzt man für eine watchOS-Companion-App?
SwiftUI, als eigenständiges Xcode-Target innerhalb desselben Projekts wie die iOS-App.
3Wie tauschen iPhone-App und Watch-App Daten aus?
Über das WatchConnectivity-Framework mit einer WCSession-Instanz, die je nach Anforderung sendMessage, transferUserInfo oder updateApplicationContext nutzt.
4Was ist der Unterschied zwischen sendMessage und updateApplicationContext?
sendMessage liefert Echtzeitdaten, verlangt aber eine erreichbare Gegenstelle, während updateApplicationContext den letzten Zustand zuverlässig überträgt und ältere, noch nicht zugestellte Updates überschreibt.
5Wie funktioniert die Kommunikation bei Wear OS?
Über die Wearable Data Layer API mit MessageClient für einmalige Nachrichten und DataClient für persistente, automatisch synchronisierte Datenobjekte.
6Kann ich UI-Code zwischen React-Native-App und Watch-App teilen?
Nein, die UI-Schicht muss auf der Watch immer vollständig nativ in SwiftUI beziehungsweise Jetpack Compose for Wear implementiert werden.
7Was lässt sich zwischen den Plattformen wiederverwenden?
Reine Datenmodelle und Geschäftsregeln in einem plattformspezifischen Swift- oder Kotlin-Package, nicht aber UI-Komponenten oder Styling.
8Braucht eine Wear-OS-App zwingend ein gekoppeltes Smartphone?
Nicht zwingend, Google unterstützt auch Standalone-Wear-Apps mit eigener Konnektivität, für eine reine Companion-App ist aber meist die gekoppelte Variante relevant.
9Wie prüft man, ob eine Watch-App überhaupt installiert ist, bevor man Daten sendet?
Über CapabilityClient unter Wear OS beziehungsweise die isWatchAppInstalled-Eigenschaft der WCSession unter watchOS.
10Wo läuft die eigentliche Bestelllogik bei einem Watch-Reorder-Feature?
Weiterhin vollständig auf dem Telefon in der React-Native-App, die Watch-App löst über die Bridge lediglich die Anfrage aus.