Web 应用的覆盖面非常广。它们可在多个平台上运行。您可以通过链接轻松分享它们。但传统上,它们缺乏与操作系统的集成。不久前,这些应用甚至无法安装。幸运的是,这种情况已经改变,现在我们可以利用这项集成为 PWA 添加实用功能。我们来探索其中的一些选项。
使用文件系统
使用文件的典型用户工作流程如下所示:
- 从设备中选择一个文件或文件夹,然后直接打开。
- 对这些文件或文件夹进行更改,然后直接将更改保存回来。
- 创建新的文件和文件夹。
在 File System Access API 之前,Web 应用无法执行此操作。打开文件需要上传文件,保存更改需要用户下载,并且 Web 根本无法在用户的文件系统中创建新文件和文件夹。
打开文件
如需打开文件,我们使用 window.showOpenFilePicker()
方法。请注意,此方法需要用户手势,例如按钮点击。以下是打开文件的其余设置:
- 从文件系统访问的文件选择器 API 中捕获文件句柄。您可以从中了解该文件的基本信息。
- 使用句柄的
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();
正在保存更改
如需保存对文件所做的更改,您还需要用户手势;然后:
- 使用文件句柄创建
FileSystemWritableFileStream
。 - 对数据流进行更改。这不会原地更新文件;通常,系统会创建一个临时文件。
- 最后,完成更改后,关闭数据流,这会将更改从临时更改转变为永久更改。
我们在代码中来看看这个过程:
// 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,您可以从应用内打开文件,但反之呢?用户希望将自己喜爱的应用设置为默认的文件打开方式。文件处理 API 是一项实验性 API,可让已安装的 PWA 执行以下操作:在用户设备上注册为文件处理程序,在 Web 应用清单中指定 PWA 支持的 MIME 类型和文件扩展名。您可以为受支持的扩展程序指定自定义文件图标。
注册后,已安装的 PWA 将显示为用户文件系统中的选项,用户可以直接在其中打开文件。以下是用于让 PWA 读取文本文件的清单设置示例:
...
"file_handlers": [
{
"action": "/open-file",
"accept": {
"text/*": [".txt"]
}
}
]
...
网址处理
借助网址处理功能,您的 PWA 可以从操作系统捕获其范围内的链接,并在 PWA 窗口(而非默认浏览器的标签页)中呈现这些链接。例如,如果您收到指向 PWA 的邮件,或者点击 PWA 中的深层链接(指向特定内容的网址),相应内容将在独立窗口中打开。
使用 WebAPK 时,Android 设备会自动提供此行为,例如当用户使用 Chrome 安装 PWA 时。无法通过 Safari 捕获安装在 iOS 和 iPadOS 上的 PWA 的网址。
对于桌面浏览器,网络浏览器社区创建了新的规范。此规范目前处于实验阶段;它添加了一个新的清单文件成员: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 作用域网址的网址处理。开发者必须创建此文件。在以下示例中,该文件如下所示:
{
"web_apps": [
{
"manifest": "/mypwa/app.webmanifest",
"details": {
"paths": [ "/*" ]
}
}
]
}
网址协议处理
网址处理适用于标准 https
协议网址,但也可以使用自定义 URI 架构,例如 pwa://
。在某些操作系统中,已安装的应用通过注册其 scheme 来获得此能力。
对于 PWA,此功能是使用网址协议处理程序 API 启用的,该 API 仅适用于桌面设备。您只能通过在应用商店中分发 PWA 来为移动设备允许自定义协议。
如需进行注册,您可以使用 registerProtocolHandler() 方法,也可以在清单中使用 protocol_handlers
成员,并提供所需的架构和您要在 PWA 上下文中加载的网址,例如:
...
{
"protocol_handlers": [
{
"protocol": "web+pwa",
"url": "/from-protocol?value=%s"
},
]
}
...
您可以将网址 from-protocol
路由到正确的处理脚本,并在 PWA 中获取查询字符串 value
。%s
是触发操作的已转义网址的占位符,因此,如果您在某个位置(例如 <a href="web+pwa://testing">
)有链接,您的 PWA 将打开 /from-protocol?value=testing
。
调用其他应用
您可以使用 URI 架构在各个平台上连接到用户设备中的任何其他已安装应用(无论是 PWA 还是其他应用)。您只需创建一个链接或使用 navigator.href
并指向所需的 URI 架构,以网址转义形式传递参数即可。
您可以使用众所周知的标准 scheme,例如使用 tel:
进行通话、使用 mailto:
发送电子邮件或使用 sms:
发送短信;也可以了解其他应用的网址 scheme,例如众所周知的即时通讯、地图、导航、在线会议、社交网络和应用商店。
网页分享
借助 Web Share API,您的 PWA 可以通过共享渠道将内容发送到设备中已安装的其他应用。
此 API 仅适用于具有 share
机制的操作系统,包括 Android、iOS、iPadOS、Windows 和 ChromeOS。
您可以共享包含以下内容的对象:
- 文本(
title
和text
属性) - 网址(
url
属性) - 文件(
files
属性)。
如需检查当前设备是否可以共享简单数据(例如文本),请检查是否存在 navigator.share()
方法;如需共享文件,请检查是否存在 navigator.canShare()
方法。
您可以通过调用 navigator.share(objectToShare)
请求执行分享操作。该调用会返回一个 promise,该 promise 会解析为 undefined
或因异常而被拒绝。
Web Share Target
借助 Web Share Target API,您的 PWA 可以成为设备上其他应用(无论是 PWA 还是非 PWA)的共享操作目标。您的 PWA 会接收其他应用共享的数据。
该功能目前适用于搭载 WebAPK 的 Android 设备和 ChromeOS,并且仅在用户安装了您的 PWA 后才可使用。浏览器会在应用安装时在操作系统中注册共享目标。
您可以使用“网站共享目标”草稿规范中定义的 share_target
成员在清单中设置网站共享目标。share_target
会设置为具有以下属性的对象:
action
- 将在预计接收共享数据的 PWA 窗口中加载的网址。
method
- 系统将为操作使用 HTTP 动词方法,例如
GET
、POST
或PUT
。 enctype
- (可选)参数的编码类型,默认为
application/x-www-form-urlencoded
,但对于POST
等方法,也可以设置为multipart/form-data
。 params
- 一个对象,用于将分享数据(来自 Web Share 的键:
title
、text
、url
和files
)映射到浏览器将使用所选编码在网址(在method: 'GET'
上)或请求正文中传递的参数。
例如,您可以通过在清单中添加以下代码,为 PWA 定义要接收的共享数据(仅限标题和网址):
...
"share_target": {
"action": "/receive-share/",
"method": "GET",
"params": {
"title": "shared_title",
"url": "shared_url"
}
}
...
在前面的示例中,如果系统中的任何应用都与标题共享网址,并且用户从对话框中选择您的 PWA,浏览器将创建指向您来源的 /receive-share/?shared_title=AAA&shared_url=BBB
的新导航,其中 AAA 是共享的标题,BBB 是共享的网址。您可以使用 JavaScript 通过 URL
构造函数解析 window.location
字符串,从中读取数据。
浏览器将使用清单中的 PWA 名称和图标来填充操作系统的分享条目。您无法为此目的选择其他组合。
如需查看更详细的示例以及如何接收文件,请参阅使用 Web Share Target API 接收共享数据
联系人选取工具
借助 Contact Picker API,您可以请求设备呈现包含用户所有联系人的原生对话框,以便用户选择一个或多个联系人。然后,您的 PWA 便可从这些联系人那里接收所需的数据。
Contact Picker API 主要适用于移动设备,所有操作均通过兼容平台上的 navigator.contacts
界面完成。
您可以使用 navigator.contacts.getProperties()
请求可供查询的属性,并请求选择一个或多个联系人,以及所需属性的列表。
一些示例属性包括 name
、email
、address
和 tel
。当您要求用户选择一个或多个联系人时,可以调用 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.
}
}