HoloLens (1. generációs) és az Azure 311 – Microsoft Graph

Megjegyzés

Az Mixed Reality Academy oktatóanyagokat HoloLens (1. generációs) és Mixed Reality Modern headsetekkel tervezték. Ezért fontos, hogy ezeket az oktatóanyagokat a helyére helyezzük azoknak a fejlesztőknek, akik továbbra is útmutatásra van szüksége az eszközök fejlesztéséhez. Ezek az oktatóanyagok nem frissülnek a 2. HoloLens használt legújabb eszközkészletekkel vagy interakciókkal. A rendszer fenntartja őket, hogy továbbra is a támogatott eszközökön dolgoznak. A jövőben egy új oktatóanyag-sorozat lesz közzétéve, amely bemutatja, hogyan fejleszthet a 2. HoloLens való fejlesztéshez. Ez az értesítés az oktatóanyagokra mutató hivatkozással fog frissülni, amikor közzé lesznek adva.

Ebben a kurzusban megtudhatja, hogyan jelentkezhet be a Graph microsoftos Microsoft-fiók biztonságos hitelesítéssel egy vegyes valóságon belüli alkalmazásban. Ezután lekéri és megjeleníti az ütemezett értekezleteket az alkalmazás felületén.

A Microsoft Graph OLYAN API-k készlete, amelyek a Microsoft számos szolgáltatásának hozzáférését teszik lehetővé. A Microsoft Graph a Kapcsolatok által összekapcsolt erőforrások mátrixaként ismerteti, ami azt jelenti, hogy lehetővé teszi az alkalmazások számára a csatlakoztatott felhasználói adatokhoz való hozzáférést. További információért látogasson el a Microsoft Graph oldalára.

A fejlesztés magában foglalja egy olyan alkalmazás létrehozását, amelyben a felhasználónak meg kell nézni, majd rá kell koppintaniuk egy sphere-re, amely arra fogja kérni a felhasználót, hogy biztonságosan jelentkezzen be egy Microsoft-fiók. Miután bejelentkezett a fiókjába, a felhasználó láthatja az adott napra ütemezett értekezletek listáját.

A kurzus befejezése után vegyes valósággal fog HoloLens alkalmazással, amely a következőket képes lesz végrehajtani:

  1. A Koppintás kézmozdulattal koppintson egy objektumra, amely felszólítja a felhasználót, hogy jelentkezzen be egy Microsoft-fiókba (lépjen ki az alkalmazásból a bejelentkezéshez, majd vissza az alkalmazásba újra).
  2. A napra ütemezett értekezletek listájának megtekintése.

Az alkalmazásban Ön kell, hogy az eredményeket hogyan integrálja a tervbe. Ennek a kurzusnak az a célja, hogy megtanítsa, hogyan integrálhat egy Azure-szolgáltatást a Unity-projektjéhez. Az Ön feladata, hogy az ebben a kurzusban megszerezhető ismereteket használja fel a vegyes valóságon áteső alkalmazások továbbadása érdekében.

Eszköztámogatás

Tanfolyam HoloLens Modern headsetek
MR és Azure 311: Microsoft Graph ✔️

Előfeltételek

Megjegyzés

Ez az oktatóanyag olyan fejlesztők számára készült, akik alapszintű tapasztalattal rendelkeznek a Unity és a C# használatában. Vegye figyelembe azt is, hogy a jelen dokumentumban található előfeltételek és írásos utasítások az íráskor (2018. július) tesztelt és ellenőrzött adatokat jelölik. Használhatja a legújabb szoftvereket, amelyek az eszközök telepítése cikkben szerepelnek, azonban nem feltételezhető, hogy a kurzusban szereplő információk tökéletesen megegyeznek az újabb szoftverekben található információkkal, mint az alább felsoroltak.

Ehhez a kurzushoz a következő hardvereket és szoftvereket javasoljuk:

Előkészületek

  1. A projekt létrehozásakor felmerülő problémák elkerülése érdekében határozottan javasoljuk, hogy az oktatóanyagban említett projektet egy gyökér- vagy gyökérmappában hozza létre (a hosszú mappaútvonalak problémákat okozhatnak a build létrehozásakor).
  2. Állítsa be és tesztelje a HoloLens. Ha támogatásra van szüksége a HoloLens, mindenképpen látogasson el a HoloLens cikkre.
  3. Egy új alkalmazás fejlesztésekor jó ötlet lehet az új HoloLens-alkalmazás fejlesztésekor (néha segíthet, ha ezeket a feladatokat minden felhasználónál el tudja végezni).

