【问题标题】:Porting Chrome app to UWP: How to handle "background page"?将 Chrome 应用程序移植到 UWP:如何处理“背景页面”?
【发布时间】:2019-01-19 22:14:10
【问题描述】:

我有一个 Chrome 应用程序(本质上是一个 Chrome 扩展程序,具有一些额外的 API 访问权限并在单独的窗口中显示其 UI),我正在尝试移植到 UWP。我有 Chrome 应用程序的源代码,但该应用程序的很多工作都是在其后台页面中完成的。 UWP JS 应用似乎没有后台页面的概念,或与 Chrome 扩展/应用 API 等效的用于与后台页面交互的概念。

在 UWP JS 应用程序中是否有某种方法可以创建与应用程序一样运行、在应用程序运行之前完全加载、不显示 UI 并且可以从其他页面访问的“背景页面” ?它需要是持久的(即不是每次导航 UI 页面时都重新加载)并且始终可用(即在其他页面加载之前完成加载)。

或者,如果有更好的方法来做到这一点(将 Chrome 应用程序移植到无法运行 Chrome 并且需要运行客户端/不能托管在服务器上的 Windows 设备),请提出替代方法。

【问题讨论】:

  • UWP 应用中没有这样的“背景页面”,Chrome 扩展与 UWP 应用完全不同,为什么要移植到 UWP?
  • @BreezeLiu-MSFT 我想移植它,这样我就可以在无法运行的 Windows 设备上运行该应用程序(它是 Chrome 应用程序,而不是扩展程序,尽管差异不大)运行 Chrome,例如 Xbox、Win10 S、IoT 或 HoloLens 等。鉴于它是用 JS 编写的(甚至没有任何本机代码绑定,尽管它确实调用了一些我需要替换的特定于 Chrome 的 API),我认为最好的方法是将它放在 JS UWP 中。但是,我需要一种方法来处理通常存在于后台页面中并通过后台页面访问的逻辑。
  • 你想在你的uwp项目中只有JS代码吗?也许您可以尝试创建一个 Windows 运行时组件并从 JavaScript 调用它。请参阅主题 Windows Runtime components 创建 c++/c# Windows 运行时组件并从 JS 项目中调用它和主题 Raising Events in Windows Runtime Components
  • @BreezeLiu-MSFT 嗯,这个想法是移植应用程序,而不是用另一种语言编写它的克隆。很多繁重的工作是在后台页面完成的;用 .NET 语言重写它本质上意味着重写除 UI 之外的所有内容,包括自定义网络协议(通过 websockets 实现)和一些加密代码(可能会变得更快,但我相信原始实现)不仅仅是我的重新实现)。

标签: javascript uwp google-chrome-app windows-10-universal porting


【解决方案1】:

我认为您正在寻找的是一个“服务”类,它与应用程序一样存在,并且包含需要从应用程序中的多个位置调用的“共享”代码。 为此,我建议您研究单例模式(顺便说一句,这是一种代码味道)或者更好的是,使用 IoC 容器并将该类注册为“单例”。

这两种方法都允许您拥有一个所述类的实例,只要应用程序正在运行,它就会保持其状态。

【讨论】:

  • 正如我在问题中所说,我正在尝试移植一个 Chrome 应用程序(完全用 JavaScript 编写)。从概念上讲,Chrome 应用程序/扩展程序的背景页面的 UWP 等价物可能是 Application 对象,但对于用 JavaScript 编写的 UWP 似乎不存在!我不确定后台服务是否也是,但即使它们是,它们也不是我真正想要的。
【解决方案2】:

我通过反复试验找到了一个最有效的解决方案:

将应用程序的默认页面(在清单中指定)更改为background.html(或调用任何背景页面)。这确保它首先被加载。然后将chrome.app.runtime.onLaunched.addListener(callback) 实现为window.onload(callback)window.addEventListener('load', callback) 触发器;这将是应用程序的用户交互部分(应用程序显示 UI 等)的入口点。在执行任何窗口管理 (1) 或完全访问后台页面 (2) 的每个页面上,都需要进行两项更关键的代码更改;在实践中,最好将它们放入每个页面都包含的 JS/TS 文件中:

  1. 修改窗口处理代码以在“背景页面”上创建/显示全宽和全高<iframes>。在实践中,这可能意味着修改或“实施”chrome.app.window API,UWP 默认不提供这些 API。 (您也可以将此类 API 用于您自己的帧处理函数的每个地方都更改为您自己的帧处理函数,但这可能需要更多的工作)。我只是使用了原始的 DOM 操作函数; jquery 也可以。在任何给定时间可见的任何 iframe 实际上都会成为活动窗口。如果您的应用不使用 Chrome API 的所有功能,您可能只能部分实现 AppWindow 类型。
  2. 实现chrome.runtime.getBackgroundPage(callback)(或重新编写对它的所有引用),而不是沿着window.parent 层次结构到达后台页面,并在那里安排回调。根据您的应用,您可能还需要实现其他 chrome.runtime API 和/或类型。

总的来说,我的这种方法效果很好。它允许将“背景页面”用作应用程序范围的全局对象,具有任意属性和 API。它确保后台页面首先加载和最后卸载(并且能够捕获内容页面的卸载事件等)。它甚至有一些好处,例如启用伪启动屏幕(在“背景”页面的顶部添加图像或类似的东西,它会在 JS 完成加载和onload 事件之前显示在该页面上 - 模拟chrome.app.runtime.onLaunched 事件 - 触发)。不过,它也有一些弱点:

  • Chrome 应用程序支持一次显示多个窗口。 UWP 应用在桌面上支持这一点,但在其他地方不支持。您可以强制只有一个窗口(在整个窗口 iframe 中加载所有不同的“窗口”),但是如果应用程序希望一次显示两个窗口,则需要处理它们之间的切换。你也可以做一个拆分视图的事情(多个“窗口”iframes 一次可见),但要做到这一点还需要做更多的工作。
  • Chrome 应用程序支持指定窗口尺寸。 UWP 应用在桌面上对此的支持有限,在应用始终全屏运行的平台上则完全不支持。
  • Chrome 应用程序有许多其他 API,例如用于文件系统访问等,您可能需要使用 Windows.* API 替换/重新实现。找到它们并不难,因为调试器会因为你试图调用不存在的函数而对你大喊大叫,但它可能会使移植工作比这里给出的相对较少的代码更改更大。另一方面,以“网络安全”方式(如本地存储、indexedDB 或 cookie)存储所有数据的应用也可以。
  • Chrome 应用程序能够在不显示任何 UI 的情况下继续运行(在后台页面中,这是不可见的),无论是持续监控更新或播放音乐,还是只是将数据保存在内存中。 UWP 可以做到这一点(有限制),但我还没有找到一种方法在 JavaScript 中做到这一点,所以实际上当你关闭 UI 窗口时,应用程序将退出。这也意味着您响应用户关闭“最后一个”用户界面窗口的能力非常有限。

【讨论】:

    猜你喜欢
    • 2018-10-11
    • 2012-07-22
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 2011-05-28
    相关资源
    最近更新 更多