System.Exception 在 Hololens 上评估 OpenFilePicker 时被调用

System.Exception getting called when assessing OpenFilePicker on Hololens

我正在将 MRTK 用于 hololens 应用程序,我需要 select 用户放入其文档文件夹中的文件。我正在尝试访问 FileOpenPicker 并通过按下按钮使用 PickSingleFileAsync() 函数来获取文件,然后将其加载到我的应用程序中。

这个函数里面的代码基本上就是我在做的:

(Code Source)

private async void PickAFileButton_Click(object sender, RoutedEventArgs e)
        {
            // Clear previous returned file name, if it exists, between iterations of this scenario
            OutputTextBlock.Text = "";

            FileOpenPicker openPicker = new FileOpenPicker();
            openPicker.ViewMode = PickerViewMode.Thumbnail;
            openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
            openPicker.FileTypeFilter.Add(".jpg");
            openPicker.FileTypeFilter.Add(".jpeg");
            openPicker.FileTypeFilter.Add(".png");
            StorageFile file = await openPicker.PickSingleFileAsync();
            if (file != null)
            {
                // Application now has read/write access to the picked file
                OutputTextBlock.Text = "Picked photo: " + file.Name;
            }
            else
            {
                OutputTextBlock.Text = "Operation cancelled.";
            }
        }

但是,当我构建并部署到 Hololens 模拟器时,当我按下按钮时,它运行代码的第一部分很好,但我在这一行遇到异常

StorageFile file = await openPicker.PickSingleFileAsync();

经过广泛的研究和一些挫折后,我对它做了一个非常糟糕和模糊的 post

在那 post 我引用了这个 which was made 2 years ago and says you can't do this but The Microsoft docs for Hololens 说你可以使用文件选择器,在这种情况下,FileOpenPicker。

我发现 this post 埋藏在 Windows 混合现实开发者论坛中相关但不是我遇到的问题,我仍然觉得有必要包括在这个post.

我还想补充一点,我确实安装了一个文件选择器应用程序。根据 this post on Microsoft Docs,如果您调用 FileOpenPicker,它将打开您设备上首次安装的任何文件选择器。

同样在正在生成的 MRTK 和 Appx 中,我确保启用了“PictureLibrary”功能的权限。

任何帮助将不胜感激,我觉得我已经等了太久才就这个话题做出更正式的 post,我希望能得到一些答案。谢谢!

ALL THANKS TO THIS POST! 我终于找到了解决问题的方法。我查看过的任何文档中都没有提到的最大调用是 UnityEngine.WSA.Application.InvokeOnUIThread()

我没有 运行 参与其中,也没有找到任何文档说明这是 MRTK+unity for hololens 开发的解决方案。因此,对于正在寻找问题解决方案的任何人,我将在上面引用 link 以防将来出现问题。

#if !UNITY_EDITOR && UNITY_WSA_10_0
        Debug.Log("***********************************");
        Debug.Log("File Picker start.");
        Debug.Log("***********************************");

        UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
        {
            var filepicker = new FileOpenPicker();
            // filepicker.FileTypeFilter.Add("*");
            filepicker.FileTypeFilter.Add(".txt");

            var file = await filepicker.PickSingleFileAsync();
            UnityEngine.WSA.Application.InvokeOnAppThread(() => 
            {
                Debug.Log("***********************************");
                string name = (file != null) ? file.Name : "No data";
                Debug.Log("Name: " + name);
                Debug.Log("***********************************");
                string path = (file != null) ? file.Path : "No data";
                Debug.Log("Path: " + path);
                Debug.Log("***********************************");

                

                //This section of code reads through the file (and is covered in the link)
                // but if you want to make your own parcing function you can 
                // ReadTextFile(path);
                //StartCoroutine(ReadTextFileCoroutine(path));

            }, false);
        }, false);

        
        Debug.Log("***********************************");
        Debug.Log("File Picker end.");
        Debug.Log("***********************************");
#endif

编辑:

关于“InvokeOnUIThread”和“InvokeOnAppThread”的含义的一些解释。

想想你的 MRTK 应用程序 运行 在全息镜头上的方式,你的应用程序 运行 在它自己的小环境中使用 MRTK 特定的统一引擎处理你的应用程序中的函数调用。然后,该应用程序 运行 在全息镜头的更大应用程序 (OS) 中运行。因此,每当您调用 UWP 特定函数时,只有全息镜头才能理解的事情,您需要在 InvokeOnUIThread 中调用这些函数。现在,当您 运行 进入该函数调用时,如果您需要将任何函数回调回 MRTK、unity 或您自己创建的函数,则需要使用 InvokeOnAppThread。这实质上告诉应用程序您想要进行一些 UWP 函数调用,然后在任何时候如果您需要从 UWP 函数调用传回任何信息,同时仍在 InvokeOnUIThread 调用中,您需要使用 InvokeOnAppThread。

根据我的发现,这基本上就是整个事情的运作方式,我认为这对记录很重要。