HoloLens (1. Generation) und Azure 311: Microsoft Graph

Hinweis

Die Tutorials der Mixed Reality Academy wurden im Hinblick auf HoloLens (1. Gen.) und immersive Mixed Reality-Headsets entworfen. Daher halten wir es für wichtig, diese Tutorials für Entwickler verfügbar zu halten, die noch nach Anleitung beim Entwickeln für diese Geräte suchen. Diese Tutorials werden nicht mit den neuesten Toolsets oder Interaktionen aktualisiert, die für HoloLens 2 verwendet werden. Sie werden gewartet, um weiterhin auf den unterstützten Geräten zu funktionieren. Es wird eine neue Reihe von Tutorials geben, die in Zukunft veröffentlicht werden, die zeigen, wie für HoloLens 2 entwickelt werden kann. Dieser Hinweis wird mit einem Link zu diesen Tutorials aktualisiert, wenn sie veröffentlicht werden.

In diesem Kurs erfahren Sie, wie Sie microsoft Graph verwenden, um sich mithilfe der sicheren Authentifizierung in einer Mixed Reality-Anwendung bei Ihrem Microsoft-Konto anzumelden. Anschließend rufen Sie Ihre geplanten Besprechungen auf der Anwendungsoberfläche ab und zeigen sie an.

Screenshot: Geplante Besprechungen in der Anwendungsoberfläche

Microsoft Graph ist eine Reihe von APIs, die den Zugriff auf viele Dienste von Microsoft ermöglichen. Microsoft beschreibt Microsoft Graph als eine Matrix von Ressourcen, die durch Beziehungen verbunden sind, was bedeutet, dass eine Anwendung auf alle Arten von verbundenen Benutzerdaten zugreifen kann. Weitere Informationen finden Sie auf der Microsoft Graph-Seite.

Die Entwicklung umfasst die Erstellung einer App, in der der Benutzer angewiesen wird, eine Kugel zu betrachten und dann zu tippen, wodurch der Benutzer aufgefordert wird, sich sicher bei einem Microsoft-Konto anzumelden. Nach der Anmeldung bei ihrem Konto kann der Benutzer eine Liste der für den Tag geplanten Besprechungen anzeigen.

Nach Abschluss dieses Kurses verfügen Sie über eine Mixed Reality HoloLens-Anwendung, die folgendes ausführen kann:

  1. Tippen Sie mithilfe der Tap-Geste auf ein Objekt, das den Benutzer auffordert, sich bei einem Microsoft-Konto anzumelden (aus der App heraus, um sich anzumelden, und dann wieder in die App zurück).
  2. Zeigen Sie eine Liste der besprechungen an, die für den Tag geplant sind.

In Ihrer Anwendung liegt es bei Ihnen, wie Sie die Ergebnisse in Ihr Design integrieren. In diesem Kurs erfahren Sie, wie Sie einen Azure-Dienst in Ihr Unity-Projekt integrieren. Es ist Ihre Aufgabe, das Wissen, das Sie aus diesem Kurs gewinnen, zu nutzen, um Ihre Mixed Reality-Anwendung zu verbessern.

Geräteunterstützung

Kurs HoloLens Immersive Headsets
MR und Azure 311: Microsoft Graph ✔️

Voraussetzungen

Hinweis

Dieses Tutorial richtet sich an Entwickler, die über grundlegende Erfahrungen mit Unity und C# verfügen. Bitte beachten Sie auch, dass die Voraussetzungen und schriftlichen Anweisungen in diesem Dokument das darstellen, was zum Zeitpunkt des Schreibens (Juli 2018) getestet und überprüft wurde. Sie können die neueste Software verwenden, wie im Artikel Installieren der Tools aufgeführt, obwohl nicht davon ausgegangen werden sollte, dass die Informationen in diesem Kurs perfekt dem entsprechen, was Sie in neuerer Software finden, als die unten aufgeführten.

Wir empfehlen die folgende Hard- und Software für diesen Kurs:

Vorbereitung

  1. Um Probleme beim Erstellen dieses Projekts zu vermeiden, wird dringend empfohlen, das in diesem Tutorial erwähnte Projekt in einem Stamm- oder Fast-Root-Ordner zu erstellen (lange Ordnerpfade können zur Buildzeit Zu Problemen führen).
  2. Richten Sie Ihre HoloLens ein und testen Sie sie. Wenn Sie Unterstützung beim Einrichten Ihrer HoloLens benötigen, lesen Sie den Artikel HoloLens-Setup.
  3. Es ist eine gute Idee, Kalibrierung und Sensoroptimierung durchzuführen, wenn Sie mit der Entwicklung einer neuen HoloLens-App beginnen (manchmal kann dies helfen, diese Aufgaben für jeden Benutzer auszuführen).

Hilfe zur Kalibrierung finden Sie unter diesem Link zum Artikel HoloLens-Kalibrierung.

Hilfe zur Sensoroptimierung finden Sie unter diesem Link zum Artikel HoloLens Sensoroptimierung.

Kapitel 1: Erstellen Ihrer App im Anwendungsregistrierungsportal

Zunächst müssen Sie Ihre Anwendung im Anwendungsregistrierungsportal erstellen und registrieren.

