Delen via


HoloLens (1e generatie) en Azure 311 - Microsoft Graph

Notitie

De Mixed Reality Academy-zelfstudies zijn ontworpen met HoloLens (1e generatie) en Mixed Reality Immersive Headsets in gedachten. Daarom vinden we het belangrijk om deze zelfstudies te behouden voor ontwikkelaars die nog steeds op zoek zijn naar richtlijnen bij het ontwikkelen voor die apparaten. Deze zelfstudies worden niet bijgewerkt met de nieuwste toolsets of interacties die worden gebruikt voor HoloLens 2. Ze blijven behouden om door te gaan met het werken op de ondersteunde apparaten. Er is een nieuwe reeks zelfstudies die in de toekomst zullen worden gepost en die laten zien hoe u zich ontwikkelt voor HoloLens 2. Deze kennisgeving wordt bijgewerkt met een koppeling naar deze zelfstudies wanneer ze worden gepost.

In deze cursus leert u hoe u Microsoft Graph gebruikt om u aan te melden bij uw Microsoft-account met behulp van beveiligde verificatie in een mixed reality-toepassing. Vervolgens haalt u de geplande vergaderingen op en geeft u deze weer in de toepassingsinterface.

Schermopname van de geplande vergaderingen in de toepassingsinterface.

Microsoft Graph is een set API's die zijn ontworpen voor toegang tot veel van de services van Microsoft. Microsoft Graph beschrijft Microsoft Graph als een matrix van resources die zijn verbonden door relaties, wat betekent dat een toepassing toegang heeft tot allerlei soorten verbonden gebruikersgegevens. Ga naar de Microsoft Graph-pagina voor meer informatie.

Ontwikkeling omvat het maken van een app waarin de gebruiker wordt geïnstrueerd om naar een bol te kijken en vervolgens op een bol te tikken, waardoor de gebruiker wordt gevraagd zich veilig aan te melden bij een Microsoft-account. Zodra de gebruiker zich heeft aangemeld bij zijn of haar account, ziet hij een lijst met vergaderingen die voor de dag zijn gepland.

Nadat u deze cursus hebt voltooid, hebt u een HoloLens-toepassing voor mixed reality, die het volgende kan doen:

  1. Tik met behulp van het tikbeweging op een object, waarmee de gebruiker wordt gevraagd zich aan te melden bij een Microsoft-account (de app wordt verwijderd om u aan te melden en vervolgens weer in de app).
  2. Bekijk een lijst met vergaderingen die zijn gepland voor de dag.

In uw toepassing is het aan u om te bepalen hoe u de resultaten integreert met uw ontwerp. Deze cursus is ontworpen om u te leren hoe u een Azure Service integreert met uw Unity-project. Het is uw taak om de kennis die u uit deze cursus krijgt te gebruiken om uw mixed reality-toepassing te verbeteren.

Ondersteuning voor apparaten

Cursus HoloLens Insluitende headsets
MR en Azure 311: Microsoft Graph ✔️

Vereisten

Notitie

Deze zelfstudie is ontworpen voor ontwikkelaars die basiservaring hebben met Unity en C#. Houd er ook rekening mee dat de vereisten en schriftelijke instructies in dit document staan voor wat er op het moment van schrijven is getest en geverifieerd (juli 2018). U bent vrij om de nieuwste software te gebruiken, zoals vermeld in het artikel over de installatie van de hulpprogramma's , hoewel wordt ervan uitgegaan dat de informatie in deze cursus perfect overeenkomt met wat u vindt in nieuwere software dan hieronder wordt vermeld.

Voor deze cursus raden we de volgende hardware en software aan:

Voordat u begint

  1. Om problemen met het bouwen van dit project te voorkomen, wordt u sterk aangeraden het project te maken dat in deze zelfstudie wordt genoemd in een hoofdmap of in een near-rootmap (lange mappaden kunnen problemen veroorzaken tijdens de build).
  2. Uw HoloLens instellen en testen. Als u ondersteuning nodig hebt voor het instellen van uw HoloLens, gaat u naar het installatieartikel van HoloLens.
  3. Het is een goed idee om kalibratie en sensorafstemming uit te voeren bij het ontwikkelen van een nieuwe HoloLens-app (soms kan het helpen om deze taken voor elke gebruiker uit te voeren).

Voor hulp bij kalibratie volgt u deze koppeling naar het HoloLens-kalibratieartikel.