Ha segítségre van szüksége a felhozásról, kövesse ezt a hivatkozást, amely a HoloLens cikkre hivatkozik.

Ha segítségre van szüksége az érzékelő hangolásával, kövesse ezt a hivatkozást a HoloLens Sensor Tuning cikkre.

1. fejezet – Az alkalmazás létrehozása az alkalmazásregisztrációs portálon

Először létre kell hoznia és regisztrálnia kell az alkalmazást az alkalmazásregisztrációs portálon.

Ebben a fejezetben azt a szolgáltatáskulcsot is megtalálja, amely lehetővé teszi, hogy hívásokat kezdeményezsen a Microsoft Graph a fiók tartalmához való hozzáféréshez.

  1. Lépjen a Microsoft alkalmazásregisztrációs portálra, és jelentkezzen be Microsoft-fiókjával. Miután bejelentkezett, a rendszer átirányítja az alkalmazásregisztrációs portálra.

  2. A Saját alkalmazások szakaszban kattintson az Alkalmazás hozzáadása gombra.

    Fontos

    Az alkalmazásregisztrációs portál eltérő lehet attól függően, hogy korábban már dolgozott-e a Microsoft Graph. Az alábbi képernyőképeken ezek a különböző verziók jelennek meg.

  3. Adjon nevet az alkalmazásnak, és kattintson a Létrehozás gombra.

  4. Az alkalmazás létrehozása után a rendszer átirányítja az alkalmazás főoldalára. Másolja ki az alkalmazásazonosítót, és jegyezze fel ezt az értéket egy biztonságos helyen, mert hamarosan használni fogja a kódban.

  5. A Platformok szakaszban ellenőrizze, hogy megjelenik-e a Natív alkalmazás lehetőség. Ha nem, kattintson az Add Platform (Platform hozzáadása) elemre, és válassza a Native Application (Natív alkalmazás) lehetőséget.

  6. Görgessen le ugyanazon az oldalon, és a Microsoft Graph engedélyek című szakaszban további engedélyeket kell hozzáadnia az alkalmazáshoz. Kattintson a Delegált engedélyek melletti Hozzáadás gombra.

  7. Mivel azt szeretné, hogy az alkalmazás hozzáférjen a felhasználó naptárához, jelölje be a Calendars.Read jelölőnégyzetet, és kattintson az OK gombra.

  8. Görgessen le az aljára, és kattintson a Mentés gombra.

  9. A rendszer megerősíti a mentést, és kijelentkezhet az alkalmazásregisztrációs portálról.

2. fejezet – A Unity-projekt beállítása

