1

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

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

(代码源)

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 Emulator 时,当我按下按钮时,它会很好地运行代码的第一部分,但在这一行出现异常

StorageFile file = await openPicker.PickSingleFileAsync();

经过广泛的研究和一些挫折后,我在这里发表了一篇非常糟糕和模糊的帖子。

在那篇文章中,我引用了 2 年前发表的这篇文章,并说你不能这样做,但Hololens 的 Microsoft 文档说你可以使用文件选择器,在这种情况下是 FileOpenPicker。

我在 Windows Mixed Reality 开发人员论坛中发现了这篇文章,虽然这不是我遇到的问题,但我仍然觉得有必要将其包含在这篇文章中。

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

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

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

4

1 回答 1

1

感谢这篇文章!我终于找到了解决我的问题的方法。在我浏览的任何文档中都没有提到的最大的电话是这个UnityEngine.WSA.Application.InvokeOnUIThread()

我没有遇到这个问题,也没有找到任何文档说明这是 MRTK+unity for hololens 开发的解决方案。因此,对于在那里寻找问题解决方案的任何人,我将引用上面的链接,以防它在未来被破坏。

#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 应用程序在 hololens 上运行的方式,您的应用程序在它自己的小环境中运行,并在您的应用程序中使用 MRTK 特定的统一引擎处理函数调用。然后,该应用程序在 hololens 的更大应用程序(操作系统)中运行。因此,每当您调用 UWP 特定函数时,只有 hololens 才能理解的内容,您需要在 InvokeOnUIThread 中调用这些函数。现在,当您在该函数调用中运行时,如果您需要对 MRTK、unity 或您自己创建的函数进行任何函数调用,则需要使用 InvokeOnAppThread。这实质上是告诉应用程序您想要进行一些 UWP 函数调用,然后在任何时候如果您需要从 UWP 函数调用传回任何信息,同时仍在 InvokeOnUIThread 调用中,

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

于 2021-02-19T17:43:23.400 回答