Volg deze koppeling naar het artikel HoloLens Sensor Tuning voor hulp bij sensorafstemming.

Hoofdstuk 1: Uw app maken in de portal voor toepassingsregistratie

Om te beginnen moet u uw toepassing maken en registreren in de portal voor toepassingsregistratie.

In dit hoofdstuk vindt u ook de servicesleutel waarmee u microsoft Graph kunt aanroepen om toegang te krijgen tot uw accountinhoud.

  1. Navigeer naar de Microsoft-portal voor toepassingsregistratie en meld u aan met uw Microsoft-account. Zodra u zich hebt aangemeld, wordt u omgeleid naar de portal voor toepassingsregistratie.

  2. Klik in de sectie Mijn toepassingen op de knop Een app toevoegen.

    Schermopname waarin wordt weergegeven waar u een app wilt toevoegen.

    Belangrijk

    De portal voor toepassingsregistratie kan er anders uitzien, afhankelijk van of u eerder met Microsoft Graph hebt gewerkt. In de onderstaande schermafbeeldingen worden deze verschillende versies weergegeven.

  3. Voeg een naam toe voor uw toepassing en klik op Maken.

    Schermopname die laat zien waar u een naam voor uw toepassing kunt toevoegen.

  4. Zodra de toepassing is gemaakt, wordt u omgeleid naar de hoofdpagina van de toepassing. Kopieer de toepassings-id en noteer deze waarde ergens veilig. U gebruikt deze binnenkort in uw code.

    Schermopname die laat zien waar de toepassings-id moet worden weergegeven.

  5. Zorg ervoor dat systeemeigen toepassing wordt weergegeven in de sectie Platforms. Als u niet op Platform toevoegen klikt en systeemeigen toepassing selecteert.

    Schermopname met de sectie Systeemeigen toepassing gemarkeerd.

  6. Schuif omlaag op dezelfde pagina en in de sectie Met de naam Microsoft Graph-machtigingen moet u extra machtigingen voor de toepassing toevoegen. Klik op Toevoegen naast Gedelegeerde machtigingen.

    Schermopname waarin wordt weergegeven waar u Toevoegen naast Gedelegeerde machtigingen kunt selecteren.

  7. Aangezien u wilt dat uw toepassing toegang heeft tot de agenda van de gebruiker, schakelt u het selectievakje Agenda's.Lezen in en klikt u op OK.

    Schermopname van het selectievakje Calendars.Read.

  8. Schuif naar de onderkant en klik op de knop Opslaan .

    Schermopname van waar u Opslaan kunt selecteren.

  9. Uw opslag wordt bevestigd en u kunt zich afmelden bij de portal voor toepassingsregistratie.

Hoofdstuk 2 - Het Unity-project instellen

