Web 联系人选择器 API 简介
如果你正在开发一款移动应用,需要访问用户的联系人,你肯定不会犹豫,但在网页端,这项功能却一直缺失。Chrome 团队发现了这个空白,并着手开发一个 API,让开发者能够以网页端应有的安全性和隐私保护方式访问用户的联系人。现在,该 API 已在 Android M 或更高版本的 Chrome 80 中提供。
在这篇文章中,我们将研究新的联系人选择器 API,并将其应用于Twilio 客户端应用程序,以添加联系人选择功能,用于通过浏览器拨打电话。
联系人选择器 API
联系人选择器 API 由一个ContactsManager对象组成,该对象可通过contacts其属性访问navigator。由于目前仅在 Android 版 Chrome 浏览器上受支持,因此我们首先需要检查浏览器是否支持。我们可以使用以下代码行进行检查:
const supportsContacts = ('contacts' in navigator && 'ContactsManager' in window);
我们应该确保将任何使用联系人选择器 API 的代码都放在支持条件测试中,以免在不支持该 API 的浏览器中导致 JavaScript 错误。
确认可以使用后,我们接下来关注该navigator.contacts.select函数。它接受两个参数:一个包含联系人属性的数组和一个选项对象。可用的属性包括“name”、“email”和“tel”(此外,还有一个试用版,可以添加两个额外的属性:“address”和“icon”)。第二个参数只有一个选项:“multiple”,其值为 true 或 false,表示您希望返回一个还是多个联系人。
select会向用户显示一个模态框,其中包含一个允许用户选择联系人的界面,然后返回一个 Promise 对象。该 Promise 对象会解析为一个联系人数组(即使您只请求了一个联系人)。每个联系人都会有一个数组属性,分别对应您请求的每个属性(因为联系人应用程序允许多个电话号码或电子邮件地址)。例如:
navigator.contacts.select(["name", "tel"])
.then(contacts => {
console.log(contacts);
})
.catch(console.error);
//=> [{ "name": ["Phil Nash"], "tel": ["+61412345678", "+447123456789"]}]
由于我们返回的是一个 Promise,所以你也可以使用 async/await:
try {
const contacts = await navigator.select(["name", "tel"]);
console.log(contacts);
} catch(error) {
console.error(error);
}
//=> [{ "name": ["Phil Nash"], "tel": ["+61412345678", "+447123456789"]}]
接下来,您的应用程序需要显示联系人信息,并允许用户选择要在应用程序中使用的联系人属性。
联系人选择器 API 需要用户通过手势激活,并且只能在安全域上运行,这与其他可能访问敏感数据的新型 Web API 类似。此外,每次调用该 API 时都会显示联系人选择器模态框,因此不会永久访问用户的联系人,用户始终可以控制自己共享的数据。
理论部分就到此为止,让我们把它添加到应用程序中看看实际效果。
在应用程序中使用联系人选择器 API
作为本文的引子,我构建了一个简单的基于 Twilio Client 的应用程序,它可以通过浏览器拨打电话。我们将使用 Contact Picker API 添加从设备联系人中选择呼叫对象的功能。
准备申请
运行此应用程序需要以下几项:
- Node.js
- 一个 Twilio 帐户(如果您还没有帐户,请在此处注册一个新的 Twilio 帐户,升级时即可获得 10 美元信用额度)
- 您可以使用此号码拨打 Twilio 电话。
- 使用ngrok,我们可以暴露本地服务器并接收传入的 webhook。
- 一台装有部分联系人的安卓设备用于测试
准备好这些文件后,首先从 GitHub 克隆或下载应用程序的入门分支:
git clone https://github.com/philnash/contact-picker-twilio-client.git -b getting-started
cd contact-picker-twilio-client
安装依赖项:
npm install
将文件复制.env.example到.env:
cp .env.example .env
现在您需要填写.env包含账户凭证的文件。您可以在Twilio 控制台中找到您的 Twilio 账户 SID 。您还需要生成一个API 密钥,并收集 SID 和密钥(如果您想了解更多关于 API 密钥和密钥的信息,请观看此视频)。对于来电显示,您可以购买一个新的电话号码,或者验证您自己的电话号码。最后,您还需要一个TwiML 应用。
TwiML 应用是一组 Webhook URL,Twilio 可以使用这些 URL 将呼叫连接到您的应用程序。对于 Twilio 客户端,当您从浏览器发起呼叫时,Twilio 需要知道下一步如何处理该呼叫,因此会查询 TwiML 应用以查找要发送请求的语音 URL。要实现这一点,我们需要使用 ngrok 创建一个到本地服务器的隧道。
应用程序在 3000 端口启动,因此请运行:
ngrok http 3000
然后获取 ngrok URL 并创建一个 TwiML 应用程序,并为其提供语音 URL https://YOUR_NGROK_SUBDOMAIN.ngrok.io/voice。
配置全部完成,现在运行应用程序:
npm start
它看起来会是这样:
在输入框中输入您的电话号码,点击拨号,您将会接到一个电话。
添加联系人选择器 API
在编辑器或 IDE 中打开项目并加载。除了Twilio Client JS 库之外,这就是运行此应用程序所需的client/app.js所有代码。
要将联系人选择器 API 添加到此系统中,我们需要执行以下几个步骤:
- 检查我们是否支持该 API。
- 在界面上添加一个按钮以触发 API
- 监听点击事件并调用联系人选择器 API
- 处理来自 API 的响应,并将联系人的电话号码填充到输入框中。
首先,在init函数底部检查一下 API 是否受支持。如果受支持,我们还需要编写更多代码;如果不受支持,则显示一条解释性消息。
});
});
if ("contacts" in navigator && "ContactsManager" in window) {
} else {
const notSupported = document.createElement("p");
notSupported.classList.add("error");
notSupported.innerText = "Sorry, the contact picker API is not supported in your browser.";
dialBtn.insertAdjacentElement("afterend", notSupported);
}
};
window.addEventListener("DOMContentLoaded", init);
接下来,我们将获取<main>页面上元素的引用,创建一个按钮并将其附加到该元素上。
if ("contacts" in navigator && "ContactsManager" in window) {
const mainElt = document.getElementsByTagName("main")[0];
const contactsButton = document.createElement("button");
contactsButton.innerText = "Choose contact";
mainElt.appendChild(contactsButton);
}
我们需要在用户点击此按钮时触发联系人选择器 API(注意:该 API 需要点击等交互操作,因此无法在页面加载时触发)。调用联系人选择器 API 时,我们会传递一个属性数组,在本例中,我们只需要联系人姓名和电话号码。我们还可以传递一个对象,指定是否需要多个联系人。
我们还会使用 async/await 来处理来自 API 的异步响应。为此,我们的处理函数需要声明为一个async函数。在将按钮添加到页面的代码之前添加事件处理程序。
contactsButton.innerText = "Choose contact";
contactsButton.addEventListener("click", async () => {
const contactProperties = ["name", "tel"];
const options = { multiple: false };
const contacts = await navigator.contacts.select(contactProperties, options);
});
mainElt.appendChild(contactsButton);
}
API 调用成功后,该contacts变量将是一个数组。如果用户选择了一个联系人,则数组中将包含一个元素;如果传递了多个选项{ multiple: true },则数组中可能包含多个元素;如果用户根本没有选择任何联系人,则数组为空。在继续操作之前,我们应该检查数组中是否存在联系人。
一旦确定找到了联系人,我们就可以提取他们的姓名和电话号码。联系人对象会包含我们请求的每个属性,在本例中是“姓名”和“电话号码”。这些属性是数组,可以包含零个、一个或多个条目。在测试过程中,我发现联系人的数组中可能包含空条目,因此我们也需要过滤掉这些空条目。
对于此应用程序,如果没有可用的电话号码,我们将忽略它;否则,我们将把电话号码作为输入的值添加进去,并将名称添加到“拨号”按钮中。
const contacts = await navigator.contacts.select(contactProperties, options);
if (contacts.length > 0) {
const contact = contacts[0];
const contactNumber = contact.tel.filter(tel => tel.length > 0)[0];
const contactName = contact.name.filter(name => name.length > 0)[0];
if (contactNumber) {
phoneNumInput.value = contactNumber.replace(/\s/g, "");
dialBtn.innerText = `Dial ${contactName}`;
}
}
});
}
这就是测试所需的所有代码。在安卓设备上的 Chrome 浏览器中打开你的应用(你也可以使用 ngrok URL)。它应该像这样运行:
联系人选择器 API 在这里
本文介绍了联系人选择器 API,并展示了一个使用该 API 简化联系人拨号的 Web 应用程序示例。您可以在 GitHub 上查看此电话和联系人 Web 应用程序的完整版本。
我们还发现,应该测试一下这个 API 是否存在,因为它目前仅在 Android M 及更高版本的 Chrome 80 中可用。其他浏览器是否会实现它还有待观察,但你可以利用这个 API 逐步提升部分用户的体验。
这个 API 不仅适用于我们开发的这类通信应用,还可以用来与用户的联系人分享内容,甚至可以为用户构建社交关系图。你有什么利用这个 API 开发应用的想法吗?欢迎在下方评论区或在Twitter 上联系我 @philnash。
文章来源:https://dev.to/twilio/an-introduction-to-the-web-contact-picker-api-43ap

