Teil 1: Project Rome: Apps auf Wanderschaft

Vom Handy zur Xbox zum Desktop und zurück
Kommentare

Microsofts Stärke liegt traditionell im Desktopbereich: Das halbwegs erfolgreiche Windows Mobile ging spätestens mit dem Aufkommen des iPhone den Weg über den Jordan. Um in der heutigen, verbundenen Zeit relevant zu bleiben, muss man im Hause Microsoft die Desktop- und sonstige Infrastruktur so effizient wie möglich mit anderen Diensten verbinden.

Mit Project Rome möchte man in Redmond die Stärke der Xbox und die enorme Verbreitung von Windows am Laptop bzw. am Desktop ausnutzen. Die dahinterstehende Idee ist einfach: Ein Nutzer soll einen Task auf einem Gerät beginnen können, um ihn danach mit „minimalem Aufwand“ auf einem anderen Gerät fertigzustellen.

Die in Vorstellungen gerne besprochene Übergabe eines Films von Handy auf Xbox mag nett aussehen, dürfte in der Praxis aber wenig Relevanz haben. Bessere Anwendungsfälle wären beispielsweise ein Aktienverwaltungsprogramm, das Charts bei Bedarf unter Nutzung einer Xbox oder einer Workstation an einen Beamer sendet.

Artikelserie

Teil 1: Project Rome: Apps auf Wanderschaft

Teil 2: Project Rome auf Abwegen

Teil 3: Komplexe Remote-Interaktionen mit App Services

Im Interesse maximaler Flexibilität beschränkt sich Microsoft nicht auf die hauseigene Cloud: Project Rome funktioniert auch unter Nutzung von Bluetooth oder WLAN. Das Remote-Systems-API sucht automatisch nach dem idealen Kommunikationsmedium: Entwickler können die Endgeräte als „einfach vorhanden“ annehmen. Als Bindeglied zwischen den verschiedenen Geräten eines Nutzers dient ein Microsoft-Account. Dass man sich in Redmond naturgemäß darüber freut, wenn möglichst viele Nutzer die hauseigenen Dienste nutzen, folgt aus der Logik.

Windows Developer wird Ihnen in den kommenden Ausgaben detailliert die Möglichkeiten des Project-Rome-Service vorstellen. Dieser erste Teil wird Grundlagen der Universal Windows Platform vorstellen; im darauffolgenden Artikel werfen wir einen Blick auf Project Rome für Android, und der dritte und letzte Artikel geht sodann auf App-Services ein, die die Realisierung fortgeschrittener Kommunikationsszenarien ermöglichen.

Eine Frage der Arbeitsumgebung

Da Microsoft mittlerweile diverse Betriebssysteme – darunter auch die einstigen Todfeinde Android und iOS – unterstützt, ist für eine vollständige Betrachtung von Project Rome einiges an Hardware erforderlich. Der Autor nutzt in den folgenden Schritten ein unter Windows 10 Version 1703 laufendes Lenovo ThinkPad T430, ein unter Windows 10 Version 10.0.14393.1066 laufendes TecLast X98-Pro und auf Seiten von Android ein Vernee Apollo Lite mit Android 6.0.

Aktiv und passiv

Bei der Betrachtung des Remote Systems-API ist es empfehlenswert, Geräte in aktive und passive Teilnehmer zu unterteilen. Ein aktiver Teilnehmer kann hierbei Kommandos senden, während ein passives Device Kommandos entgegennimmt. Universal-Windows-Platform-basierte Systeme können beide Rollen ausfüllen, während Android und iOS nur zum Absetzen von Befehlen fähig sind.

Microsoft zeigt sich im Bereich der Windows-Version übrigens relativ kulant: Project Rome läuft auf allen Versionen von Windows 10 ab Version v10.0.14393.0. Zudem ist zum Test natürlich ein Microsoft-Account erforderlich, der mit den lokalen Benutzerkonten des ThinkPads und des Tablets verbunden sein muss.

