”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 JavaScript 读取电话联系人

使用 JavaScript 读取电话联系人

发布于2024-08-26
浏览:148

作者注:本文中描述的技术和流程是实验性的,仅适用于少数浏览器。在撰写本文时,联系人选取器 API 仅受 Android Chrome(从版本 80 开始)和 iOS Safari(从版本 14.5 开始,但仅在标志后面)支持。如果您想查看该功能,可以在我的网站上查看正在运行的演示。


从手机或平板电脑上的联系人列表中读取条目传统上仅限于本机应用程序。但通过联系人选择器 API,我们可以使用 JavaScript 来做到这一点。

此功能对于需要电话号码或 VoIP 等联系信息的应用程序、我们想要发现认识的人的社交网络或需要填写表单信息而不交换应用程序来查看数据的应用程序可能很有趣。

API 和设备将限制哪些属性可用。有五个标准可供开发者选择:

  • 姓名
  • 电话
  • 电子邮件
  • 地址
  • 图标

这里的复数很重要,因为一个联系人可以有多个电话、电子邮件或多个地址。为了一致性,返回的数据将始终位于数组内,即使它是单个值。稍后会详细介绍。


隐私和安全

手机上存储的联系信息可能包含我们必须谨慎对待的敏感信息。因此,我们必须考虑隐私和安全因素:

  • 联系人选取器 API 代码必须在顶级浏览上下文中运行。它可以防止外部代码(例如广告或第三方插件)读取您手机上的联系人列表。
  • 联系人选取器 API 代码只能在用户手势后运行。因此,开发人员无法完全自动化该过程。用户必须采取行动才能触发接触读取。
  • 此人必须允许访问联系人列表。这个限制是手机强加的,不是JS强加的。用户必须授予浏览器访问联系人的权限(如果还没有)。

他们第一次使用使用联系人选择器 API 的网站时,可能会收到如下消息:

Read Phone Contacts with JavaScript

有些人可能会觉得这个弹出窗口“可怕”。
 

手机每次都会显示此弹出窗口,直到用户点击“允许”。在此之前,联系人选取器 API 将不会运行。哪个好;我们希望确保用户授予适当的权限。一次性的事情也很好。每次页面运行联系人选择器 API 代码时授予授权将是一件令人头疼的事情。


API 和代码

联系人选取器 API 只定义了两个方法:

  • getProperties():返回可在设备上读取的属性列表。定义中只有五个:“地址”、“电子邮件”、“图标”(这可能不是联系人图片)、“姓名”、“电话”(电话),但设备可能不允许访问所有其中。
  • select():打开联系人弹出窗口并在用户完成操作后返回选择。它需要两个参数:要读取的属性列表和带有选项的可选对象。

这两种方法都返回 Promise,但考虑到它们触发的操作会阻塞应用程序的常规流程,我们在处理它们时应该使用 async/await。

忽略 getProperties() 并直接请求所有属性可能很诱人。但如果你这样做的话要小心:它可能会起作用,但如果任何指定的属性不可用, select() 方法将抛出异常。

例子

联系人选择器 API 的演示正在运行(在此处在线运行或观看此视频)。如果支持 API,它会显示一个按钮,用于读取联系人的电话号码、姓名和电子邮件以进行显示。

首先,我们需要按钮。正如隐私和安全部分前面详细介绍的,在调用 API 之前需要用户执行操作,因此如果没有用户交互,我们无法触发任何内容:


主要代码在 getContactData() 函数中。但在此之前,如果联系人选择器 API 不可用,那么显示该按钮有何意义呢?如果按钮不可用,我们将其隐藏。或者更好的是,让我们默认隐藏按钮(添加隐藏属性),并且仅在 API 可用时才显示它。

// only show the button if browser supports Contact Picker API
if ("contacts" in navigator) {
  document.querySelector("button").removeAttribute("hidden");
}

现在按钮逻辑已经就位,让我们关注 getContactData()。这是该函数的注释版本:

