在应用之间共享数据
应用共享是指一个应用将信息或数据传递给同一设备上的另一个应用的能力。此功能对用户很有用,因为它允许他们在两个应用之间共享信息,而无需这些应用事先了解对方。
例如,在您的移动设备上,您可以从照片应用中将照片或视频分享到另一个接受图像的应用,例如电子邮件应用。这种共享模式由安装了这两个应用的操作系统(OS)编排。
- 当用户发起照片分享时,照片应用会准备所选图像的数据,并将其交给操作系统。
- 操作系统会选择能够处理共享图像数据的应用列表,并将其显示给用户。
- 一旦用户选择了一个目标应用,操作系统就会用共享的图像启动该应用。
渐进式 Web 应用 (PWA) 也可以使用相同的 OS 编排模式来共享信息。PWA 既可以共享数据,也可以接收共享数据。
在构建 PWA 时,接受共享数据可以让您的 PWA 感觉更熟悉,并更自然地集成到用户的设备中。
与他人分享数据
要让用户能够从您的 PWA 与其他应用共享数据,请使用 Web Share API。Web Share API 允许您的应用通过底层操作系统共享机制与其他应用共享文本、链接或文件。
要共享数据,请在用户操作(例如单击按钮)后使用 navigator.share() 方法。
检查支持情况
在您的应用中显示内容共享 UI 之前,请检查以确保 Web Share API 功能受支持。即使支持 Web Share API 的浏览器,也不是所有浏览器都支持共享所有类型的数据。因此,最好首先使用 navigator.canShare() 方法来验证您打算共享的数据是否确实可以从运行您应用的浏览器中共享。
此示例显示了如何检查 Web Share API 是否受支持以及数据是否可以共享
function canBrowserShareData(data) {
if (!navigator.share || !navigator.canShare) {
return false;
}
return navigator.canShare(data);
}
const sharedDataSample = {
title: "Some text title",
text: "More text",
url: "A url we want to share",
};
if (canBrowserShareData(sharedDataSample)) {
// Enable the share button in the UI.
renderAppSharingUI();
} else {
// We can't share on this browser/operating system.
}
处理异常
navigator.share() 方法返回一个 Promise,在共享数据不正确、用户中止共享操作或数据传输失败等情况下,该 Promise 可能会被拒绝。
因此,捕获 Promise 拒绝对于避免您的应用 JavaScript 代码出错非常重要。
async function shareData(data) {
try {
await navigator.share(data);
// The data was shared successfully.
} catch (e) {
// The data could not be shared.
console.error(`Error: ${e}`);
}
}
共享文本数据
以下示例演示了在应用中的按钮被单击时如何共享链接和一些文本。示例中使用的 canBrowserShareData 函数在 检查支持情况 中进行了描述,此处不再重复。
// Retrieve the button from the DOM. The button is hidden for now.
const button = document.querySelector("#share");
if (canBrowserShareData({ text: "text", url: "https://example.com" })) {
// Show the button.
button.style.display = "inline";
// Listen for click events on the button to share data.
button.addEventListener("click", async () => {
try {
await navigator.share({
text: "An MDN article to learn how to share data between apps",
url: "https://mdn.org.cn/docs/Web/Progressive_web_apps/How_to/Share_data_between_apps",
});
console.log("The URL was successfully shared");
} catch (err) {
console.error(`The URL could not be shared: ${err}`);
}
});
}
共享文件
以下代码示例演示了在应用中的按钮被单击时如何共享文件。canBrowserShareFiles 函数用于仅在浏览器支持文件共享时显示共享按钮。
function canBrowserShareFiles() {
if (!navigator.share || !navigator.canShare) {
return false;
}
// Create some test data with a file, to check if the browser supports
// sharing it.
const testFile = new File(["foo"], "foo.txt", { type: "text/plain" });
const data = { files: [testFile] };
return navigator.canShare(data);
}
// Retrieve the button from the DOM. The button is hidden for now.
const button = document.querySelector("#share");
if (canBrowserShareFiles()) {
// The browser supports sharing files. Show the button.
button.style.display = "inline";
// Listen for clicks on the button and share a file.
button.addEventListener("click", async () => {
try {
// Get the file to be shared. This function should return a File
// object, perhaps by creating it dynamically, or retrieving it
// from IndexedDB.
const file = await getTheFileToShare();
await navigator.share({
title: "My shared file",
files: [file],
});
console.log("The file was successfully shared");
} catch (err) {
console.error(`The file could not be shared: ${err}`);
}
});
}
有关更多信息,请参阅 navigator.share() 方法页面上的 共享文件示例。
处理来自其他应用的共享数据
要将您的 PWA 注册为其他应用共享数据的目标,请使用 Web Share Target API,特别是 share_target Web 应用清单成员。
share_target 清单成员允许已安装的 PWA 在操作系统级别被注册为其他应用共享内容的潜在目标。这意味着,当用户从另一个应用共享与您的 PWA 兼容的某些数据时,操作系统会将您的 PWA 列在电子邮件或消息应用等典型共享目标旁边。请注意,PWA 必须已安装才能显示为接收共享数据的潜在目标。
您在清单文件中使用 share_target 成员提供的信息,定义了您的应用可以成为哪些数据的目标,以及当用户选择您的应用作为目标时,操作系统应如何启动您的应用。
处理文本数据
这是一个使用 share_target 成员的 Web 应用清单示例
{
"name": "ChattyBox",
"start_url": "/",
"display": "standalone",
"icons": [
{
"src": "images/icon-256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"share_target": {
"action": "/share-handler",
"method": "GET",
"params": {
"text": "description",
"url": "link"
}
}
}
当您的应用被用户选中以处理其他应用的共享内容时,您的应用将被启动,共享内容将以类似于 <form> 元素提交的方式传递给它。
在前面的 Web 应用清单代码示例中,当 ChattyBox 应用被选为目标时,它将通过对 /share-handler URL 发出 HTTP GET 请求来启动,共享数据将作为名为 description 和 link 的请求参数传递。
GET 请求将如下所示:/shared-handler?description=...&link=...。
您的应用的主要 JavaScript 代码随后可以使用 URLSearchParams 接口检索共享数据。
const url = new URL(document.location);
const sharedDescription = url.searchParams.get("description");
const sharedLink = url.searchParams.get("link");
有关更多信息,请参阅 share_target Web 应用清单成员页面上的 使用 GET 接收共享数据 示例。
处理共享文件
在前面的示例中,文本数据被作为 GET 请求处理。然而,处理文件需要使用 POST 请求,并使用 multipart/form-data 编码类型。
以下代码片段展示了 PWA 如何配置为接受不同类型的共享文件。
{
"name": "ChattyBox",
"start_url": "/",
"display": "standalone",
"icons": [
{
"src": "images/icon-256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"share_target": {
"action": "/share-file-handler",
"method": "POST",
"enctype": "multipart/form-data",
"params": {
"files": [
{
"name": "textFiles",
"accept": ["text/plain", ".txt"]
},
{
"name": "htmlFiles",
"accept": ["text/html", ".html"]
},
{
"name": "images",
"accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
}
]
}
}
}
如本示例所示,files 属性中的每个文件对象都必须具有 name 属性和 accept 属性。accept 属性必须指定接受的 MIME 类型或文件扩展名。
当您的应用被用户选中以处理共享文件(或文件)时,应用将以 POST 请求在 /share-file-handler URL 处启动,并附带编码的表单数据。
由于这是一个 POST 请求,您的应用的主要 JavaScript 代码无法直接访问表单数据。您可以在服务器端代码中处理提交的文件,通过在 /share-file-handler URL 端点接收它们。但是,为了获得更好的离线体验,您可以使用 fetch 事件处理程序在服务工作线程代码中处理文件,如下所示。
// service-worker.js
self.addEventListener("fetch", (event) => {
// Only use this event listener for POST requests sent to /share-file-handler.
const url = new URL(event.request.url);
if (
event.request.method !== "POST" ||
url.pathname !== "/share-file-handler"
) {
return;
}
event.respondWith(
(async () => {
// Get the data from the submitted form.
const formData = await event.request.formData();
// Get the submitted files.
const textFiles = formData.getAll("textFiles");
const htmlFiles = formData.getAll("htmlFiles");
const imageFiles = formData.getAll("images");
// Send the files to the frontend app.
sendFilesToFrontend(textFiles, htmlFiles, imageFiles);
// Redirect the user to a URL that shows the imported files.
return Response.redirect("/display-new-files", 303);
})(),
);
});
在此代码示例中,共享文件从表单数据中提取,用户被重定向到另一个页面。您可以使用服务工作线程中的代码按照自己的意愿处理提取的文件。例如,您可以使用 Worker.postMessage() 方法将它们发送到您应用的主 JavaScript 代码,或者将它们存储在 Indexed DB 数据库中,该数据库可供您的服务工作线程和应用的主 JavaScript 代码访问。
有关更多信息,请参阅 share_target Web 应用清单成员页面上的 接收共享文件 示例。
另见
- Web Share API
share_target清单成员- 使用 Web Share API 与 OS 共享 UI 集成(来自 web.dev)
- 使用 Web Share Target API 接收共享数据(来自 developer.chrome.com)
- 与其他应用共享内容(来自 microsoft.com)