In diesem Kapitel finden Sie auch den Dienstschlüssel, mit dem Sie Anrufe an Microsoft Graph tätigen können, um auf Ihre Kontoinhalte zuzugreifen.

  1. Navigieren Sie zum Microsoft-Anwendungsregistrierungsportal , und melden Sie sich mit Ihrem Microsoft-Konto an. Nachdem Sie sich angemeldet haben, werden Sie zum Anwendungsregistrierungsportal weitergeleitet.

  2. Klicken Sie im Abschnitt Meine Anwendungen auf die Schaltfläche App hinzufügen.

    Screenshot, der zeigt, wo Sie App hinzufügen auswählen.

    Wichtig

    Das Anwendungsregistrierungsportal kann unterschiedlich aussehen, je nachdem, ob Sie zuvor mit Microsoft Graph gearbeitet haben. Die folgenden Screenshots zeigen diese verschiedenen Versionen an.

  3. Fügen Sie einen Namen für Ihre Anwendung hinzu, und klicken Sie auf Erstellen.

    Screenshot: Hinzufügen eines Namens für Ihre Anwendung

  4. Nachdem die Anwendung erstellt wurde, werden Sie zur Anwendungsseite Standard weitergeleitet. Kopieren Sie die Anwendungs-ID , und notieren Sie sich diesen Wert an einem sicheren Ort. Sie werden ihn bald in Ihrem Code verwenden.

    Screenshot: Anzeige der Anwendungs-ID

  5. Stellen Sie im Abschnitt Plattformen sicher, dass native Anwendung angezeigt wird. Klicken Sie andernfalls auf Plattform hinzufügen , und wählen Sie Native Anwendung aus.

    Screenshot: Hervorhebung des Abschnitts

  6. Scrollen Sie auf derselben Seite nach unten, und im Abschnitt Microsoft Graph-Berechtigungen müssen Sie zusätzliche Berechtigungen für die Anwendung hinzufügen. Klicken Sie neben Delegierte Berechtigungen auf Hinzufügen.

    Screenshot, der zeigt, wo Neben Delegierte Berechtigungen die Option Hinzufügen ausgewählt werden soll.

  7. Da Ihre Anwendung auf den Kalender des Benutzers zugreifen soll, aktivieren Sie das Kontrollkästchen Calendars.Read , und klicken Sie auf OK.

    Screenshot: Kontrollkästchen Calendars.Read

  8. Scrollen Sie nach unten, und klicken Sie auf die Schaltfläche Speichern .

    Screenshot, der zeigt, wo Sie Speichern auswählen.

  9. Ihre Speicherung wird bestätigt, und Sie können sich im Anwendungsregistrierungsportal abmelden.

Kapitel 2: Einrichten des Unity-Projekts

Das Folgende ist eine typische Einrichtung für die Entwicklung mit Mixed Reality und ist daher eine gute Vorlage für andere Projekte.

  1. Öffnen Sie Unity, und klicken Sie auf Neu.

    Screenshot: Unity-Schnittstelle

  2. Sie müssen einen Unity-Projektnamen angeben. Fügen Sie MSGraphMR ein. Stellen Sie sicher, dass die Projektvorlage auf 3D festgelegt ist. Legen Sie den Speicherort auf einen für Sie geeigneten Ort fest (denken Sie daran, dass näher an Stammverzeichnissen besser ist). Klicken Sie dann auf Projekt erstellen.

    Screenshot: Auswahl von

  3. Wenn Unity geöffnet ist, lohnt es sich, zu überprüfen, ob der Standardskript-Editor auf Visual Studio festgelegt ist. Navigieren Sie zu Einstellungen bearbeiten>, und navigieren Sie dann im neuen Fenster zu Externe Tools. Ändern Sie den externen Skript-Editor in Visual Studio 2017. Schließen Sie das Fenster Einstellungen.

    Screenshot: Festlegen des externen Skript-Editors auf Visual Studio 2017

  4. Wechseln Sie zuDateierstellungseinstellungen>, wählen Sie Universelle Windows-Plattform aus, und klicken Sie dann auf die Schaltfläche Plattform wechseln, um Ihre Auswahl anzuwenden.

    Screenshot: Auswahl der Option Plattform wechseln

  5. Stellen Sie in denDateibuildeinstellungen> Folgendes sicher:

    1. Zielgerät ist auf HoloLens festgelegt

    2. Buildtyp ist auf D3D festgelegt

    3. SDK ist auf Zuletzt installiert festgelegt.

    4. Visual Studio-Version ist auf Latest installed (Neueste Installation) festgelegt.

    5. Build and Run ist auf Lokaler Computer festgelegt.

    6. Speichern Sie die Szene, und fügen Sie sie dem Build hinzu.

      1. Wählen Sie dazu Offene Szenen hinzufügen aus. Ein Speicherfenster wird angezeigt.

        Screenshot, der zeigt, wo Geöffnete Szenen hinzufügen ausgewählt werden soll.

      2. Erstellen Sie einen neuen Ordner für diese und jede zukünftige Szene. Wählen Sie die Schaltfläche Neuer Ordner aus, um einen neuen Ordner zu erstellen, nennen Sie ihn Szenen.

        Screenshot: Name des neuen Ordners

      3. Öffnen Sie den neu erstellten Ordner Scenes , und geben Sie dann im Textfeld Dateiname: MR_ComputerVisionScene ein, und klicken Sie dann auf Speichern.

        Screenshot, der zeigt, wo der Dateiname eingegeben werden soll.

        Wichtig

        Beachten Sie, dass Sie Ihre Unity-Szenen im Ordner Assets speichern müssen, da sie dem Unity-Projekt zugeordnet sein müssen. Das Erstellen des Ordners szenen (und anderer ähnlicher Ordner) ist eine typische Methode zum Strukturieren eines Unity-Projekts.

    7. Die restlichen Einstellungen in Buildeinstellungen sollten vorerst als Standard beibehalten werden.

  6. Klicken Sie im Fenster Buildeinstellungen auf die Schaltfläche Playereinstellungen . Dadurch wird der zugehörige Bereich in dem Bereich geöffnet, in dem sich der Inspektor befindet.

    Screenshot: Dialogfeld

  7. In diesem Bereich müssen einige Einstellungen überprüft werden:

    1. Auf der Registerkarte Andere Einstellungen :

      1. DieSkriptlaufzeitversion sollte experimental (.NET 4.6 Equivalent) lauten, was einen Neustart des Editors auslöst.

      2. Skript-Back-End sollte .NET sein

      3. API-Kompatibilitätsgrad sollte .NET 4.6 sein.

        Screenshot: Überprüfen des API-Kompatibilitätsgrads

    2. Aktivieren Sie auf der Registerkarte Veröffentlichungseinstellungen unter Funktionen Folgendes:

      • InternetClient

        Screenshot, der zeigt, wo die Option InternetClient ausgewählt werden soll.

    3. Aktivieren Sie weiter unten im Bereich unter XR-Einstellungen (unter Veröffentlichungseinstellungen) das Kontrollkästchen Virtual Reality Wird unterstützt, und stellen Sie sicher, dass das Windows Mixed Reality SDK hinzugefügt wurde.

      Screenshot: Hinzufügen Windows Mixed Reality SDK

  8. Zurück in den Buildeinstellungen ist Unity C#-Projekte nicht mehr ausgegraut. aktivieren Sie das Kontrollkästchen neben diesem.

  9. Schließen Sie das Fenster Buildeinstellungen.

  10. Speichern Sie Ihre Szene und Ihr Projekt (FILE>SAVE SCENES / FILE>SAVE PROJECT).