// it is asynchronous because we'll wait for the modal selection
async function getContactData() {
  // indicate what contact values will be read
  const props = ["tel", "name", "email"];

  // wrap everything in a try...catch, just in case
  try {
    // open the native contact selector (after permission is granted)
    const contacts = await navigator.contacts.select(props);

    // this will execute after the native contact selector is closed
    if (contacts.length) {
      // if there's data, show it
      alert("Selected data: "   JSON.stringify(contacts));
    } else {
      // ...if not, indicate nothing was selected
      alert("No selection done");
    }
  } catch (ex) {
    // if something fails, show the error message
    alert(ex.message)
  }
}

一旦按钮触发此功能,并且如果浏览器有权限(参见上一节的屏幕截图),则会显示联系模式,指示基本信息:读取数据的 URL、将返回什么数据以及可供选择的联系人列表。

Read Phone Contacts with JavaScript

联系人选择器显示将共享哪些信息
 

关闭模式后,contacts 变量会将数据存储在 JSON 中,作为一个数组,其中包含包含所请求信息的对象(如果联系人卡片中不可用,则可能为空)。

例如,这是选择自己作为联系人后的结果(假数据):

[
  {
    "address": [],
    "email": [ "[email protected]" ],
    "icon": [],
    "name": [ "Alvaro Montoro" ],
    "tel": [ "555-555-5555", "555-123-4567" ]
  }
]

如果数据包含图标,它将是带有图像的斑点。如果数据中包含地址,那么它将是一个更复杂的对象,包含街道、城市、国家、邮政编码等。您可以在规范中查看返回值。

但是,如果我们只选择一个联系人,为什么要使用数组呢?因为可以选择多个联系人!

选择多个联系人

可以选择多个联系人。如果我们想这样做,我们需要将第二个参数传递给 navigator.contacts.select() 方法来指示此选项。

const props = ["tel", "address", "icon", "name", "email"];
// only one option available: read multiple or only one (default)
const options = { multiple: true };