Für die folgenden Schritte setzen wir auf Visual Studio Community 2017: Als Universal Windows SDK kommt die für das Creators Update vorgesehene Version zum Einsatz. Erstellen Sie im nächsten Schritt ein neues Projekt für die Universal Windows Platform: Der Autor nutzt in den folgenden Schritten die Vorlage Visual C# | Windows Universal | Blank App (Universal Windows). Die Vergabe des Namens kann im Großen und Ganzen beliebig erfolgen – wir wählen für dieses Beispiel den Namen SUSRome1.

Nach dem üblichen Abarbeiten des Projektgenerators müssen Sie das Programm im ersten Schritt um eine Capability erweitern. Die in der Windows-for-IoT-Welt erforderlichen händischen Manipulationen an der Manifestdatei sind nicht mehr notwendig: Klicken Sie die Datei im Solution Explorer doppelt an, um sie im grafischen Editor zu öffnen. Markieren Sie sodann die in Abbildung 1 dargestellte Option „Remote System“, um das betreffende Feature zu aktivieren.

Abb. 1: Microsoft kommt dem Versprechen von WYSIWYG an dieser Stelle nach

Im nächsten Schritt ist ein Knopf erforderlich, der für die Aktivierung des asynchron ablaufenden Suchvorgangs zuständig ist. Legen Sie ihn auf die gewohnte Art und Weise in der XAML-Datei an und verdrahten Sie ihn mit dem Event Handler aus Listing 1.

private async void CmdStartSearch_Click(object sender, RoutedEventArgs e){
  RemoteSystemAccessStatus accessStatus = await RemoteSystem.RequestAccessAsync();
  if (accessStatus == RemoteSystemAccessStatus.Allowed) {
    myRSW = RemoteSystem.CreateWatcher();
    myRSW.RemoteSystemAdded += RemoteSystemWatcher_RemoteSystemAdded;
    myRSW.RemoteSystemRemoved += RemoteSystemWatcher_RemoteSystemRemoved;
    myRSW.Start();
  }
}

Die Interaktion mit dem Remote-Systems-API erfolgt über Event Handler. Im ersten Schritt beschaffen wir hierbei unter Nutzung der Klasse RemoteSystem eine Instanz des RemoteSystemWatchers, der für die Überwachung und Verwaltung der über das Remote-Systems-API ansprechbaren Endstellen verantwortlich ist.

Sie bekommt vor dem Anwerfen der Überwachungsoperation zwei Event Handler eingeschrieben, deren Deklaration wir uns sogleich zuwenden wollen. Vorher müssen Sie die Page noch um eine globale Member-Variable erweitern, die für das Vorhalten der Watcher-Klasse verantwortlich ist:

