OS 集成

Web 应用具有广泛的影响力。它们可在多个平台上运行。它们易于通过链接共享。但传统上,它们缺乏与操作系统的集成。不久前,它们甚至无法安装。幸运的是,这种情况已经改变,现在我们可以利用这种集成来为我们的 PWA 添加有用的功能。让我们探索其中的一些选项。

使用文件系统

使用文件的典型用户工作流程如下所示

  • 从设备中选择文件或文件夹并直接打开。
  • 对这些文件或文件夹进行更改,然后将更改直接保存回去。
  • 创建新的文件和文件夹。

File System Access API 之前,Web 应用无法做到这一点。打开文件需要文件上传,保存更改需要用户下载它们,并且 Web 完全无法在用户的文件系统中创建新的文件和文件夹。

打开文件

要打开文件,我们使用 window.showOpenFilePicker() 方法。请注意,此方法需要用户手势,例如按钮点击。以下是打开文件的其余设置

  1. 从文件系统访问的文件选择器 API 中捕获 文件句柄。这为您提供有关文件的基本信息。
  2. 使用句柄的 getFile() 方法,您将获得一种特殊的 Blob,称为 File,其中包含有关文件的其他只读属性(例如名称和上次修改日期)。因为它是一个 Blob,所以可以在其上调用 Blob 方法,例如 text(),以获取其内容。
// Have the user select a file.
const [ handle ] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await handle.getFile();
// Get the file content.
// Also available, slice(), stream(), arrayBuffer()
const content = await file.text();

保存更改

要保存对文件的更改,您也需要用户手势;然后

  1. 使用文件句柄创建 FileSystemWritableFileStream
  2. 对流进行更改。这不会就地更新文件;相反,通常会创建一个临时文件。
  3. 最后,当您完成更改后,您关闭流,这将把更改从临时文件移动到永久文件。

让我们在代码中看看

// Make a writable stream from the handle.
const writable = await handle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();

文件处理

File System Access API 允许您从应用内打开文件,但反过来呢?用户希望将他们喜欢的应用设置为打开文件的默认应用。File Handling API 是一个实验性 API,它允许已安装的 PWA:在用户设备上注册为文件处理程序,在您的 Web 应用清单中指定您的 PWA 支持的 MIME 类型和文件扩展名。您可以为您的支持的扩展名指定自定义文件图标。

注册后,您安装的 PWA 将在用户的文件系统中显示为一个选项,允许他们直接在其中打开文件。以下是 PWA 读取文本文件的清单设置示例

...
"file_handlers": [
     {
         "action": "/open-file",
         "accept": {
             "text/*": [".txt"]
         }
     }
]
...

URL 处理

通过 URL 处理,您的 PWA 可以从操作系统捕获属于其作用域的链接,并在 PWA 窗口中呈现它们,而不是默认浏览器的选项卡。例如,如果您收到指向 PWA 的消息,或者单击 PWA 中的深层链接(指向特定内容片段的 URL),则内容将在独立窗口中打开。

当使用 WebAPK 时,例如当用户使用 Chrome 安装 PWA 时,此行为在 Android 上自动可用。无法在从 Safari 安装在 iOS 和 iPadOS 上的 PWA 上捕获 URL。

对于桌面浏览器,Web 浏览器社区创建了一个新的规范。此规范目前是 实验性的;它添加了一个新的清单文件成员:url_handlers。此属性需要 PWA 想要捕获的来源数组。您的 PWA 的来源将自动获得授权,而每个其他来源都必须通过名为 web-app-origin-association 的文件接受该操作处理。例如,如果您的 PWA 的清单托管在 web.dev 上,并且您想添加 app.web.dev 来源,它将如下所示

"url_handlers": [
    {"origin": "https://app.web.dev"},
]

在这种情况下,浏览器将检查 app.web.dev/.well-known/web-app-origin-association 中是否存在文件,接受来自 PWA 作用域 URL 的 URL 处理。开发人员必须创建此文件。在以下示例中,该文件如下所示

{
    "web_apps": [
        {
            "manifest": "/mypwa/app.webmanifest",
            "details": {
                "paths": [ "/*" ]
            }
        }
    ]
}

URL 协议处理

URL 处理适用于标准 https 协议 URL,但可以使用自定义 URI 方案,例如 pwa://。在某些操作系统中,已安装的应用通过注册其方案来获得此能力。

对于 PWA,此功能通过 URL 协议处理程序 API 启用,该 API 仅在桌面设备上可用。您只能通过在应用商店中分发 PWA 来允许移动设备的自定义协议。

要注册,您可以使用 registerProtocolHandler() 方法,或在您的清单中使用 protocol_handlers 成员,其中包含所需的方案和您想要在 PWA 上下文中加载的 URL,例如

...
{
  "protocol_handlers": [
    {
      "protocol": "web+pwa",
      "url": "/from-protocol?value=%s"
    },
  ]
}
...