try {
  const contacts = await navigator.contacts.select(props, options);
  // ...

结果是一个联系人数组,因此本示例的其余代码可以保持不变。


上面的代码可能会令人生畏,主要是因为我添加了所有注释。这是上面代码的简单注释版本。正如您可能注意到的,这非常简单:

async function getContactData() {
  if ("contacts" in navigator) {
    const props = await navigator.contacts.getProperties();
    const options = { multiple: true };

    try {
      const contacts = await navigator.contacts.select(props, options);

      if (contacts.length) {
        // code managing the selected data
      } else {
        // code when nothing was selected
      }
    } catch (ex) {
      // code if there was an error
    }
  }
}

您可以在我的网站上查看正在运行的演示。别担心,除了将联系信息写在屏幕上之外,我不会对其进行任何操作。但如果你不相信我,请先检查一下代码。


结论:隐私优于盗版

联系信息是 PII(个人身份信息),我们必须以敏感数据所需的谨慎和安全态度对待它。

除了我不会遵循的可能的法律要求(因为我不了解它们,而且它们因国家/地区而异),以下是处理敏感数据时的一些基本准则:

  • 尊重人们的隐私。不要强迫他们分享他们不想分享的信息。
  • 以安全的方式谨慎处理数据。如果您正在处理的数据是您自己的,您会放心吗?
  • 如果不需要,请勿存储数据。阅读它,使用它,忘记它。不要存储您不使用的数据。
  • 仅获取您需要的数据。不要偷偷摸摸或阴暗。获取建立可信度和信任所需的信息。

假设 Web 应用程序在选择电话号码时尝试读取地址、姓名或电子邮件。如果这种情况发生在我身上,我会自动拒绝许可并离开网站。

因此,请探索 JavaScript 和联系人选择器 API,但请始终记住,屏幕后面有人,他们共享的数据如果落入坏人之手,可能会存在风险。别乱来。



如果您喜欢这篇关于 JavaScript 的文章,并且喜欢使用 JS 测试 Web API 和不同的东西,请查看另一篇文章:


使用 HTML 和 JavaScript 开发摇滚乐队游戏
Read Phone Contacts with JavaScript

版本声明 本文转载于:https://dev.to/alvaromontoro/read-phone-contacts-with-javascript-1j2?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • JavaScript 是同步还是异步,是单线程还是多线程? JavaScript代码是如何执行的?
    JavaScript 是同步还是异步,是单线程还是多线程? JavaScript代码是如何执行的?
    JavaScript 是一种同步、单线程语言,一次只能执行一个命令。仅当当前行执行完毕后,才会移至下一行。但是,JavaScript 可以使用事件循环、Promises、Async/Await 和回调队列执行异步操作(JavaScript 默认情况下是同步的)。 JavaScript代码是如何执行的...
    编程 发布于2024-11-06
  • 如何从 PHP 中的对象数组中提取一列属性?
    如何从 PHP 中的对象数组中提取一列属性?
    PHP:从对象数组中高效提取一列属性许多编程场景都涉及使用对象数组,其中每个对象可能有多个属性。有时,需要从每个对象中提取特定属性以形成单独的数组。在 PHP 中,在不借助循环或外部函数的情况下用一行代码实现此目标可能很棘手。一种可能的方法是利用 array_walk() 函数和 create_fu...
    编程 发布于2024-11-06
  • 构建 PHP Web 项目的最佳实践
    构建 PHP Web 项目的最佳实践
    规划新的 PHP Web 项目时,考虑技术和战略方面以确保成功非常重要。以下是一些规则来指导您完成整个过程: 1. 定义明确的目标和要求 为什么重要:清楚地了解项目目标有助于避免范围蔓延并与利益相关者设定期望。 行动: 创建具有特定功能的项目大纲。 确定核心特征和潜在的发展阶段。 ...
    编程 发布于2024-11-06
  • 如何在不使用嵌套查询的情况下从 MySQL 中的查询结果分配用户变量?
    如何在不使用嵌套查询的情况下从 MySQL 中的查询结果分配用户变量?
    MySQL 中根据查询结果分配用户变量背景和目标根据查询结果分配用户定义的变量可以增强数据库操作能力。本文探讨了一种在 MySQL 中实现此目的的方法,而无需借助嵌套查询。用户变量赋值语法与流行的看法相反,用户变量赋值可以直接集成到查询中。 SET 语句的赋值运算符是= 或:=。但是,:= 必须在其...
    编程 发布于2024-11-06
  • 如何使用 array_column() 函数从 PHP 中的对象数组中提取 Cat ID?
    如何使用 array_column() 函数从 PHP 中的对象数组中提取 Cat ID?
    从 PHP 中的对象数组中提取猫 ID处理对象数组(例如猫对象数组)时,提取特定属性通常可以成为一项必要的任务。在这种特殊情况下,我们的目标是将每个 cat 对象的 id 属性提取到一个新数组中。正如您的问题中所建议的,一种方法涉及使用 array_walk() 和 create_function ...
    编程 发布于2024-11-06
  • 实用指南 - 迁移到 Next.js App Router
    实用指南 - 迁移到 Next.js App Router
    随着 Next.js App Router 的发布,许多开发者都渴望迁移他们现有的项目。在这篇文章中,我将分享我将项目迁移到 Next.js App Router 的经验,包括主要挑战、变化以及如何使该过程更加顺利。 这是一种增量方法,您可以同时使用页面路由器和应用程序路由器。 为...
    编程 发布于2024-11-06
  • 何时以及为何应调整 @Transactional 中的默认隔离和传播参数?
    何时以及为何应调整 @Transactional 中的默认隔离和传播参数?
    @Transactional中的隔离和传播参数在Spring的@Transactional注解中,两个关键参数定义了数据库事务的行为:隔离和传播。本文探讨了何时以及为何应考虑调整其默认值。传播传播定义了事务如何相互关联。常见选项包括:REQUIRED: 在现有事务中运行代码,如果不存在则创建一个新事...
    编程 发布于2024-11-06
  • OpenAPI 修剪器 Python 工具
    OpenAPI 修剪器 Python 工具
    使用 OpenAPI Trimmer 简化您的 OpenAPI 文件 管理大型 OpenAPI 文件可能会很麻烦,尤其是当您只需要一小部分 API 来执行特定任务时。这就是 OpenAPI Trimmer 派上用场的地方。它是一个轻量级工具,旨在精简您的 OpenAPI 文件,使其...
    编程 发布于2024-11-06
  • PHP:揭示动态网站背后的秘密
    PHP:揭示动态网站背后的秘密
    PHP(超文本预处理器)是一种服务器端编程语言,广泛用于创建动态和交互式网站。它以其简单语法、动态内容生成能力、服务器端处理和快速开发能力而著称,并受到大多数网络托管服务商的支持。PHP:揭秘动态网站背后的秘方PHP(超文本预处理器)是一种服务器端编程语言,以其用于创建动态和交互式网站而闻名。它广泛...
    编程 发布于2024-11-06
  • JavaScript 中的变量命名最佳实践,实现简洁、可维护的代码
    JavaScript 中的变量命名最佳实践,实现简洁、可维护的代码
    简介:增强代码清晰度和维护 编写干净、易理解和可维护的代码对于任何 JavaScript 开发人员来说都是至关重要的。实现这一目标的一个关键方面是通过有效的变量命名。命名良好的变量不仅使您的代码更易于阅读,而且更易于理解和维护。在本指南中,我们将探讨如何选择具有描述性且有意义的变量名称,以显着改进您...
    编程 发布于2024-11-06
  • 揭示 Spring AOP 的内部工作原理
    揭示 Spring AOP 的内部工作原理
    在这篇文章中,我们将揭开 Spring 中面向方面编程(AOP)的内部机制的神秘面纱。重点将放在理解 AOP 如何实现日志记录等功能,这些功能通常被认为是一种“魔法”。通过浏览核心 Java 实现,我们将看到它是如何与 Java 的反射、代理模式和注释相关的,而不是任何真正神奇的东西。 ...
    编程 发布于2024-11-06
  • JavaScript ESelease 笔记:释放现代 JavaScript 的力量
    JavaScript ESelease 笔记:释放现代 JavaScript 的力量
    JavaScript ES6,正式名称为 ECMAScript 2015,引入了重大增强功能和新功能,改变了开发人员编写 JavaScript 的方式。以下是定义 ES6 的前 20 个功能,它们使 JavaScript 编程变得更加高效和愉快。 JavaScript ES6 的 2...
    编程 发布于2024-11-06
  • 了解 Javascript 中的 POST 请求
    了解 Javascript 中的 POST 请求
    function newPlayer(newForm) { fetch("http://localhost:3000/Players", { method: "POST", headers: { 'Content-Type': 'application...
    编程 发布于2024-11-06
  • 如何使用 Savitzky-Golay 滤波平滑噪声曲线?
    如何使用 Savitzky-Golay 滤波平滑噪声曲线?
    噪声数据的平滑曲线:探索 Savitzky-Golay 过滤在分析数据集的过程中,平滑噪声曲线的挑战出现在提高清晰度并揭示潜在模式。对于此任务,一种特别有效的方法是 Savitzky-Golay 滤波器。Savitzky-Golay 滤波器在数据可以通过多项式函数进行局部近似的假设下运行。它利用最小...
    编程 发布于2024-11-06
  • 重载可变参数方法
    重载可变参数方法
    重载可变参数方法 我们可以重载一个采用可变长度参数的方法。 该程序演示了两种重载可变参数方法的方法: 1 各种可变参数类型:可以重载具有不同可变参数类型的方法,例如 vaTest(int...) 和 vaTest(boolean...)。 varargs 参数的类型决定了将调用哪个方法。 2 添加公...
    编程 发布于2024-11-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3