Az alábbiakban egy tipikus, vegyes valóságban való fejlesztésre vonatkozó beállítás van beállítva, és mint ilyen, jó sablon más projektekhez.

  1. Nyissa meg a Unityt, és kattintson a New (Új) elemre.

  2. Meg kell adnia egy Unity-projekt nevét. Szúrja be az MSGraphMR gombra. Győződjön meg arról, hogy a projektsablon beállítása 3D. A Hely beállításnál adja meg az Önnek megfelelő helyet (ne feledje, hogy a gyökérkönyvtárakhoz közelebb is jobb). Ezután kattintson a Create project (Projekt létrehozása) elemre.

  3. Ha a Unity meg van nyitva, érdemes ellenőrizni, hogy az alapértelmezett Script Editor értéke Visual Studio. Lépjen a Beállításokszerkesztése lapra, majd az új ablakban lépjen a Külső eszközök elemre. Módosítsa a Külső szkriptszerkesztőta 2017 Visual Studio re. Zárja be a Beállítások ablakot.

  4. A Fájl build Gépházválassza a Universal Windows Platform lehetőséget, majd kattintson a Switch Platform (Platformváltás) gombra a választás alkalmazáshoz.

  5. Amíg továbbra is a Fájlbuild Gépház,győződjön meg a következőről:

    1. A Céleszköz beállítása HoloLens

    2. A Build Type (Build típusa) beállítása D3D

    3. Az SDK a Legújabb telepítve beállításra van állítva

    4. Visual Studio Verziója a Legújabb telepítve beállításra van állítva

    5. A Build and Run (Összeállítás és futtatás) beállítása Local Machine (Helyi gép)

    6. Mentse a jelenet, és adja hozzá a buildhez.

      1. Ehhez válassza az Add Open Scenes (Nyitott jelenetek hozzáadása) gombra. Megjelenik egy Mentés ablak.

      2. Hozzon létre egy új mappát ehhez és minden jövőbeli jelenethez. Új mappa létrehozásához kattintson az Új mappa gombra, és adja neki a Scenes nevet.

      3. Nyissa meg az újonnan létrehozott Scenes mappát, majd a Fájlnév:szövegmezőbe írja be a MR_ComputerVisionScene,majd kattintson a Mentés gombra.

        Fontos

        Vegye figyelembe, hogy a Unity-jeleneteket az Assets mappába kell mentenie, mivel a Unity-projekthez kell őket társítanunk. A scenes mappa (és más hasonló mappák) létrehozása egy Unity-projekt strukturálható tipikus módja.

    7. A Build Gépház többibeállítását az alapértelmezett értéken kell hagynunk.

  6. A Build Gépház ablakban kattintson a Player Gépház gombra, ezzel megnyitja a kapcsolódó panelt abban a térben, ahol az Inspector található.

  7. Ezen a panelen ellenőrizni kell néhány beállítást:

    1. Az Egyéb Gépház lapon:

      1. Aparancsfájl-futtatás futásidejű verziójának kísérletinek kell lennie (.NET 4.6-os megfelelő), ami a szerkesztő újraindítását igényli.

      2. A parancsfájl-háttérrendszernek.NET-nek kell lennie

      3. Az API-kompatibilitási szintlegyen .NET 4.6

    2. A Közzétételi lap Gépház képességek alattellenőrizze a következőt:

      • InternetClient

    3. A panelen lejjebb, az XR Gépház (a Publish Gépházalatt) jelölje be a Virtual Reality supported (Virtuális valóságtámogatott) jelölőnégyzetet, és győződjön meg arról, hogy az Windows Mixed Reality SDK hozzá van adva.

  8. A Build Gépház,ahol a Unity C#-projektek már nem szürkülnek ki; jelölje be a mellette látható jelölőnégyzetet.

  9. Zárja be a Build Gépház ablakot.

  10. Mentse a jelenetét és a projektet(FILESAVE SCENES / FILESAVE PROJECT).

3. fejezet – Kódtárak importálása a Unityben

Fontos

Ha ki szeretné hagyni a kurzus Unity Set up összetevőjét, és rögtön a kódba szeretne ugrani, nyugodtan töltse le ezt az Azure-MR-311.unitypackagecsomagot, importálja a projektbe Custom Package-csomagként, majd folytassa az 5.fejezetből.

A Microsoft Graph Unityben való használathoz a Microsoft.Identity.Client DLL-t kell használnia. A Microsoft Graph SDK-t is használhatja, azonban a Unity-projekt létrehozása után (azaz a projekt build utáni szerkesztésével) hozzá kell majd adni egy NuGet-csomagot. A szükséges DLL-ek közvetlenül a Unitybe való importálása egyszerűbbnek tekinthető.

Megjegyzés

Jelenleg van egy ismert probléma a Unityben, amely miatt a beépülő modulokat újra kell konfigurálni az importálás után. Ezek a lépések (a szakasz 4–7. lépései) a hiba megoldása után már nem szükségesek.

A Microsoft-Graph saját projektjéhez való importáláshoz töltse le a MSGraph_LabPlugins.zip fájlt. Ez a csomag a tesztelt kódtárak verzióival lett létrehozva.

Ha szeretne többet tudni arról, hogyan adhat hozzá egyéni DLL-eket Unity-projektjéhez, kövesse ezt a hivatkozást.