您可以将 URL from-protocol 路由到正确的处理程序,并在您的 PWA 中获取查询字符串 value%s 是触发操作的转义 URL 的占位符,因此如果您在某处有一个链接,例如 <a href="web+pwa://testing">,您的 PWA 将打开 /from-protocol?value=testing

调用其他应用

您可以使用 URI 方案连接到用户设备上每个平台上的任何其他已安装应用(PWA 或非 PWA)。您只需要创建一个链接或使用 navigator.href 并指向您想要的 URI 方案,以 URL 转义形式传递参数即可。

您可以使用众所周知的标准方案,例如 tel: 用于电话呼叫,mailto: 用于发送电子邮件,或 sms: 用于短信;或者您可以了解其他应用的 URL 方案,例如来自知名的消息传递、地图、导航、在线会议、社交网络和应用商店。

Web Share

浏览器支持

  • Chrome: 89.
  • Edge: 93.
  • Firefox: behind a flag.
  • Safari: 12.1.

来源

借助 Web Share API,您的 PWA 可以通过共享渠道将内容发送到设备上的其他已安装应用。

该 API 仅在具有 share 机制的操作系统上可用,包括 Android、iOS、iPadOS、Windows 和 ChromeOS。您可以共享包含以下内容的对象

  • 文本(titletext 属性)
  • URL(url 属性)
  • 文件(files 属性)。

要检查当前设备是否可以共享,对于简单数据(如文本),您可以检查是否存在 navigator.share() 方法;要共享文件,您可以检查是否存在 navigator.canShare() 方法。

您可以通过调用 navigator.share(objectToShare) 来请求共享操作。该调用返回一个 Promise,该 Promise 解析为 undefined 或拒绝并抛出异常。

Chrome on Android and Safari on iOS opening the Share Sheet thanks to Web Share.

Web Share Target

Web Share Target API 允许您的 PWA 成为来自该设备上另一个应用的共享操作的目标,无论它是 PWA 还是非 PWA。您的 PWA 接收由另一个应用共享的数据。

它目前在带有 WebAPK 和 ChromeOS 的 Android 上可用,并且仅在用户安装您的 PWA 后才有效。浏览器在安装应用时在操作系统内注册共享目标。

您可以在清单中使用在 Web Share Target 草案规范 中定义的 share_target 成员来设置 Web 共享目标。share_target 设置为具有某些属性的对象

action
将在 PWA 窗口中加载的 URL,该窗口应接收共享数据。
method
将用于操作的 HTTP 谓词方法,例如 GETPOSTPUT
enctype
(可选)参数的编码类型,默认值为 application/x-www-form-urlencoded,但对于 POST 等方法,也可以设置为 multipart/form-data
params
一个对象,它将共享数据(来自键:titletexturlfiles,来自 Web Share)映射到浏览器将在 URL 中(在 method: 'GET' 上)或在使用选定编码的请求正文中传递的参数。

例如,您可以为您的 PWA 定义您想要接收共享数据(仅标题和 URL),方法是在您的清单中添加

...
"share_target": {
   "action": "/receive-share/",
   "method": "GET",
   "params": {
      "title": "shared_title",
      "url": "shared_url"
   }
}
...

从之前的示例中,如果系统中的任何应用正在共享带有标题的 URL,并且用户从对话框中选择了您的 PWA,则浏览器将创建一个新的导航到您的来源的 /receive-share/?shared_title=AAA&shared_url=BBB,其中 AAA 是共享标题,BBB 是共享 URL。您可以使用 JavaScript 通过使用 URL 构造函数 解析 window.location 字符串来读取该数据。

浏览器将使用您清单中的 PWA 名称和图标来填充操作系统的共享条目。您不能为此目的选择不同的集合。

有关更详细的示例以及如何接收文件,请查看 使用 Web Share Target API 接收共享数据

联系人选择器

浏览器支持

  • Chrome:不支持。
  • Edge:不支持。
  • Firefox:不支持。
  • Safari:不支持。

来源

借助 Contact Picker API,您可以请求设备呈现一个原生对话框,其中包含用户的所有联系人,以便用户可以选择一个或多个。然后,您的 PWA 可以从这些联系人处接收您想要的数据。

Contact Picker API 主要在移动设备上可用,并且所有操作都通过兼容平台上的 navigator.contacts 接口完成。

您可以请求使用 navigator.contacts.getProperties() 查询可用的属性,并使用所需属性的列表请求单个或多个联系人选择。

一些示例属性包括 nameemailaddresstel。当您要求用户选择一个或多个联系人时,您可以调用 navigator.contacts.select(properties),并传递您想要在返回中获取的属性数组。

以下示例将列出选择器接收到的联系人。

async function getContacts() {
   const properties = ['name', 'email', 'tel'];
   const options = { multiple: true };
   try {
     const contacts = await navigator.contacts.select(properties, options);
     console.log(contacts);
   } catch (ex) {
     // Handle any errors here.
   }
}

资源