Hier volgt een typische opzet voor het ontwikkelen met mixed reality en is als zodanig een goede sjabloon voor andere projecten.

  1. Open Unity en klik op Nieuw.

    Schermopname van de Unity-interface.

  2. U moet een Unity-projectnaam opgeven. MSGraphMR invoegen. Zorg ervoor dat de projectsjabloon is ingesteld op 3D. Stel de locatie in op een locatie die geschikt is voor u (vergeet niet, dichter bij hoofdmappen is beter). Klik vervolgens op Project maken.

    Schermopname van waar u Project maken kunt selecteren.

  3. Als Unity is geopend, is het de moeite waard om te controleren of de standaardscripteditor is ingesteld op Visual Studio. Ga naar Voorkeuren bewerken>en navigeer vervolgens vanuit het nieuwe venster naar Externe hulpprogramma's. Wijzig de externe scripteditor in Visual Studio 2017. Sluit het venster Voorkeuren .

    Schermopname die laat zien waar de externe scripteditor moet worden ingesteld op Visual Studio 2017.

  4. Ga naar Instellingen voor bestandsbuild>en selecteer Universeel Windows-platform en klik vervolgens op de knop Platform wisselen om uw selectie toe te passen.

    Schermopname die laat zien waar u Switch Platform kunt selecteren.

  5. Zorg er tijdens het maken van >bestanden voor dat:

    1. Doelapparaat is ingesteld op HoloLens

    2. Buildtype is ingesteld op D3D

    3. SDK is ingesteld op Laatst geïnstalleerd

    4. Visual Studio-versie is ingesteld op Meest recent geïnstalleerd

    5. Bouwen en uitvoeren is ingesteld op lokale computer

    6. Sla de scène op en voeg deze toe aan de build.

      1. Doe dit door Open Scènes toevoegen te selecteren. Er wordt een venster voor opslaan weergegeven.

        Schermopname die laat zien waar u Open scènes toevoegen kunt selecteren.

      2. Maak een nieuwe map voor deze en eventuele toekomstige scènes. Selecteer de knop Nieuwe map om een nieuwe map te maken, geef deze de naam Scènes.

        Schermopname van de naam van de nieuwe map.

      3. Open de zojuist gemaakte map Scènes en klik vervolgens in het tekstvak Bestandsnaam, typ MR_ComputerVisionScene en klik vervolgens op Opslaan.

        Schermopname die laat zien waar de bestandsnaam moet worden getypt.

        Belangrijk

        Houd er rekening mee dat u uw Unity-scènes in de map Assets moet opslaan, omdat deze moeten worden gekoppeld aan het Unity-project. Het maken van de scènemap (en andere vergelijkbare mappen) is een typische manier om een Unity-project te structureren.

    7. De overige instellingen, in Build-instellingen, moeten voorlopig standaard blijven staan.

  6. Klik in het venster Build-instellingen op de knop Spelerinstellingen . Hiermee opent u het gerelateerde deelvenster in de ruimte waar de Inspector zich bevindt.

    Schermopname van het dialoogvenster Spelerinstellingen.

  7. In dit deelvenster moeten enkele instellingen worden geverifieerd:

    1. Op het tabblad Overige instellingen :

      1. Scripting Runtime-versie moet experimenteel (.NET 4.6 Equivalent) zijn, waardoor de editor opnieuw moet worden opgestart.

      2. Back-end voor scripts moet .NET zijn

      3. API-compatibiliteitsniveau moet .NET 4.6 zijn

        Schermopname die laat zien waar het API-compatibiliteitsniveau moet worden gecontroleerd.

    2. Schakel op het tabblad Publicatie-instellingen onder Mogelijkheden het volgende in:

      • InternetClient

        Schermopname van waar u de optie InternetClient kunt selecteren.

    3. Ga verder naar het deelvenster in XR-instellingen (hieronder Publicatie-instellingen), controleer virtual reality ondersteund en controleer of de Windows Mixed Reality SDK is toegevoegd.

      Schermopname die laat zien waar u Windows Mixed Reality SDK kunt toevoegen.

  8. In build-instellingen wordt Unity C# Projects niet meer grijs weergegeven. Schakel het selectievakje ernaast in.

  9. Sluit het venster Build Settings.

  10. Sla uw scène en project op (FILE>SAVE SCENES / FILE>SAVE PROJECT).

Hoofdstuk 3 - Bibliotheken importeren in Unity

Belangrijk

Als u het Unity Set up-onderdeel van deze cursus wilt overslaan en direct in code wilt doorgaan, kunt u dit Azure-MR-311.unitypackage downloaden, het importeren in uw project als een aangepast pakket en vervolgens doorgaan vanaf hoofdstuk 5.

Als u Microsoft Graph in Unity wilt gebruiken, moet u gebruikmaken van het DLL-bestand Microsoft.Identity.Client. Het is echter mogelijk om de Microsoft Graph SDK te gebruiken, maar het vereist de toevoeging van een NuGet-pakket nadat u het Unity-project hebt gebouwd (wat betekent dat u het project na de build bewerkt). Het wordt beschouwd als eenvoudiger om de vereiste DLL's rechtstreeks in Unity te importeren.

Notitie

Er is momenteel een bekend probleem in Unity waarvoor invoegtoepassingen na het importeren opnieuw moeten worden geconfigureerd. Deze stappen (4 - 7 in deze sectie) zijn niet meer vereist nadat de fout is opgelost.

Als u Microsoft Graph in uw eigen project wilt importeren, downloadt u het MSGraph_LabPlugins.zip-bestand. Dit pakket is gemaakt met versies van de bibliotheken die zijn getest.

Als u meer wilt weten over het toevoegen van aangepaste DLL's aan uw Unity-project, volgt u deze koppeling.

