一些 WinRT 功能在 Xbox 上失败,但在 Windows 10 上没有

Posted

技术标签:

【中文标题】一些 WinRT 功能在 Xbox 上失败,但在 Windows 10 上没有【英文标题】:Several WinRT functions fail on Xbox, but not on Windows 10 【发布时间】:2021-11-01 06:45:30 【问题描述】:

我正在开发用于 Xbox 的托管应用程序的已安装部分的升级版本。我们将不再使用旧的 jsproj 类型,而是实施一个使用 XAML 的新项目。这是一个简单的结构,其中一个页面包含一个 Webview,它将显示应用程序托管部分的内容。

无论如何,当我在这个新应用程序中测试托管部分时,我注意到 WinRT 有一些奇怪的地方。我们有很多使用 WinRT 的 javascript,但其中一些没有按预期运行。我发现至少有两个函数因以下错误而失败。

错误 1 ​​(JavaScript):

  try 
    const applicationView = Windows.UI.ViewManagement.ApplicationView.getForCurrentView();
    applicationView.setDesiredBoundsMode(
      Windows.UI.ViewManagement.ApplicationViewBoundsMode.useCoreWindow,
    );
   catch (e) 
    console.log(e); // Element not found
  

错误 2 (JavaScript):

try 
  this.control = Windows.Media.SystemMediaTransportControls.getForCurrentView();
  this.control.isEnabled = true;
  this.control.isFastForwardEnabled = true;
  this.control.isNextEnabled = true;
  this.control.isPauseEnabled = true;
  this.control.isPlayEnabled = true;
  this.control.isPreviousEnabled = true;
  this.control.isRecordEnabled = true;
  this.control.isRewindEnabled = true;
  this.control.isStopEnabled = true;
  this.control.isChannelUpEnabled = true;
  this.control.isChannelDownEnabled = true;
  this.control.playbackStatus = MediaPlaybackStatus.playing;
  this.control.onbuttonpressed = this.onButtonPressed;
 catch (e) 
  console.log(e);
  /*
    Invalid window handle. Could not find an appropriate view to be associated 
    with this instance of the MediaPlaybackControl. Please make sure that a view
    has been initialized.
  */

这些相同的方法在 C# 中也可以工作:

using Windows.UI.ViewManagement;
using Windows.Media;
...
    public MainPage()
    
        this.InitializeComponent();
        ApplicationView.GetForCurrentView()
            .SetDesiredBoundsMode(
                ApplicationViewBoundsMode.UseCoreWindow
            );
        this.control = SystemMediaTransportControls
            .GetForCurrentView();
    
    // code is happy

这是我正在使用的目标版本和最低版本:

Target version: Windows 10, version 2004 (10.0; build 19041)
Minimum version: Windows 10, version 1809 (10.0; build 17763)

我也尝试将目标版本降级为:

Target version: Windows 10, version 1903 (10.0; build 18362)
Minimum version: Windows 10, version 1809 (10.0; build 17763)

非常奇怪的是,当我在 Windows 10 上运行具有相同托管内容的同一个应用程序时,不会发生这些错误。不过,当我在 Xbox One 或 Xbox Series S|X 上启动应用程序时确实会发生这些错误.我猜 Windows 10 使用的运行时版本与 Xbox 上使用的不同,但降级目标版本也无济于事。

是什么导致了这些错误,有没有办法修复它们?

注意:我们可以不用调用来获取应用程序视图,但我们需要客户端处理来自SystemMediaTransportControls 的按钮按下的监听。这里的目标是首先启动应用程序的已安装部分,并在稍后的工作阶段更新托管部分的 JavaScript,但似乎该项目的旧版本和该项目的旧版本之间没有明确的 1:1关于 WinRt 如何工作的新内容。

【问题讨论】:

从哪里调用 SystemMediaTransportControls.getForCurrentView()?它需要在 UI 线程中完成。我在派生自 Page 的类的构造函数中进行调用。 这发生在应用程序的托管部分(在 JavaScript 中)。但据我所知,当从 webview 中的浏览器调用时,没有办法在 UI 线程上显式运行它? 您能否分享更多您在上述方法中调用的代码,它是否在 JavaScript 中调用? @NicoZhu-MSFT 是的。它在 JavaScript 内部被调用。这里的部分神秘之处在于,它在 C# 中有效,但在 JavaScript 中无效,但仅在 Xbox One、Series X 或 Series S 上运行时才有效。当在 Windows 10 上运行时,这些方法在 C# 和 JavaScript 中有效。 顺便说一句,我更新了问题以显示实际代码。 【参考方案1】:

根据Microsoft documentation,默认情况下,WebView 内容托管在桌面设备系列中的 UI 线程上,而在所有其他设备(Xbox One、Series X 或 Series S,...)上不在 UI 线程上.因此,当不需要默认值时,我们可以使用我们需要的 WebViewExecutionMode 值在 XAML 之外创建一个 WebView 实例。例如:

 var webView = new WebView(WebViewExecutionMode.SameThread);            
        webView.Source = new Uri("https://...");    
        WebViewParent.Child = webView; //assuming WebViewParent is present in XAML

根据我的测试,当我使用 WebViewExecutionMode.SeparateThread 创建 WebView 实例时确实发生了错误,但在我使用 WebViewExecutionMode.SameThread 或 WebViewExecutionMode.SeparateProcess 时没有发生。

【讨论】:

果然,这确实有效。但是,我发现更改线程模型会破坏我编写的必须从 UI 线程(C# 端)调用的其他代码。无论如何,我将此标记为答案,因为它确实解决了问题,即使它给我带来了其他麻烦。

以上是关于一些 WinRT 功能在 Xbox 上失败,但在 Windows 10 上没有的主要内容,如果未能解决你的问题,请参考以下文章

xbox无线手柄怎么连接电脑

使用 Win32 和 UWP/Xbox 平台支持管理 C++ 应用程序的最佳实践?

XBOX 在插槽 0 中检测到一个游戏手柄,但在 Game Maker Studio 2 中未检测到输入

XAML 页面不是在 Windows 10 Mobile 上的 WinRT 应用程序中收集的垃圾,但在 WP8.1 上按预期工作

在 WinRT 中绘制二叉树

在 C++ 中按下 Xbox 按钮