Kapitel 3: Importieren von Bibliotheken in Unity

Wichtig

Wenn Sie die Unity Setup-Komponente dieses Kurses überspringen und direkt mit dem Code fortfahren möchten, können Sie dieses Azure-MR-311.unitypackage herunterladen, es als benutzerdefiniertes Paket in Ihr Projekt importieren und dann in Kapitel 5 fortfahren.

Um Microsoft Graph in Unity zu verwenden, müssen Sie die Microsoft.Identity.Client-DLL verwenden. Es ist möglich, das Microsoft Graph SDK zu verwenden, es ist jedoch das Hinzufügen eines NuGet-Pakets erforderlich, nachdem Sie das Unity-Projekt erstellt haben (d. h. das Bearbeiten des Projekts nach dem Build). Es gilt als einfacher, die erforderlichen DLLs direkt in Unity zu importieren.

Hinweis

Es gibt derzeit ein bekanntes Problem in Unity, das erfordert, dass Plug-Ins nach dem Import neu konfiguriert werden müssen. Diese Schritte (4 bis 7 in diesem Abschnitt) sind nicht mehr erforderlich, nachdem der Fehler behoben wurde.

Um Microsoft Graph in Ihr eigenes Projekt zu importieren, laden Sie die MSGraph_LabPlugins.zip-Datei herunter. Dieses Paket wurde mit Versionen der getesteten Bibliotheken erstellt.

Wenn Sie mehr darüber erfahren möchten, wie Sie Ihrem Unity-Projekt benutzerdefinierte DLLs hinzufügen, folgen Sie diesem Link.

So importieren Sie das Paket:

  1. Fügen Sie das Unity-Paket zu Unity hinzu, indem Sie die Menüoption Assets>Import Package>Custom Package (Benutzerdefiniertes Paket importieren) verwenden. Wählen Sie das Paket aus, das Sie gerade heruntergeladen haben.

  2. Vergewissern Sie sich im eingeblendeten Feld Unity-Paket importieren , dass alles unter (und einschließlich) Plug-Ins ausgewählt ist.

    Screenshot, der die ausgewählten Konfigurationsparameter unter Plug-Ins zeigt.

  3. Klicken Sie auf die Schaltfläche Importieren , um die Elemente zu Ihrem Projekt hinzuzufügen.

  4. Navigieren Sie im Projektbereich unter Plugins zum Ordner MSGraph, und wählen Sie das Plug-In Microsoft.Identity.Client aus.

    Screenshot: Microsoft.Identity.Client-Plug-In

  5. Stellen Sie bei auswahl des Plug-Ins sicher, dass Beliebige Plattform deaktiviert ist. Stellen Sie dann sicher, dass WSAPlayer ebenfalls deaktiviert ist, und klicken Sie dann auf Übernehmen. Dies dient lediglich dazu, zu bestätigen, dass die Dateien ordnungsgemäß konfiguriert sind.

    Screenshot, der zeigt, wo bestätigt wird, dass

    Hinweis

    Wenn Sie diese Plug-Ins markieren, werden sie so konfiguriert, dass sie nur im Unity-Editor verwendet werden. Es gibt einen anderen Satz von DLLs im WSA-Ordner, die verwendet werden, nachdem das Projekt aus Unity als universelle Windows-Anwendung exportiert wurde.

  6. Als Nächstes müssen Sie den WSA-Ordner im Ordner MSGraph öffnen. Es wird eine Kopie derselben Datei angezeigt, die Sie gerade konfiguriert haben. Wählen Sie die Datei aus, und wählen Sie dann im Inspektor Folgendes aus:

    • Stellen Sie sicher, dass Any Platformdeaktiviert ist, und dass nurWSAPlayeraktiviert ist.

    • Stellen Sie sicher, dass das SDK auf UWP und skriptendes Back-End auf Dot Net festgelegt ist.

    • Stellen Sie sicher, dass Nicht verarbeitenaktiviert ist.

      Screenshot, der zeigt, dass

  7. Klicken Sie auf Anwenden.