A csomag importálása:

  1. Adja hozzá a Unity-csomagot a Unityhez az AssetsImport PackageCustom Package menüelem használatával. Válassza ki az előbb letöltött csomagot.

  2. A felugró Import Unity Package (Import Unity-csomag) mezőben győződjön meg arról, hogy minden elem ki van jelölve a beépülő modulok alatt (és beleértve a beépülő modulokat is).

  3. Kattintson az Importálás gombra az elemek projekthez való hozzáadásához.

  4. A Project Panel Beépülő modulok menüjében válassza az MSGraph mappát, és válassza ki a Microsoft.Identity.Client nevű beépülő modult.

  5. A beépülő modul kiválasztása után győződjön meg arról, hogy a Bármely platform jelölőnégyzet nincs bejelölve, majd győződjön meg arról, hogy a WSAPlayer is be van jelölve, majd kattintson az Apply (Alkalmaz) gombra. Ez csupán annak megerősítésére van állítva, hogy a fájlok megfelelően vannak konfigurálva.

    Megjegyzés

    Ezeknek a beépülő moduloknak a megjelölése úgy konfigurálja őket, hogy csak a Unity-szerkesztőben használják őket. A WSA-mappában különböző DLL-ek találhatók, amelyeket a rendszer a projekt Unityből Universal Windows-alkalmazásként való exportálása után fog használni.

  6. Ezután meg kell nyitnia a WSA mappát az MSGraph mappában. Láthatja ugyanannak a fájlnak a másolatát, amely az előbb konfigurált. Válassza ki a fájlt, majd a vizsgálóban:

    • Győződjön meg arról, hogy a Bármely platform jelölőnégyzet nincs bejelölve,és hogycsak aWSAPlayer van bejelölve.

    • Győződjön meg arról, hogy az SDK az UWP,a Scripting Backend beállítása pedig Dot Net

    • Győződjön meg arról, hogy a Ne legyen folyamatbejelölve.

  7. Kattintson az Alkalmaz gombra.

4. fejezet – Kamera beállítása