Het pakket importeren:

  1. Voeg het Unity-pakket toe aan Unity met behulp van de menuoptie Aangepast pakket> voor assets>importeren. Selecteer het pakket dat u zojuist hebt gedownload.

  2. Controleer in het vak Import Unity Package dat verschijnt of alles onder (en inclusief) invoegtoepassingen is geselecteerd.

    Schermopname van de geselecteerde configuratieparameters onder Plugins.

  3. Klik op de knop Importeren om de items aan uw project toe te voegen.

  4. Ga naar de map MSGraph onder Invoegtoepassingen in het projectvenster en selecteer de invoegtoepassing Microsoft.Identity.Client.

    Schermopname van de invoegtoepassing Microsoft.Identity.Client.

  5. Als de invoegtoepassing is geselecteerd, controleert u of Any Platform is uitgeschakeld en controleert u of WSAPlayer ook is uitgeschakeld en klikt u vervolgens op Toepassen. Dit is alleen om te bevestigen dat de bestanden correct zijn geconfigureerd.

    Schermopname die laat zien waar u kunt bevestigen dat Any Platform en WSAPlayer niet zijn ingeschakeld.

    Notitie

    Als u deze invoegtoepassingen markeert, worden ze alleen gebruikt in de Unity Editor. Er is een andere set DLL's in de WSA-map die wordt gebruikt nadat het project uit Unity is geëxporteerd als een Universele Windows-toepassing.

  6. Vervolgens moet u de WSA-map openen in de map MSGraph . U ziet een kopie van hetzelfde bestand dat u zojuist hebt geconfigureerd. Selecteer het bestand en klik vervolgens in de inspector:

    • zorg ervoor dat Elk platform is uitgeschakeld en dat alleen WSAPlayer is ingeschakeld.

    • Zorg ervoor dat de SDK is ingesteld op UWP en dat de back-end voor scripts is ingesteld op Dot Net

    • Zorg ervoor dat het proces niet is ingeschakeld.

      Schermopname waarin wordt weergegeven dat Niet verwerken is geselecteerd.

  7. Klik op Toepassen.

Hoofdstuk 4 - Camera-instelling