Kapitel 4 : Kameraeinrichtung

Während dieses Kapitels richten Sie die Hauptkamera Ihrer Szene ein:

  1. Wählen Sie im Hierarchiebereich die Hauptkamera aus.

  2. Nach auswahl können Sie alle Komponenten der Hauptkamera im Inspektorbereich sehen.

    1. Das Camera-Objekt muss den Namen Hauptkamera haben (beachten Sie die Schreibweise!)

    2. Das Hauptkameratag muss auf MainCamera festgelegt sein (beachten Sie die Schreibweise!)

    3. Stellen Sie sicher, dass die Transformationsposition auf 0, 0, 0 festgelegt ist.

    4. Festlegen von Clear Flags auf Volltonfarbe

    5. Legen Sie die Hintergrundfarbe der Kamerakomponente auf Schwarz, Alpha 0(Hexadezimalcode: #00000000) fest.

      Screenshot, in dem hervorgehoben wird, wo die Hintergrundfarbe festgelegt werden soll.

  3. Die endgültige Objektstruktur im Hierarchiebereich sollte wie in der folgenden Abbildung dargestellt sein:

    Screenshot, der die endgültige Objektstruktur im Hierarchiebereich zeigt.

Kapitel 5: Erstellen der BesprechungsUI-Klasse

Das erste Skript, das Sie erstellen müssen, ist MeetingsUI, das für das Hosten und Auffüllen der Benutzeroberfläche der Anwendung zuständig ist (Willkommensnachricht, Anweisungen und Besprechungsdetails).

So erstellen Sie diese Klasse:

  1. Klicken Sie im Projektbereich mit der rechten Maustaste auf den Ordner Assets, und wählen Sie dann Ordner erstellen> aus. Nennen Sie den Ordner Skripts.

    Screenshot: Speicherort des Ordners Screenshot: Erstellen des Ordners

  2. Öffnen Sie den Ordner Skripts, und klicken Sie dann in diesem Ordner mit der rechten Maustaste aufC#-Skript erstellen>. Nennen Sie das Skript MeetingsUI.

    Screenshot: Erstellen des Ordners

  3. Doppelklicken Sie auf das neue MeetingUI-Skript , um es mit Visual Studio zu öffnen.

  4. Fügen Sie die folgenden Namespaces ein:

    using System;
    using UnityEngine;
    
  5. Fügen Sie in der -Klasse die folgenden Variablen ein:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static MeetingsUI Instance;
    
        /// <summary>
        /// The 3D text of the scene
        /// </summary>
        private TextMesh _meetingDisplayTextMesh;
    
  6. Ersetzen Sie dann die Start() -Methode, und fügen Sie eine Awake() -Methode hinzu. Diese werden aufgerufen, wenn die -Klasse initialisiert:

        /// <summary>
        /// Called on initialization
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        void Start ()
        {
            // Creating the text mesh within the scene
            _meetingDisplayTextMesh = CreateMeetingsDisplay();
        }
    
  7. Fügen Sie die Methoden hinzu, die für die Erstellung der Besprechungsbenutzeroberfläche verantwortlich sind, und füllen Sie sie bei Bedarf mit den aktuellen Besprechungen auf:

        /// <summary>
        /// Set the welcome message for the user
        /// </summary>
        internal void WelcomeUser(string userName)
        {
            if(!string.IsNullOrEmpty(userName))
            {
                _meetingDisplayTextMesh.text = $"Welcome {userName}";
            }
            else 
            {
                _meetingDisplayTextMesh.text = "Welcome";
            }
        }
    
        /// <summary>
        /// Set up the parameters for the UI text
        /// </summary>
        /// <returns>Returns the 3D text in the scene</returns>
        private TextMesh CreateMeetingsDisplay()
        {
            GameObject display = new GameObject();
            display.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f);
            display.transform.position = new Vector3(-3.5f, 2f, 9f);
            TextMesh textMesh = display.AddComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleLeft;
            textMesh.alignment = TextAlignment.Left;
            textMesh.fontSize = 80;
            textMesh.text = "Welcome! \nPlease gaze at the button" +
                "\nand use the Tap Gesture to display your meetings";
    
            return textMesh;
        }
    
        /// <summary>
        /// Adds a new Meeting in the UI by chaining the existing UI text
        /// </summary>
        internal void AddMeeting(string subject, DateTime dateTime, string location)
        {
            string newText = $"\n{_meetingDisplayTextMesh.text}\n\n Meeting,\nSubject: {subject},\nToday at {dateTime},\nLocation: {location}";
    
            _meetingDisplayTextMesh.text = newText;
        }
    
  8. Löschen Sie die Update() -Methode, und speichern Sie Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