Ebben a fejezetben a jelenet fő kameráját fogja beállítani:

  1. A Hierarchia panelen válasszaa Main Camera (Fő kamera) lehetőséget.

  2. A kiválasztás után az Inspector panelen láthatja a Main Camera (Fő kamera) összes összetevőját.

    1. A Kamera objektumnak Main Camera (Main Camera) nevet kell adnunk (jegyezze fel a helyesírást!)

    2. A Main Camera Tag (Fő kameracímke) beállításnak MainCamera -nak kell lennie (jegyezze fel a helyesírást!)

    3. Győződjön meg arról, hogy az Átalakítás pozíciója0, 0, 0

    4. A Clear Flags (Jelzők ürítője) beállításaFolytonos színre

    5. Állítsa a Kamera összetevő háttérszínétFekete, Alfa 0(Hexikus kód: #00000000)

  3. A Hierarchia panel utolsó objektumszerkezetének az alábbi képen láthatóhoz hasonlónak kell lennie:

5. fejezet – ÉrtekezletekUI létrehozása osztály

Az első szkript, amelyet létre kell hoznia, a MeetingsUI,amely az alkalmazás felhasználói felületének (üdvözlőüzenet, utasítások és az értekezletek részletei) futtatásáért és felugrásáért felelős.

Az osztály létrehozása:

  1. Kattintson a jobb gombbal az Assets mappára a Project panelen,majd válassza a Mappalétrehozása lehetőséget. A mappának a Scripts (Szkriptek) nevet kell írnia.

  2. Nyissa meg a Scripts mappát, majd a mappában kattintson a jobb gombbal a Create C# Script (C#-szkript létrehozása) parancsra. Nevezze el a szkriptet MeetingsUI néven.

  3. Kattintson duplán az új MeetingsUI szkriptre a következővel való Visual Studio.

  4. Szúrja be a következő névtereket:

    using System;
    using UnityEngine;
    
  5. A osztályon belül szúrja be a következő változókat:

        /// <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. Ezután cserélje le a Start() metódust, és adjon hozzá egy Egy Új() metódust. Ezeket a osztály inicializálja a következő inicializáláskor:

        /// <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. Adja hozzá az Értekezletek felhasználói felület létrehozásáért felelős metódusokat, és töltse fel az aktuális értekezletekkel, amikor a rendszer kéri:

        /// <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. Törölje az Update() metódust, és mentse a módosításokat a Visual Studio a Unitybe való visszatérés előtt.

6. fejezet – A Graph létrehozása

A következő létrehozni szükséges szkript a Graph szkript. Ez a szkript felelős a felhasználó hitelesítésére és az aktuális napra ütemezett értekezletek a felhasználó naptárból való lekérésére vonatkozó hívásokért.

Az osztály létrehozása:

  1. Kattintson duplán a Scripts mappára a megnyitásához.

  2. Kattintson a jobb gombbal a Scripts (Szkriptek) mappára, majd kattintson a CreateC# Script (C#-szkript létrehozása) parancsra. A szkriptnek a következő nevet Graph:.

  3. Kattintson duplán a szkriptre, és nyissa meg a Visual Studio.

  4. Szúrja be a következő névtereket:

    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
    

    Fontos

    Figyelje meg, hogy a szkript kódjának egyes részei precompile Directives (PrecompileDirektíva) köré vannak csomagolva, így elkerülhetők a kódtárakkal kapcsolatos problémák a megoldás Visual Studio során.

  5. Törölje a Start() ésaz Update() metódust, mert azok nem lesznek használva.

  6. A Graph osztályon kívül szúrja be a következő objektumokat, amelyek a napi ütemezett értekezleteket képviselő JSON-objektum deerializálásához szükségesek:

    /// <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. A Graph adja hozzá a következő változókat:

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

    Megjegyzés

    Módosítsa az appId értékét az 1. fejezet 4. lépésében feljegyzettalkalmazásazonosítóra. Ennek az értéknek ugyanaznak kell lennie, mint az alkalmazásregisztrációs portál alkalmazásregisztrációs oldalán.

  8. A Graph osztályban adja hozzá a SignInAsync() és az AquireTokenAsync()metódusokat, amelyek arra kérik a felhasználót, hogy szúrja be a bejelentkezési hitelesítő adatokat.

        /// <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. Adja hozzá a következő két metódust:

    1. BuildTodayCalendarEndpoint(), amely felépíti az ütemezett értekezletek lekérésének napját és időtartományát megszabadító URI-t.

    2. ListMeetingsAsync(), amely az ütemezett értekezleteket kéri a Microsoft Graph.

        /// <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. Befejezte a Graph szkriptet. Mentse a módosításokat a Visual Studio, mielőtt visszatér a Unitybe.

7. fejezet – A GazeInput szkript létrehozása

Most létre fogja hozni a GazeInput sebességet. Ez az osztály kezeli és nyomon követi a felhasználó tekintetét egy, a Main Camera-tólérkező Raycast használatával, amely előrevetul.

A szkript létrehozása:

  1. Kattintson duplán a Scripts mappára a megnyitásához.

  2. Kattintson a jobb gombbal a Scripts (Szkriptek) mappára, majd kattintson a CreateC# Script (C#-szkript létrehozása) parancsra. A szkriptnek nevezze el a GazeInput nevet.

  3. Kattintson duplán a szkriptre, és nyissa meg a Visual Studio.

  4. Módosítsa úgy a névtérkódot, hogy megfeleljen az alábbinak, és adja hozzá a" [System.Serializable] "címkét a GazeInput osztály fölé, hogy szerializálható legyen:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. A GazeInput osztályban adja hozzá a következő változókat:

        [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. Adja hozzá a CreateCursor() metódust, hogy létrehozza HoloLens kurzort a jelenetben, és hívja meg a metódust a Start() metódusból:

        /// <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. Az alábbi módszerek teszik lehetővé a Raycast tekintetét, és nyomon követik az összpontosított objektumokat.

    /// <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. Mentse a módosításokat a Visual Studio, mielőtt visszatér a Unitybe.

8. fejezet – A Interactions osztály létrehozása

Most létre kell hoznia az Interactions szkriptet, amely a következő műveletekért felelős:

  • A Tap (Koppintás) interakció és a Camera Gaze (Kamera tekintete)kezelése, amely lehetővé teszi, hogy a felhasználó a jelenetben a "button" (gomb) naplót használja.

  • A bejelentkezés "button" objektumának létrehozása a jelenetben, hogy a felhasználó kommunikálhat vele.

A szkript létrehozása:

  1. Kattintson duplán a Scripts mappára a megnyitásához.

  2. Kattintson a jobb gombbal a Scripts (Szkriptek) mappára, majd kattintson a CreateC# Script (C#-szkript létrehozása) parancsra. A szkriptnek a Interactions (Interakciók) nevet kell írnia.

  3. Kattintson duplán a szkriptre, és nyissa meg a Visual Studio.

  4. Szúrja be a következő névtereket:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Módosítsa a Interaction osztály örökléséta MonoBehaviour osztályróla GazeInput osztályra.

    public class Interactions: MonoBehaviour

    public class Interactions : GazeInput
    
  6. Az Interaction osztályba szúrja be a következő változót:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Cserélje le a Start metódust; Figyelje meg, hogy ez egy felülbírálási metódus, amely a "base" Gaze osztály metódusát hívja meg. A Start() akkor lesz meghívva, amikor az osztály inicializál, regisztrál a bemenetfelismerésre, és létrehozza a bejelentkezés gombot a jelenetben:

        /// <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. Adja hozzá a CreateSignInButton() metódust, amely létrehozza a bejelentkezés gombot a jelenetben, és beállítja annak tulajdonságait:

        /// <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. Adja hozzá GestureRecognizer_Tapped() metódust, amely a Tap user eseményre válaszol.

        /// <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. Törölje az Update() metódust, majd mentse a módosításokat a Visual Studio a Unitybe való visszatérés előtt.

9. fejezet – A szkripthivatkozások beállítása

Ebben a fejezetben az Interactions szkriptet a Main Camera (Fő kamera) számára kell eltennünk. Ez a szkript kezeli majd a többi szkript elhelyezését, ahol szükség van rá.

  • Az Project PanelScripts mappájában húzza a Interactions (Interakciók) szkriptet a Main Camera objektumra az alábbi képen látható módon.

10. fejezet – A címke beállítása

A tekintetet kezelő kód a SignInButton címke használatával azonosítja, hogy a felhasználó melyik objektummal fog bejelentkezni a Microsoft Graph.

A címke létrehozása:

  1. A Unity-szerkesztőben kattintson a Fő kamerára a Hierarchia panelen.

  2. Az Inspector panelen kattintson a MainCameraTag elemre egy legördülő lista megnyitásához. Kattintson a Címke hozzáadása... elemre.

  3. Kattintson a + gombra.

  4. Írja be a Címke neve mezőben a SignInButton nevet, majd kattintson a Mentés gombra.

11. fejezet – A Unity-projekt létrehozása az UWP-re

A projekt Unity szakaszának minden szükséges művelete befejeződött, így ideje a Unityből felépíteni.

  1. Lépjen a Build Gépház (FileBuild Gépház).

  2. Ha még nem, jelölje be a Unity C# Projects jelölőnégyzetet.

  3. Kattintson a Build (Build) gombra. A Unity elindít egy Fájlkezelő, amelyben létre kell hoznia, majd ki kell választania egy mappát, amelybe az alkalmazást felépíti. Hozza létre ezt a mappát, és nevezze elApp néven. Ezután jelölje ki az Alkalmazás mappát, és kattintson a Mappa kiválasztása elemre.

  4. A Unity megkezdi a projekt appmappába való építését.

  5. Miután a Unity befejezte az összeállítást (ez némi időt is vegyen el), megnyit egy Fájlkezelő-ablakot a build helyén (ellenőrizze a feladatsávot, mert előfordulhat, hogy nem mindig jelenik meg az ablak felett, de értesítést küld egy új ablakról).

12. fejezet – Üzembe helyezés HoloLens

Üzembe helyezés a következő HoloLens:

  1. A távoli üzembe helyezéshez szüksége lesz a HoloLens IP-címére, és annak biztosításához, hogy a HoloLens fejlesztői módban legyen. Ehhez tegye a következőt:

    1. Bár a saját HoloLens, nyissa meg a Gépház.

    2. Ugrás a Hálózati internet>>>>

    3. Jegyezze fel az IPv4-címet.

    4. Ezután lépjen vissza a Gépház,majd az Update Security for Developers (Biztonsági beállítások frissítésefejlesztőknek) lapra

    5. Állítsa be a Fejlesztői módot.

  2. Lépjen az új Unity-buildhez (az App mappához), és nyissa meg a megoldásfájlt a Visual Studio.

  3. A Megoldáskonfigurációban válassza a Hibakeresés lehetőséget.

  4. A Megoldásplatformonválassza az x86, távoli gép lehetőséget. A rendszer kérni fogja egy távoli eszköz (ebben az esetben a HoloLens IP-címének beszúrása).

  5. A Build (Build) menüben kattintson a Deploy Solution (Megoldás üzembe helyezése) elemre az alkalmazás saját HoloLens.

  6. Az alkalmazásnak meg kell jelenni a telepített alkalmazások listájában a HoloLens, készen áll az indulásra!

A Microsoft Graph HoloLens alkalmazása

Gratulálunk, felépített egy vegyes valóságot használó alkalmazást, amely a Microsoft Graph használatával olvassa be és jeleníti meg a felhasználó Naptár adatait.

Soron kívüli gyakorlatok

1. gyakorlat

A Microsoft Graph a felhasználóval kapcsolatos egyéb információk megjelenítéséhez

  • Felhasználói e-mail-cím/ telefonszám/profilkép

1. gyakorlat

Hangvezérlés implementálása a Microsoft Graph felhasználói felületén.