Im ersten Teil haben wir uns mit der Einrichtung der Entwicklungsumgebung zum Schreiben von .NET MAUI-Anwendungen für die Wear OS-Plattform befasst. Nach der Einführung in die Plattform und dem Ausführen unserer ersten Emulation können wir uns nun kurze Tipps zur geräteübergreifenden Kommunikation, zum Abhören von Ereignissen sowie zur Lösung einiger aufgetretener Verteilungsprobleme ansehen.
Die Wear OS-Anwendung selbst ist keine Dotnet-MAUI-Anwendung, sondern eine gewöhnliche Dotnet-Android-Anwendung, wie die früheren nativen Xamarin.Android-Projekte, aber mit .NET-Paketen. Die Struktur ist jedoch die gleiche - es gibt Activities, in denen etwas UI-Logik geschrieben wird, und XML-Layout-Dateien im Ordner Resources/Layout, die die UI selbst definieren.
Denken Sie daran, die Benutzeroberfläche einfach zu gestalten und bedenken Sie, dass Ihre Benutzer Ihre Anwendung buchstäblich am Handgelenk tragen werden. Sie muss also einfach und benutzerfreundlich sein, mehr noch als eine mobile Anwendung. Einen umfassenden Leitfaden für die Entwicklung von Benutzeroberflächen für Wear OS finden Sie hier: https://developer.android.com/design/ui/wear
Für die Kommunikation mit Online-Ressourcen muss der Entwickler kein eigenes Gateway für die mobile Anwendung schreiben. Dies übernimmt das Wear OS selbst. Es bietet eine Netzwerkverbindung über direktes WiFi oder über eine Bluetooth-Verbindung über das Mobiltelefon. Das Netzwerk ist jedoch versteckt und nur für den Entwickler verfügbar oder nicht.
Die wichtigste Funktion für nicht eigenständige Wear-OS-Anwendungen ist die Kommunikation mit mobilen Anwendungen über Bluetooth. Das Konzept der Kommunikation zwischen den Geräten der Benutzer ist für den Entwickler hinter der statischen Klasse WearableClass verborgen. Diese API stellt (unter anderem) den DataClient zur Verfügung, der es ermöglicht, Nachrichten zu publizieren und Listener anzuhängen, um die von anderen gekoppelten Geräten publizierten Nachrichten zu hören.
Die Veröffentlichung von Daten von Uhren auf Mobiltelefonen (oder umgekehrt) erfolgt durch Code wie:
var dataMap = PutDataMapRequest.Create(“/specific_path”);
dataMap.DataMap.PutString(“MessageKey”, “Message Value”);
var request = dataMap.AsPutDataRequest();
WearableClass.GetDataClient(Application.Context).PutDataItem(request);
Auf dem anderen Gerät fügen wir dem Listener für denselben Pfad eine Lesezeichennachricht hinzu, wenn sie eintrifft:
public override void OnDataChanged(DataEventBuffer dataEvents) {
foreach (var data in dataEvents) {
if (data.DataItem.Uri.Path != “/specific_path”) continue;
var item = DataMapItem.FromDataItem(data.DataItem);
var message = data.DataMap.GetString(“MessageKey”);
... do something with received message string
break;
}
}
}
Neben dem DataClient bietet WearableClass weitere Clients an - CapabilityClient, MessageClient, NodeClient, ... Für weitere Informationen folgen Sie bitte diesem Link:
https://developer.android.com/training/wearables/data/data-layer
Die Bluetooth-Kommunikation zwischen Mobiltelefon und Uhr basiert auf Nachrichten. Sie können die Daten nicht einfach vom Handy auf die Uhr "lesen". Man muss die Daten abfragen und auf die Antwort warten.
In realen Szenarien beim Start der Wear OS Anwendung und der Synchronisierung mit dem Mobiltelefon:
1. Wir müssen die Anfrage mit PutDataItem (siehe oben) auf einem bestimmten Pfad in der Wear OS App veröffentlichen.
2. Auf der mobilen Seite muss ein Listener für einen bestimmten Pfad registriert werden.
3. Wenn die Anfrage eintrifft, wird sie verarbeitet und die mobile Anwendung muss ihre Antwort auf einem anderen Pfad veröffentlichen.
4. Auf den Uhren muss auf Daten auf einem anderen Pfad gewartet werden und die von der mobilen Anwendung veröffentlichte "Antwort" abgefangen werden.
Wie wird sichergestellt, dass veröffentlichte Nachrichten an das andere Gerät geliefert werden?
Es gibt ein verstecktes Feature/Fehler in WearableClass bei der Veröffentlichung von Daten. Es werden nur die Daten veröffentlicht, die sich seit der letzten Veröffentlichung geändert haben. Wenn die Daten gleich sind, überspringt die WearableClass-Schicht die Datenveröffentlichung ohne Warnung oder Antwort.
Der beste Weg, um sicherzustellen, dass unsere Logik in der Kommunikation zwischen Mobiltelefon und Uhr richtig funktioniert, ist, die einzelnen Daten bei der Veröffentlichung mit einem Zeitstempel zu versehen. Im obigen Beispiel sollte dies wie folgt aussehen
dataMap.DataMap.PutString(“TimeStamp”, DateTime.UtcNow.Ticks.ToString());
dataMap.DataMap.PutString(“MessageKey”, “Message Value”);
Eine häufig auftretende Aufgabe, die die Benutzerfreundlichkeit unserer Wear OS Anwendung erheblich verbessert, ist das Starten der Uhrenanwendung, wenn der Benutzer die mobile Anwendung öffnet. Dies wird nicht automatisch von der WearableClass API erledigt. Wir müssen uns selbst darum kümmern.
In der Hauptaktivität unseres Android-Projekts der MAUI-Applikation überschreiben wir die OnResume-Methode und veröffentlichen die Nachricht an alle verbundenen Knoten (=Geräte):
protected override void OnResume(){
base.OnResume();
var nodes = await WearableClass.GetNodeClient(this)
.GetConnectedNodesAsync();
foreach (var node in nodes)
await WearableClass.GetMessageClient(this)
.SendMessage(node.Id, “/app_starts, null);
}
Und in unserer Wear OS Anwendung erstellen wir den StartupListenerService:
[Service(Exported = true, Name= "bundleid.StartupListenerService")]
[IntentFilter(new[] { "com.google.android.gms.wearable.BIND_LISTENER" })]
public class StartupListenerService : WearableListenerService {
public override void OnMessageReceived(IMessageEvent p0) {
if (p0.Path.Equals(“/app_starts”)) {
var intent = new Intent(Application.Context, typeof(MainActivity));
intent.AddFlags(ActivityFlags.NewTask);
StartActivity(intent);
} else {
base.OnMessageReceived(p0);
}
}
}
Und registrieren Sie es in der Datei AndroidManifest.xml:
<application … >
<uses-library android:name="com.google.android.wearable" android:required="true" />
<meta-data android:name="com.google.android.wearable.standalone" android:value="false" />
<service android:name="bundleid.StartupListenerService" android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
</application>
Bitte beachten Sie, dass im Service der Servicename (bundleid.StartupListenerService) explizit im ServiceAttribut oberhalb der Klassendefinition angegeben werden muss. Derselbe Name muss auch im AndroidManifest angegeben werden.
Wir bauen eine Android Wear OS Erweiterung für unsere .NET MAUI Anwendung, die plattformübergreifend ist und auf beiden Plattformen - Android und iOS - funktionieren muss. Daher haben wir plattformspezifische Implementierungen von Komponenten für die Uhr erstellt, die durch ihre Schnittstelle definiert sind.
- Für iOS ignorieren wir vorerst alle Aufrufe an Uhren - diese werden später für die Apple Watch OS Version implementiert.
- Für Android werden alle Listener und Publisher mit der WearableClass API implementiert.
Alle Komponenten, die sich auf die Uhr beziehen, wurden im IoC-Container registriert und werden über ihre Schnittstellen in den restlichen Code der mobilen Anwendung injiziert.
Nachdem wir als Entwickler alle Funktionen fertiggestellt haben und die Alpha-Tests in unserer Entwicklungsumgebung gut verlaufen sind, werden wir die Applikation für weitere Tests und die Produktion freigeben.Zu diesem Zeitpunkt trat ein sehr unglückliches Problem in unserer Wear OS Applikation auf. Die Kommunikation über WearableClass funktionierte nicht mehr und die Uhrenapplikation reagierte nicht mehr auf Nachrichten/Daten, die über DataClient verteilt wurden.
Wir haben das Problem sorgfältig untersucht und die Ursache gefunden - ein Problem mit dem Signaturzertifikat.
Damit die Wearable Data Layer zwischen dem Mobiltelefon und der Uhrenanwendung funktionieren kann, müssen zwei Bedingungen erfüllt sein:
1. Beide Apps müssen dieselbe App-ID haben (z. B. com.sabo.ias.sabot.mobile).
2. Beide .apk-Dateien müssen mit dem gleichen Keystore-Zertifikat signiert sein.
Wenn wir unsere App für die Beta-Verteilung nicht mit demselben Zertifikat signieren wie die Watch-App, werden die API-Anforderungen der Datenebene ignoriert.
Die beste Lösung besteht darin, die ".APK-Signatur" in den Android-Eigenschaften der .NET MAUI-Anwendung für mobile Geräte und der .NET Android-Anwendung für Uhren zu aktivieren und die Details des Keystore-Zertifikats einzugeben. Für Entwicklungs- und QA-Zwecke kann ein vom Entwickler erstelltes, nicht vertrauenswürdiges Zertifikat verwendet werden (z.B. bei der Verteilung der MAUI-Anwendung über die Archivierungsoption in Visual Studio). Für die Produktion muss ein öffentlich vertrauenswürdiges Entwicklerzertifikat verwendet werden.
Zusammenfassend hebt diese Präsentation unserer .NET MAUI Android Watch-Anwendung die vielseitigen und leistungsstarken Funktionen des Frameworks hervor. Wir hoffen, dass es Ihnen Spaß gemacht hat, es durchzugehen, und dass Sie etwas Nützliches für Ihre zukünftigen Unternehmungen gelernt haben.