Kapitel 6: Erstellen der Graph-Klasse

Das nächste zu erstellende Skript ist das Graph-Skript . Dieses Skript ist für die Aufrufe zur Authentifizierung des Benutzers und zum Abrufen der geplanten Besprechungen für den aktuellen Tag aus dem Kalender des Benutzers verantwortlich.

So erstellen Sie diese Klasse:

  1. Doppelklicken Sie auf den Ordner Skripts , um ihn zu öffnen.

  2. Klicken Sie mit der rechten Maustaste in den Ordner Skripts, und klicken Sie aufC#-Skript erstellen>. Nennen Sie das Skript Graph.

  3. Doppelklicken Sie auf das Skript, um es mit Visual Studio zu öffnen.

  4. Fügen Sie die folgenden Namespaces ein:

    using System.Collections.Generic;
    using UnityEngine;
    using Microsoft.Identity.Client;
    using System;
    using System.Threading.Tasks;
    
    #if !UNITY_EDITOR && UNITY_WSA
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Windows.Storage;
    #endif
    

    Wichtig

    Sie werden feststellen, dass Teile des Codes in diesem Skript um Präkompilierungsdirektiven gewickelt sind. Dadurch sollen Probleme mit den Bibliotheken beim Erstellen der Visual Studio-Projektmappe vermieden werden.

  5. Löschen Sie die Start()- und Update() -Methoden, da sie nicht verwendet werden.

  6. Fügen Sie außerhalb der Graph-Klasse die folgenden Objekte ein, die erforderlich sind, um das JSON-Objekt zu deserialisieren, das die täglichen geplanten Besprechungen darstellt:

    /// <summary>
    /// The object hosting the scheduled meetings
    /// </summary>
    [Serializable]
    public class Rootobject
    {
        public List<Value> value;
    }
    
    [Serializable]
    public class Value
    {
        public string subject { get; set; }
        public StartTime start { get; set; }
        public Location location { get; set; }
    }
    
    [Serializable]
    public class StartTime
    {
        public string dateTime;
    
        private DateTime? _startDateTime;
        public DateTime StartDateTime
        {
            get
            {
                if (_startDateTime != null)
                    return _startDateTime.Value;
                DateTime dt;
                DateTime.TryParse(dateTime, out dt);
                _startDateTime = dt;
                return _startDateTime.Value;
            }
        }
    }
    
    [Serializable]
    public class Location
    {
        public string displayName { get; set; }
    }
    
  7. Fügen Sie in der Graph-Klasse die folgenden Variablen hinzu:

        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        private string _appId = "-- Insert your Application Id here --";
    
        /// <summary>
        /// Application scopes, determine Microsoft Graph accessibility level to user account
        /// </summary>
        private IEnumerable<string> _scopes = new List<string>() { "User.Read", "Calendars.Read" };
    
        /// <summary>
        /// Microsoft Graph API, user reference
        /// </summary>
        private PublicClientApplication _client;
    
        /// <summary>
        /// Microsoft Graph API, authentication
        /// </summary>
        private AuthenticationResult _authResult;
    
    

    Hinweis

    Ändern Sie den AppId-Wert in die App-ID , die Sie in Kapitel 1, Schritt 4 notiert haben. Dieser Wert sollte mit dem wert übereinstimmen, der im Anwendungsregistrierungsportal auf der Registrierungsseite Ihrer Anwendung angezeigt wird.

  8. Fügen Sie innerhalb der Graph-Klasse die Methoden SignInAsync() und AquireTokenAsync() hinzu, die den Benutzer zum Einfügen der Anmeldeinformationen auffordern.

        /// <summary>
        /// Begin the Sign In process using Microsoft Graph Library
        /// </summary>
        internal async void SignInAsync()
        {
    #if !UNITY_EDITOR && UNITY_WSA
            // Set up Grap user settings, determine if needs auth
            ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
            string userId = localSettings.Values["UserId"] as string;
            _client = new PublicClientApplication(_appId);
    
            // Attempt authentication
            _authResult = await AcquireTokenAsync(_client, _scopes, userId);
    
            // If authentication is successful, retrieve the meetings
            if (!string.IsNullOrEmpty(_authResult.AccessToken))
            {
                // Once Auth as been completed, find the meetings for the day
                await ListMeetingsAsync(_authResult.AccessToken);
            }
    #endif
        }
    
        /// <summary>
        /// Attempt to retrieve the Access Token by either retrieving
        /// previously stored credentials or by prompting user to Login
        /// </summary>
        private async Task<AuthenticationResult> AcquireTokenAsync(
            IPublicClientApplication app, IEnumerable<string> scopes, string userId)
        {
            IUser user = !string.IsNullOrEmpty(userId) ? app.GetUser(userId) : null;
            string userName = user != null ? user.Name : "null";
    
            // Once the User name is found, display it as a welcome message
            MeetingsUI.Instance.WelcomeUser(userName);
    
            // Attempt to Log In the user with a pre-stored token. Only happens
            // in case the user Logged In with this app on this device previously
            try
            {
                _authResult = await app.AcquireTokenSilentAsync(scopes, user);
            }
            catch (MsalUiRequiredException)
            {
                // Pre-stored token not found, prompt the user to log-in 
                try
                {
                    _authResult = await app.AcquireTokenAsync(scopes);
                }
                catch (MsalException msalex)
                {
                    Debug.Log($"Error Acquiring Token: {msalex.Message}");
                    return _authResult;
                }
            }
    
            MeetingsUI.Instance.WelcomeUser(_authResult.User.Name);
    
    #if !UNITY_EDITOR && UNITY_WSA
            ApplicationData.Current.LocalSettings.Values["UserId"] = 
            _authResult.User.Identifier;
    #endif
            return _authResult;
        }
    
  9. Fügen Sie die folgenden beiden Methoden hinzu:

    1. BuildTodayCalendarEndpoint() erstellt den URI, der den Tag und die Zeitspanne angibt, in der die geplanten Besprechungen abgerufen werden.

    2. ListMeetingsAsync(), das die geplanten Besprechungen von Microsoft Graph anfordert.

        /// <summary>
        /// Build the endpoint to retrieve the meetings for the current day.
        /// </summary>
        /// <returns>Returns the Calendar Endpoint</returns>
        public string BuildTodayCalendarEndpoint()
        {
            DateTime startOfTheDay = DateTime.Today.AddDays(0);
            DateTime endOfTheDay = DateTime.Today.AddDays(1);
            DateTime startOfTheDayUTC = startOfTheDay.ToUniversalTime();
            DateTime endOfTheDayUTC = endOfTheDay.ToUniversalTime();
    
            string todayDate = startOfTheDayUTC.ToString("o");
            string tomorrowDate = endOfTheDayUTC.ToString("o");
            string todayCalendarEndpoint = string.Format(
                "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={0}&enddatetime={1}",
                todayDate,
                tomorrowDate);
    
            return todayCalendarEndpoint;
        }
    
        /// <summary>
        /// Request all the scheduled meetings for the current day.
        /// </summary>
        private async Task ListMeetingsAsync(string accessToken)
        {
    #if !UNITY_EDITOR && UNITY_WSA
            var http = new HttpClient();
    
            http.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await http.GetAsync(BuildTodayCalendarEndpoint());
    
            var jsonResponse = await response.Content.ReadAsStringAsync();
    
            Rootobject rootObject = new Rootobject();
            try
            {
                // Parse the JSON response.
                rootObject = JsonUtility.FromJson<Rootobject>(jsonResponse);
    
                // Sort the meeting list by starting time.
                rootObject.value.Sort((x, y) => DateTime.Compare(x.start.StartDateTime, y.start.StartDateTime));
    
                // Populate the UI with the meetings.
                for (int i = 0; i < rootObject.value.Count; i++)
                {
                    MeetingsUI.Instance.AddMeeting(rootObject.value[i].subject,
                                                rootObject.value[i].start.StartDateTime.ToLocalTime(),
                                                rootObject.value[i].location.displayName);
                }
            }
            catch (Exception ex)
            {
                Debug.Log($"Error = {ex.Message}");
                return;
            }
    #endif
        }
    
  10. Sie haben nun das Graph-Skript abgeschlossen. Speichern Sie Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

Kapitel 7: Erstellen des GazeInput-Skripts

Sie erstellen nun den GazeInput. Diese Klasse verarbeitet und verfolgt den Blick des Benutzers mithilfe eines Raycasts , der von der Hauptkamera stammt und nach vorne projiziert wird.

So erstellen Sie das Skript:

  1. Doppelklicken Sie auf den Ordner Skripts , um ihn zu öffnen.

  2. Klicken Sie mit der rechten Maustaste in den Ordner Skripts, und klicken Sie aufC#-Skript erstellen>. Nennen Sie das Skript GazeInput.

  3. Doppelklicken Sie auf das Skript, um es mit Visual Studio zu öffnen.

  4. Ändern Sie den Namespacecode so, dass er mit dem folgenden übereinstimmt, und fügen Sie das Tag "[System.Serializable]" über Ihrer GazeInput-Klasse hinzu, damit es serialisiert werden kann:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. Fügen Sie in der GazeInput-Klasse die folgenden Variablen hinzu:

        [Tooltip("Used to compare whether an object is to be interacted with.")]
        internal string InteractibleTag = "SignInButton";
    
        /// <summary>
        /// Length of the gaze
        /// </summary>
        internal float GazeMaxDistance = 300;
    
        /// <summary>
        /// Object currently gazed
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        internal GameObject oldFocusedObject { get; private set; }
    
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// Cursor object visible in the scene
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        internal bool Hit { get; private set; }
    
        internal Vector3 Position { get; private set; }
    
        internal Vector3 Normal { get; private set; }
    
        private Vector3 _gazeOrigin;
    
        private Vector3 _gazeDirection;
    
  6. Fügen Sie die CreateCursor()- Methode hinzu, um den HoloLens-Cursor in der Szene zu erstellen, und rufen Sie die Methode aus der Start() -Methode auf:

        /// <summary>
        /// Start method used upon initialisation.
        /// </summary>
        internal virtual void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        internal GameObject CreateCursor()
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            newCursor.SetActive(false);
            // Remove the collider, so it doesn't block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
            newCursor.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);
            Material mat = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<MeshRenderer>().material = mat;
            mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
  7. Die folgenden Methoden ermöglichen das Anvisieren von Raycast und verfolgen die fokussierten Objekte.

    /// <summary>
    /// Called every frame
    /// </summary>
    internal virtual void Update()
    {
        _gazeOrigin = Camera.main.transform.position;
    
        _gazeDirection = Camera.main.transform.forward;
    
        UpdateRaycast();
    }
    /// <summary>
    /// Reset the old focused object, stop the gaze timer, and send data if it
    /// is greater than one.
    /// </summary>
    private void ResetFocusedObject()
    {
        // Ensure the old focused object is not null.
        if (oldFocusedObject != null)
        {
            if (oldFocusedObject.CompareTag(InteractibleTag))
            {
                // Provide the 'Gaze Exited' event.
                oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    
        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            oldFocusedObject = FocusedObject;
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance);
                HitInfo = hitInfo;
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                Position = hitInfo.point;
                Normal = hitInfo.normal;
    
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedObject = null;
    
                // Provide default position for cursor.
                Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance);
    
                // Provide a default normal.
                Normal = _gazeDirection;
            }
    
            // Lerp the cursor to the given position, which helps to stabilize the gaze.
            Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f);
    
            // Check whether the previous focused object is this same. If so, reset the focused object.
            if (FocusedObject != oldFocusedObject)
            {
                ResetFocusedObject();
                if (FocusedObject != null)
                {
                    if (FocusedObject.CompareTag(InteractibleTag))
                    {
                        // Provide the 'Gaze Entered' event.
                        FocusedObject.SendMessage("OnGazeEntered", 
                            SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
        }
    
  8. Speichern Sie Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

Kapitel 8: Erstellen der Interactions-Klasse

Sie müssen nun das Interaktionsskript erstellen, das für Folgendes zuständig ist:

  • Behandlung der Tap-Interaktion und der Kameraanzeige, die es dem Benutzer ermöglicht, mit der "Schaltfläche" in der Szene zu interagieren.

  • Erstellen des Anmeldeobjekts "button" in der Szene, mit dem der Benutzer interagieren soll.

So erstellen Sie das Skript:

  1. Doppelklicken Sie auf den Ordner Skripts , um ihn zu öffnen.

  2. Klicken Sie mit der rechten Maustaste in den Ordner Skripts, und klicken Sie aufC#-Skript erstellen>. Nennen Sie das Skript Interaktionen.

  3. Doppelklicken Sie auf das Skript, um es mit Visual Studio zu öffnen.

  4. Fügen Sie die folgenden Namespaces ein:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Ändern Sie die Vererbung der Interaction-Klasse von MonoBehaviour in GazeInput.

    public class Interactions : MonoBehaviour

    public class Interactions : GazeInput
    
  6. Fügen Sie in der Interaction-Klasse die folgende Variable ein:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Ersetzen Sie die Start-Methode . Beachten Sie, dass es sich um eine Überschreibungsmethode handelt, die die Gaze-Klassenmethode "basis" aufruft. Start() wird aufgerufen, wenn die -Klasse initialisiert wird, die Eingabeerkennung registriert und die Anmeldeschaltfläche in der Szene erstellt wird:

        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        internal override void Start()
        {
            base.Start();
    
            // Register the application to recognize HoloLens user inputs
            _gestureRecognizer = new GestureRecognizer();
            _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap);
            _gestureRecognizer.Tapped += GestureRecognizer_Tapped;
            _gestureRecognizer.StartCapturingGestures();
    
            // Add the Graph script to this object
            gameObject.AddComponent<MeetingsUI>();
            CreateSignInButton();
        }
    
  8. Fügen Sie die CreateSignInButton()- Methode hinzu, die die Anmeldeschaltfläche in der Szene instanziiert und ihre Eigenschaften festlegt:

        /// <summary>
        /// Create the sign in button object in the scene
        /// and sets its properties
        /// </summary>
        void CreateSignInButton()
        {
            GameObject signInButton = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            Material mat = new Material(Shader.Find("Diffuse"));
            signInButton.GetComponent<Renderer>().material = mat;
            mat.color = Color.blue;
    
            signInButton.transform.position = new Vector3(3.5f, 2f, 9f);
            signInButton.tag = "SignInButton";
            signInButton.AddComponent<Graph>();
        }
    
  9. Fügen Sie die GestureRecognizer_Tapped()- Methode hinzu, die für das Tap-Benutzerereignis beantwortet werden soll.

        /// <summary>
        /// Detects the User Tap Input
        /// </summary>
        private void GestureRecognizer_Tapped(TappedEventArgs obj)
        {
            if(base.FocusedObject != null)
            {
                Debug.Log($"TAP on {base.FocusedObject.name}");
                base.FocusedObject.SendMessage("SignInAsync", SendMessageOptions.RequireReceiver);
            }
        }
    
  10. Löschen Sie die Update() -Methode, und speichern Sie dann Ihre Änderungen in Visual Studio, bevor Sie zu Unity zurückkehren.

Kapitel 9: Einrichten der Skriptverweise

In diesem Kapitel müssen Sie das Skript Interaktionen auf der Hauptkamera platzieren. Dieses Skript behandelt dann das Platzieren der anderen Skripts an der stelle, an der sie sich befinden müssen.

  • Ziehen Sie aus dem Ordner Skripts im Projektbereich das Skript Interaktionen auf das Hauptkameraobjekt , wie unten dargestellt.

    Screenshot, der zeigt, wohin das Interaktionsskript gezogen werden soll.

Kapitel 10: Einrichten des Tags

Der Code, der den Blick behandelt, verwendet das Tag SignInButton , um zu identifizieren, mit welchem Objekt der Benutzer interagiert, um sich bei Microsoft Graph anzumelden.

So erstellen Sie das Tag:

  1. Klicken Sie im Unity-Editor im Hierarchiebereich auf die Hauptkamera.

  2. Klicken Sie im Inspektorbereich auf das MainCamera-Tag, um eine Dropdownliste zu öffnen. Klicken Sie auf Tag hinzufügen...

    Screenshot: Hervorhebung des Tags hinzufügen... Option.

  3. Klicken Sie auf die Schaltfläche +.

    Screenshot der Schaltfläche +.

  4. Schreiben Sie den Tagnamen als SignInButton , und klicken Sie auf Speichern.

    Screenshot: Hinzufügen des SignInButton-Tagnamens

Kapitel 11: Erstellen des Unity-Projekts in UWP

Alles, was für den Unity-Abschnitt dieses Projekts benötigt wird, wurde nun abgeschlossen, daher ist es an der Zeit, es aus Unity zu erstellen.

  1. Navigieren Sie zu Buildeinstellungen (Dateibuildeinstellungen>).

    Screenshot: Dialogfeld

  2. Wenn noch nicht geschehen, markieren Sie Unity C#-Projekte.

  3. Klicken Sie auf Erstellen. Unity startet ein Explorer Fenster, in dem Sie einen Ordner erstellen und dann auswählen müssen, in dem die App erstellt werden soll. Erstellen Sie diesen Ordner jetzt, und nennen Sie ihn App. Klicken Sie dann bei ausgewählter App-Ordner auf Ordner auswählen.

  4. Unity beginnt mit dem Erstellen Ihres Projekts im Ordner App .

  5. Sobald Unity den Bau abgeschlossen hat (es kann einige Zeit dauern), öffnet es ein Explorer Fenster an der Position Ihres Builds (überprüfen Sie Ihre Taskleiste, da es möglicherweise nicht immer über Ihren Fenstern angezeigt wird, aber Sie über das Hinzufügen eines neuen Fensters benachrichtigt).

Kapitel 12: Bereitstellen in HoloLens

So stellen Sie auf HoloLens bereit:

  1. Sie benötigen die IP-Adresse Ihrer HoloLens (für Remote Deploy) und um sicherzustellen, dass sich Ihre HoloLens im Entwicklermodus befindet. Gehen Sie dazu wie folgt vor:

    1. Öffnen Sie die Einstellungen, während Sie Ihre HoloLens tragen.

    2. Wechseln Sie zu Netzwerk & Internet>Wi-Fi>Erweiterte Optionen

    3. Notieren Sie sich die IPv4-Adresse .

    4. Navigieren Sie als Nächstes zurück zu Einstellungen und dann zu Aktualisieren & Sicherheit>für Entwickler.

    5. Legen Sie den Entwicklermodus ein.

  2. Navigieren Sie zu Ihrem neuen Unity-Build (dem Ordner App ), und öffnen Sie die Projektmappendatei mit Visual Studio.

  3. Wählen Sie in der Projektmappenkonfigurationdebuggen aus.

  4. Wählen Sie auf der Lösungsplattformdie Option x86, Remotecomputer aus. Sie werden aufgefordert, die IP-Adresse eines Remotegeräts einzugeben (in diesem Fall die HoloLens, die Sie sich notiert haben).

    Screenshot, der zeigt, wo x86 und Remotecomputer ausgewählt werden.

  5. Navigieren Sie zum Menü Erstellen , und klicken Sie auf Lösung bereitstellen , um die Anwendung in Ihre HoloLens querzuladen.

  6. Ihre App sollte jetzt in der Liste der installierten Apps auf Ihrer HoloLens angezeigt werden, bereit für den Start!

Ihre Microsoft Graph HoloLens-Anwendung

Herzlichen Glückwunsch, Sie haben eine Mixed Reality-App erstellt, die Microsoft Graph nutzt, um Benutzerkalenderdaten zu lesen und anzuzeigen.

Screenshot, der die fertige Mixed Reality-App zeigt.

Zusatzübungen

Übung 1

Verwenden von Microsoft Graph zum Anzeigen anderer Benutzerinformationen

  • Benutzer-E-Mail/Telefonnummer/Profilbild

Übung 1

Implementieren Sie die Sprachsteuerung, um auf der Microsoft Graph-Benutzeroberfläche zu navigieren.