Tijdens dit hoofdstuk stelt u de hoofdcamera van uw scène in:

  1. Selecteer in het deelvenster Hiërarchie de hoofdcamera.

  2. Zodra deze optie is geselecteerd, kunt u alle onderdelen van de hoofdcamera in het deelvenster Inspector zien.

    1. Het cameraobject moet de naam Hoofdcamera hebben (let op de spelling!)

    2. De hoofdcamera-tag moet worden ingesteld op MainCamera (let op de spelling!)

    3. Zorg ervoor dat de positie van de transformatie is ingesteld op 0, 0, 0

    4. Duidelijke vlaggen instellen op effen kleur

    5. Stel de achtergrondkleur van het cameraonderdeel in op Zwart, Alpha 0 (Hex Code: #0000000000)

      Schermopname waarin wordt gemarkeerd waar de achtergrondkleur moet worden ingesteld.

  3. De uiteindelijke objectstructuur in het deelvenster Hiërarchie moet eruitzien als de structuur die wordt weergegeven in de onderstaande afbeelding:

    Schermopname van de uiteindelijke objectstructuur in het deelvenster Hiërarchie.

Hoofdstuk 5 - Klas MeetingsUI maken

Het eerste script dat u moet maken, is MeetingsUI, die verantwoordelijk is voor het hosten en vullen van de gebruikersinterface van de toepassing (welkomstbericht, instructies en de details van de vergaderingen).

Ga als volgt te werk om deze klasse te maken:

  1. Klik met de rechtermuisknop op de map Assets in het deelvenster Project en selecteer Map maken>. Geef de mapscripts een naam.

    Schermopname van waar u de map Assets kunt vinden.Schermopname van waar de map Scripts moet worden gemaakt.

  2. Open de map Scripts en klik in die map met de rechtermuisknop op C#-script maken>. Geef het script MeetingsUI een naam.

    Schermopname van waar de map MeetingsUI moet worden gemaakt.

  3. Dubbelklik op het nieuwe MeetingsUI-script om het te openen met Visual Studio.

  4. Voeg de volgende naamruimten in:

    using System;
    using UnityEngine;
    
  5. Voeg in de klasse de volgende variabelen in:

        /// <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. Vervang vervolgens de Methode Start() en voeg een Awake() -methode toe. Deze worden aangeroepen wanneer de klasse wordt geïnitialiseerd:

        /// <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. Voeg de methoden toe die verantwoordelijk zijn voor het maken van de gebruikersinterface voor vergaderingen en vul deze in met de huidige vergaderingen wanneer dit wordt aangevraagd:

        /// <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. Verwijder de methode Update() en sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 6: de Graph-klasse maken

Het volgende script dat moet worden gemaakt, is het Graph-script . Dit script is verantwoordelijk voor het uitvoeren van de aanroepen om de gebruiker te verifiëren en de geplande vergaderingen voor de huidige dag op te halen uit de agenda van de gebruiker.

Ga als volgt te werk om deze klasse te maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef de scriptgrafiek een naam.

  3. Dubbelklik op het script om het te openen met Visual Studio.

  4. Voeg de volgende naamruimten in:

    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
    

    Belangrijk

    U zult merken dat delen van de code in dit script zijn verpakt rond precompile-instructies. Dit is om problemen met de bibliotheken te voorkomen bij het bouwen van de Visual Studio-oplossing.

  5. Verwijder de methoden Start() en Update(), omdat ze niet worden gebruikt.

  6. Voeg buiten de Graph-klasse de volgende objecten in, die nodig zijn om het JSON-object te deserialiseren voor de dagelijkse geplande vergaderingen:

    /// <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. Voeg in de Graph-klasse de volgende variabelen toe:

        /// <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;
    
    

    Notitie

    Wijzig de appId-waarde in de app-id die u hebt genoteerd in hoofdstuk 1, stap 4. Deze waarde moet hetzelfde zijn als die wordt weergegeven in de portal voor toepassingsregistratie, op de registratiepagina van uw toepassing.

  8. Voeg in de Graph-klasse de methoden SignInAsync() en AquireTokenAsync() toe, waarmee de gebruiker wordt gevraagd de aanmeldingsreferenties in te voegen.

        /// <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. Voeg de volgende twee methoden toe:

    1. BuildTodayCalendarEndpoint(), waarmee de URI wordt gebouwd die de dag en de tijdsduur aangeeft, waarin de geplande vergaderingen worden opgehaald.

    2. ListMeetingsAsync(), die de geplande vergaderingen van Microsoft Graph aanvraagt.

        /// <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. U hebt nu het Graph-script voltooid. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 7: het GazeInput-script maken

U gaat nu de GazeInput maken. Deze klasse verwerkt en houdt de blik van de gebruiker bij met behulp van een Raycast die afkomstig is van de hoofdcamera, die vooruit projecteert.

Het script maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef het script de naam GazeInput.

  3. Dubbelklik op het script om het te openen met Visual Studio.

  4. Wijzig de code van de naamruimten zodat deze overeenkomt met de code hieronder, samen met het toevoegen van de tag [System.Serializable] boven uw GazeInput-klasse , zodat deze kan worden geserialiseerd:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. Voeg in de klasse GazeInput de volgende variabelen toe:

        [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. Voeg de methode CreateCursor() toe om de HoloLens-cursor in de scène te maken en roep de methode aan vanuit de Methode Start( ):

        /// <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. Met de volgende methoden kunt u Raycast bekijken en de gerichte objecten bijhouden.

    /// <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. Sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 8 : de klasse Interacties maken

U moet nu het script Interacties maken. Dit is verantwoordelijk voor:

  • Omgaan met de interactie Tik en de Camera Gaze, waarmee de gebruiker kan communiceren met het aanmelden 'knop' in de scène.

  • Het logboek maken in het object 'button' in de scène waarmee de gebruiker kan communiceren.

Het script maken:

  1. Dubbelklik op de map Scripts om deze te openen.

  2. Klik met de rechtermuisknop in de map Scripts en klik op C#-script maken>. Geef de scriptinteracties een naam.

  3. Dubbelklik op het script om het te openen met Visual Studio.

  4. Voeg de volgende naamruimten in:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Wijzig de overname van de klasse Interaction van MonoBehaviour in GazeInput.

    interacties van openbare klasse : MonoBehaviour

    public class Interactions : GazeInput
    
  6. Voeg in de klasse Interactie de volgende variabele in:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Vervang de Start-methode . U ziet dat het een onderdrukkingsmethode is, die de methode 'base' Gaze class aanroept. Start() wordt aangeroepen wanneer de klasse wordt geïnitialiseerd, wordt geregistreerd voor invoerherkenning en het maken van de aanmeldingsknop in de scène:

        /// <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. Voeg de methode CreateSignInButton() toe, waarmee de aanmeldingsknop in de scène wordt geïnstitueerde en de eigenschappen ervan worden ingesteld:

        /// <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. Voeg de methode GestureRecognizer_Tapped() toe, die moet reageren op de gebeurtenis Tik op de gebruiker.

        /// <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. Verwijder de methode Update() en sla uw wijzigingen op in Visual Studio voordat u terugkeert naar Unity.

Hoofdstuk 9 - Scriptverwijzingen instellen

In dit hoofdstuk moet u het script Interacties op de hoofdcamera plaatsen. Dat script verwerkt vervolgens het plaatsen van de andere scripts waar ze moeten zijn.

  • Sleep vanuit de map Scripts in het projectvenster het scriptInteracties naar het object Hoofdcamera, zoals hieronder wordt weergegeven.

    Schermopname van waar het script Interacties moet worden gesleept.

Hoofdstuk 10 - De tag instellen

De code die de blik verwerkt, maakt gebruik van de Tag SignInButton om te bepalen met welk object de gebruiker zal communiceren om zich aan te melden bij Microsoft Graph.

De tag maken:

  1. Klik in de Unity-editor op de hoofdcamera in het deelvenster Hiërarchie.

  2. Klik in het Inspector-deelvenster op de MainCamera-tag om een vervolgkeuzelijst te openen. Klik op Tag toevoegen...

    Schermopname waarin de tag toevoegen is gemarkeerd... optie.

  3. Klik op de + knop.

    Schermopname van de knop +.

  4. Schrijf de tagnaam als SignInButton en klik op Opslaan.

    Schermopname van waar u de tagnaam SignInButton kunt toevoegen.

Hoofdstuk 11 - Het Unity-project bouwen aan UWP

Alles wat nodig is voor de Unity-sectie van dit project is nu voltooid, dus het is tijd om het te bouwen vanuit Unity.

  1. Navigeer naar Build-instellingen (instellingen voor bestandsbuild>).

    Schermopname van het dialoogvenster Build-instellingen.

  2. Als dat nog niet zo is, tikt u op Unity C#-projecten.

  3. Klik op Opbouwen. Unity start een Bestandenverkenner-venster waarin u een map moet maken en vervolgens een map selecteert waarin u de app wilt inbouwen. Maak die map nu en noem deze app. Klik vervolgens met de map App geselecteerd op Map selecteren.

  4. Unity begint met het bouwen van uw project in de app-map .

  5. Zodra Unity klaar is met bouwen (het kan enige tijd duren), wordt er een Bestandenverkenner venster geopend op de locatie van uw build (controleer de taakbalk, omdat deze mogelijk niet altijd boven uw vensters wordt weergegeven, maar u ontvangt een melding over de toevoeging van een nieuw venster).

Hoofdstuk 12 - Implementeren in HoloLens

Implementeren op HoloLens:

  1. U hebt het IP-adres van uw HoloLens nodig (voor Extern implementeren) en om ervoor te zorgen dat uw HoloLens zich in de ontwikkelaarsmodus bevindt. U doet dit als volgt:

    1. Open de instellingen terwijl u uw HoloLens draagt.

    2. Ga naar Netwerk en Internet>Wi-Fi>Geavanceerde opties

    3. Noteer het IPv4-adres .

    4. Ga vervolgens terug naar Instellingen en ga vervolgens naar Update & Security>for Developers

    5. Stel de ontwikkelaarsmodus in.

  2. Navigeer naar uw nieuwe Unity-build (de app-map ) en open het oplossingsbestand met Visual Studio.

  3. Selecteer foutopsporing in de oplossingsconfiguratie.

  4. Selecteer x86, Remote Machine in het Solution Platform. U wordt gevraagd het IP-adres van een extern apparaat in te voegen (in dit geval de HoloLens, die u hebt genoteerd).

    Schermopname die laat zien waar u x86 en Externe machine selecteert.

  5. Ga naar het menu Bouwen en klik op Oplossing implementeren om de toepassing sideloaden naar uw HoloLens.

  6. Uw app moet nu worden weergegeven in de lijst met geïnstalleerde apps op uw HoloLens, klaar om te worden gestart.

Uw Microsoft Graph HoloLens-toepassing

Gefeliciteerd, u hebt een mixed reality-app gemaakt die gebruikmaakt van Microsoft Graph, om gebruikersagendagegevens te lezen en weer te geven.

Schermopname van de voltooide mixed reality-app.

Bonusoefeningen

Oefening 1

Microsoft Graph gebruiken om andere informatie over de gebruiker weer te geven

  • E-mailadres van gebruiker/telefoonnummer/profielafbeelding

Oefening 1

Implementeer spraakbesturing om door de Microsoft Graph-gebruikersinterface te navigeren.