public sealed partial class MainPage : Page {

public RemoteSystemWatcher myRSW;

private Dictionary<string, RemoteSystem> myDevices = new Dictionary<string, RemoteSystem>();

Zudem legen wir an dieser Stelle auch eine Dictionary-Instanz an, die die einzelnen Remote-Devices-Objekte vorhält: Sie sind für das Absetzen von Befehlen an die Endgeräte unbedingt erforderlich. Als „Schlüssel“ dient hierbei ein String, der die in den RemoteSystem-Objekten enthaltene ID bereithält.

Die RemoteSystem-Klasse enthält auch eine Gruppe weiterer Attribute, die sich durch Reflexion auf den Bildschirm holen lassen (Listing 2).

public sealed class RemoteSystem : IRemoteSystem, IRemoteSystem2 {

. . .

public string DisplayName { get; }

public string Id { get; }

public bool IsAvailableByProximity { get; }

public string Kind { get; }

public RemoteSystemStatus Status { get; }

public bool IsAvailableBySpatialProximity { get; }

Die hier verwendeten Attribute lassen sich auch zur Filterung der Suchoperationen einsetzen: Bei bandbreitenintensiven Anwendungen (oder einer sehr umfangreichen Gerätesammlung im Account des Nutzers) kann es wünschenswert sein, die Anzeige auf in der näheren Umgebung greifbare Anlagen zu beschränken.

Für uns ist dies an dieser Stelle allerdings nicht interessant, da wir davon ausgehen, dass sich der Geräteverbund des zum Test verwendeten Nutzerkontos nicht sonderlich umfangreich präsentiert.

Als nächste Aufgabe können wir uns der Realisierung der Event Handler zuwenden, die für das Aktualisieren der Dictionary-Datenstruktur vorgesehen sind und für .NET-erfahrene Entwickler keine großen Überraschungen enthalten (Listing 3).

private void RemoteSystemWatcher_RemoteSystemRemoved(RemoteSystemWatcher sender, RemoteSystemRemovedEventArgs args) {

if (myDevices.ContainsKey(args.RemoteSystemId)) {

myDevices.Remove(args.RemoteSystemId);

}

}

private void RemoteSystemWatcher_RemoteSystemAdded(RemoteSystemWatcher sender, RemoteSystemAddedEventArgs args) {

myDevices.Add(args.RemoteSystem.Id, args.RemoteSystem);

}

Interessant ist an dieser Stelle eigentlich nur, dass einmal angemeldete Geräte auch wieder verschwinden können; in diesem Fall wird das RemoteSystem-Objekt ungültig; Aufrufe seiner Methoden führen zu undefiniertem Programmverhalten und/oder Exceptions.

Im nächsten Schritt setzen Sie einen Breakpoint in die Methode RemoteSystemWatcher_RemoteSystemAdded und starten das Programm. Klicken Sie danach auf den im vorherigen Schritt angelegten Button, um das Programm zur Analyse der Umgebung zu animieren. Je nach Konfiguration wird binnen einiger Zeit eine Unterbrechung erfolgen, die Sie darauf hinweist, dass ein Device gefunden wurde.

Auf Fehlerjagd

In der Theorie dauert die Suche nach Geräten maximal eine oder zwei Sekunden. In Tests des Autors sprach der Suchalgorithmus anfangs nicht sofort an, obwohl sowohl das für die Programmausführung zuständige ThinkPad als auch das TecLast X98 Pro eingeschaltet und mit demselben Netzwerk verbunden waren.

Zur Lösung dieses Problems müssen Sie die Option „Manage my Microsoft Account“ öffnen, die in der Systemsteuerung unter Settings | Accounts bereitsteht. Klicken Sie dann auf die Option „See All“ in der Rubrik Devices, um die in Abbildung 2 gezeigte Geräteliste auf den Bildschirm zu holen.

Abb. 2: Das Backend des Microsoft-Accounts listet die diversen verbundenen Geräte auf

Der kleine Unterschied in der Windows-Version erweist sich in der Praxis als unproblematisch. Viel kritischer war, dass das Tablet nach dem Hinzufügen des Microsoft-Accounts nicht neu gestartet worden war. Zudem erwies sich die Erkennungslogik in den Tests des Autors als schwergängig: Manchmal verging eine halbe Stunde, bis ein neu eingepflegtes Gerät erstmals in der Liste erschien.

Beim Warten dürfen Sie übrigens nicht vergessen, den Button Suche Starten regelmäßig anzuklicken; Microsoft spendiert nach einem Aufruf von Start nämlich nur 30 Sekunden Suchzeit, die Klasse stellt die Arbeit daraufhin selbsttätig ein. Zur Umgehung dieses Problems bietet sich beispielsweise das Einbinden eines Timers an, der den Suchprozess regelmäßig neu startet.

Wie dem auch sei: Wir wollen in den folgenden Schritten davon ausgehen, dass die Erkennung von Remote Devices problemlos funktioniert und es während der Programmausführung zu einer oder mehreren Unterbrechungen kommt.

Funktioniert dies aus irgendeinem Grund partout nicht, so können Sie auch auf die folgende Methode des RemoteSystem-Objekts zurückgreifen, die das „direkte“ Einschreiben von Hostinformationen erlaubt:

 
public sealed class RemoteSystem : IRemoteSystem, IremoteSystem2 {

[RemoteAsync]

public static IAsyncOperation<RemoteSystem> FindByHostNameAsync(HostName hostName);

Eine Frage der Kommunikation

Auch wenn das Realisieren von XAML Data Binding gegen eine RemoteSystem Collection eine durchaus interessante Fingerübung wäre: In diesem Artikel geht es nur um Project Rome. Aus diesem Grund gehen wir in den folgenden Schritten davon aus, dass alle im Konto des Benutzers enthaltenen Geräte „faire Ziele“ für die Abarbeitung unserer Programme sind. Mit dieser Information können wir uns im nächsten Schritt daran machen, auf dem Zielgerät eine Aktion auszuführen.

Achtung: Ärger auf der Xbox One!

Laut Benutzerberichten in Stack Overflow kommt es auf der Xbox One mit der Betriebssystemversion 10.0.14393.2113 zu Problemen. Als Lösung bietet sich ein erzwungenes Downgrade auf die Version 14393.2152.161208-1218 oder ein Update auf eine neuere Version an.

Was nun? Was tun?

Das Project-Rome-API bietet zwei Möglichkeiten zur Festlegung des Ziels: Erstens die vergleichsweise komplexe Realisierung eines Application Service, der bidirektionale Kommunikation erlaubt und im dritten Teil dieser Artikelserie zur Sprache kommen wird. Zweitens ermöglichen die Rome-Services das Übertragen von URLs vom Sender zum Ziel.

In der Praxis ist das Übertragen eines URL, der vom Zielgerät nach Belieben „geparst“ wird, die Regel. Wir wollen uns in diesem Artikel – aus Gründen der Bequemlichkeit und der didaktischen Kompaktheit – anfangs mit der Ausführung von URLs beschäftigen und die wesentlich aufwendigere Arbeit mit dem Service erst im nächsten Teil durchführen.

Als erste Fingerübung bietet sich an dieser Stelle das Öffnen von Bing Maps an; der von Microsoft einst auf Mobile World Congress und Co. hochgelobte Kartendienst funktioniert in der Praxis problemlos und stellt eine integrale Komponente der Universal Windows Platform dar. Aufgrund des Sicher-Vorhanden-Seins des Produkts wollen wir ihn für einen ersten Test einspannen. Erzeugen Sie hierzu einen weiteren Button in unserem Programm, das mit dem Code in Listing 4 zu verdrahten ist.

 
private async void CmdOpenBing_Click(object sender, RoutedEventArgs e) {
  foreach (RemoteSystem SelectedDevice in myDevices.Values){
    RemoteLaunchUriStatus launchUriStatus =
      await RemoteLauncher.LaunchUriAsync(
        new RemoteSystemConnectionRequest(SelectedDevice),
        new Uri("bingmaps:?cp=47.6204~-122.3491&sty=3d&rad=200&pit=75&hdg=165"));
  }
}

Auch wenn dieser Code auf den ersten Blick erschlagend wirkt: Sein Aufbau ist primitiv. Im ersten Schritt nutzen wir einen Iterator, der alle im myDevices-Feld befindlichen Geräte anspricht. In unserem Fall ist dies insofern unkritisch, als wir davon ausgehen, dass das Feld nur ein Tablet enthält. Wer mehrere Geräte mit seinem Konto verbunden hat, sollte darauf achten, dass er nicht versehentlich Kollegen bei der Arbeit stört.

Im nächsten Schritt nutzen wir die LaunchUriAsync-Methode, um das Remote-Systems-API von Windows 10 anzuweisen, den jeweiligen URL auf das System zu übertragen und unter Nutzung des dortigen Servers aufzulösen. Der asynchrone Aufruf würde sogar eine Resultatvariable retournieren, die uns an dieser Stelle aber nicht interessiert. Führen Sie das Programm stattdessen in der vorliegenden Form aus, und erfreuen Sie sich an der Anzeige des „Markenzeichens“ einer von Microsoft für interessant befundenen Stadt.

Neben der hier verwendeten Bing-Maps-Applikation gibt es auch ein rundes Dutzend weiterer Applikationen, die als Teil des Betriebssystems ausgeliefert werden. So ist es beispielsweise problemlos möglich, bestimmte Einstellungsseiten direkt aufzurufen – ein Feature, das das Einrichten von Features wesentlich erleichtert. Zum „Herumexperimentieren“ bietet es sich an, ein gewöhnliches Kommandozeilenfenster zu öffnen. Geben Sie danach das Kommando Start, gefolgt von dem Ziel-URL ein.

Mein eigener URL

Auch wenn das Öffnen von Bing Maps durchaus lustig ist: Wirklich interessant wird das Hantieren mit dem Remote-Systems-API erst dann, wenn Sie damit ein eigenes Programm aufrufen können. Für diese Aufgabe müssen wir – logischerweise – einen weiteren Testharnisch erzeugen, der in den folgenden Schritten auf den Namen SUSClient hört und analog zum Hauptprogramm in Form einer Universal-Windows-Platform-Applikation vorliegt. Im Beispielcode zum Heft finden Sie das Projekt als Teil der Solution SUSRome1; achten Sie beim Deployment lediglich darauf, dass der betreffende Code über Remote Deployment auf das Zielsystem gebracht werden muss, bevor die Aktivierung des URL aus dem Hauptprogramm heraus erfolgen kann.

Grüße von Tovarich Haxor!

Microsoft weist in der Dokumentation explizit darauf hin, dass Windows die Herkunft der URLs in keiner Weise verifiziert. Achten Sie also darauf, dass bösartige Websites oder Drittanbieterprogramme keine destruktiven Aktionen durchführen können.</p class=“boxed“>

Entwickler können bei der Vergabe eines URL-Schemas unter Windows 10 im Großen und Ganzen nach Belieben schalten und walten – in Redmond hält man sich lediglich eine Gruppe von einigen Dutzend Schemata reserviert, die in der MSDN aufgelistet sind.

Die Konfiguration der Annahme von URLs erfolgt hierbei in der Manifestdatei, die wie gewohnt im grafischen Editor geöffnet wird. Wechseln Sie danach in den Declarations-Tab, wählen Sie in der Rubrik „Available Declarations“ den Wert „Protocol“ aus und klicken Sie zu guter Letzt auf Add. Der Editor blendet daraufhin eine Gruppe von Feldern ein, die für uns allerdings irrelevant sind – wichtig ist nur der Wert „Name“, in dem der String „susrometest2342“ zum Liegen kommt. Speichern Sie die Änderungen; dank der Eintragung im Manifest ist unser Programm nun zum Entgegennehmen von URL-Aufrufen befähigt.

Als Nächstes muss das Programm einen Einstiegspunkt erhalten, der in App.xaml.cs zum Liegen kommt (Listing 5).

sealed partial class App : Application
{
  public String myURL;
  protected override void OnActivated(IActivatedEventArgs args)
  {
    if (args.Kind == ActivationKind.Protocol) {
      ProtocolActivatedEventArgs myArgs = args as ProtocolActivatedEventArgs;
      myURL = myArgs.Uri.AbsoluteUri;
    }
  }
}

Aus technischer Sicht findet sich hier keine Raketenwissenschaft: Wenn das an OnActivated übergebene „Begründungsobjekt“ auf eine Aktivierung durch einen URL hinweist, konvertieren wir das angelieferte Parameterobjekt. Im nächsten Schritt wandert der für die Aktivierung verantwortliche URL in eine öffentliche Member-Variable der Application-Klasse, über die sie später abgeerntet werden kann.

Da dieser Artikel nicht in ein Tutorial über den (sehr interessanten) Lebenszyklus von Universal-Windows-Platform-Programmen ausarten soll, wollen wir uns auf das Anlegen einer im Rahmen des erstmaligen Ladens des Programms zu bevölkernden Textbox beschränken.

In Mainpage.xaml.cs ist im Konstruktor eine kleine Änderung erforderlich (Listing 6).

  public sealed partial class MainPage : Page
{
  public MainPage()
  {
    this.InitializeComponent();
    if ((Application.Current as App).myURL != null)
    {
      TxtURL.Text = (Application.Current as App).myURL;
    }
    else {
      TxtURL.Text = "Keine URL!";
    }
  }
}

Von besonderem Interesse ist hier nur die sehr kompakte Art des Casts: Dank der „vorgeschalteten“ Klammer können wir den in der App angelegten myURL-Wert direkt in die Texteigenschaft weiterleiten.

Schicken Sie das Programm nach getaner Arbeit unter Nutzung des Remote Debuggers auf das Tablet, wo es zur Ausführung bereitsteht. Beenden Sie es danach mit den vom Debugger dafür zur Verfügung gestellten Mitteln – unser Programm enthält keine Logik, um auf während der Ausführung eingehende URL-Ereignisse zu reagieren.

Daraufhin muss der Testharnisch des Hauptprogramms angepasst werden, sodass er statt Bing Maps unser Programm aktiviert (Listing 7).

  
private async void CmdOpenBing_Click(object sender, RoutedEventArgs e)
{
foreach (RemoteSystem SelectedDevice in myDevices.Values)
{
RemoteLaunchUriStatus launchUriStatus =
await RemoteLauncher.LaunchUriAsync(
new RemoteSystemConnectionRequest(SelectedDevice),
new Uri("susrometest2342:?hallowelt=freundlich"));
}
}

Führen Sie das Programm sodann wie gewohnt aus und klicken Sie abermals auf den Button Bing Öffnen. Das Tablet wird auf die Anfrage nun mit dem Anzeigen des SUS-Beispiels reagieren, das im Moment aber nur den zur Verkürzung der Boot-Zeit von Microsoft vorgeschriebenen „Splashscreen“ anzeigt.
Dieses auf den ersten Blick seltsam wirkende Verhalten liegt daran, dass OnActivated nicht automatisch einen Aufruf von OnLaunched auslöst. Da die eigentliche Programmstartlogik allerdings in dieser Routine liegt, bleibt das für die Anzeige vorgesehene Fenster leer. Eine bessere Version des Codes ist in Listing 8 dargestellt.

  

protected override void OnActivated(IActivatedEventArgs args)
{
  if (args.Kind == ActivationKind.Protocol) {
    ProtocolActivatedEventArgs myArgs = args as ProtocolActivatedEventArgs;
    myURL = myArgs.Uri.AbsoluteUri;
    if (Window.Current.Content == null)
    {
      Window.Current.Content = new MainPage();
    }
    Window.Current.Activate();
  }
}

Nach der Anpassung von OnActivated zeigt das Tablet nach dem Anklicken des betreffenden Buttons das Applikationsfenster samt dem an RemoteSystemConnectionRequest übergebenen URL an. Damit ist bewiesen, dass das Austauschen von Kommandos zwischen den Geräten problemlos funktioniert.

Fazit

Konservative Naturen verbinden ihr Log-in-Konto nur ungern mit dem Microsoft-Account und bekommen bei der erstmaligen Einrichtung der Beziehung für Project Rome dementsprechend Schwierigkeiten mit dem System. In der Praxis funktioniert Rome allerdings bestens – das Anwerfen von Programmen erfolgt problemlos.

Die Möglichkeiten des Remote-Systems-API sind damit allerdings nicht annähernd ausgeschöpft. Im nächsten Teil wenden wir uns der Arbeit mit Android zu, um im dritten Teil „komplexere“ Interaktionen zu realisieren – der Autor wünscht bis dahin viel Spaß!

Windows Developer

Windows DeveloperDieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -