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

使用 JavaScript 读取电话联系人

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

作者注:本文中描述的技术和流程是实验性的,仅适用于少数浏览器。在撰写本文时,联系人选取器 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]删除
最新教程 更多>
  • 对象拟合:IE和Edge中的封面失败,如何修复?
    对象拟合:IE和Edge中的封面失败,如何修复?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    编程 发布于2025-04-17
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-04-17
  • 如何解决由于Android的内容安全策略而拒绝加载脚本... \”错误?
    如何解决由于Android的内容安全策略而拒绝加载脚本... \”错误?
    Unveiling the Mystery: Content Security Policy Directive ErrorsEncountering the enigmatic error "Refused to load the script..." when deployi...
    编程 发布于2025-04-17
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样,如何?答案:是的,可以将您的Encryption库从McRypt升级到OpenSSL。可以使用openssl。附加说明: [openssl_decrypt()函数要求iv参...
    编程 发布于2025-04-17
  • 如何使用“ JSON”软件包解析JSON阵列?
    如何使用“ JSON”软件包解析JSON阵列?
    parsing JSON与JSON软件包 QUALDALS:考虑以下go代码:字符串 } func main(){ datajson:=`[“ 1”,“ 2”,“ 3”]`` arr:= jsontype {} 摘要:= = json.unmarshal([] byte(...
    编程 发布于2025-04-17
  • JavaScript中如何动态访问全局变量?
    JavaScript中如何动态访问全局变量?
    在JavaScript 一种方法是使用窗口对象存储和检索变量。通过引用全局范围,可以使用其名称动态访问变量。 //一个脚本 var somevarname_10 = 20; //另一个脚本 window.all_vars = {}; window.all_vars ['somevarnam...
    编程 发布于2025-04-17
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-04-17
  • 如何重置Postgres主键序列与表行不同步?
    如何重置Postgres主键序列与表行不同步?
    [2 解决PostgreSql主键序列差异 与表行未对准的主键序列可能会导致令人沮丧的重复键错误。这通常发生在数据导入或恢复未保留序列完整性的地方。 这是修复它的方法: 1。查找最高ID: 使用 max()[2 [2 2。获取序列的下一个值: 此查询显示了序列的下一个生成值: sel...
    编程 发布于2025-04-17
  • JavaScript计算两个日期之间天数的方法
    JavaScript计算两个日期之间天数的方法
    How to Calculate the Difference Between Dates in JavascriptAs you attempt to determine the difference between two dates in Javascript, consider this s...
    编程 发布于2025-04-17
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-04-17
  • 哪种在JavaScript中声明多个变量的方法更可维护?
    哪种在JavaScript中声明多个变量的方法更可维护?
    在JavaScript中声明多个变量:探索两个方法在JavaScript中,开发人员经常遇到需要声明多个变量的需要。对此的两种常见方法是:在单独的行上声明每个变量: 当涉及性能时,这两种方法本质上都是等效的。但是,可维护性可能会有所不同。 第一个方法被认为更易于维护。每个声明都是其自己的语句,使其...
    编程 发布于2025-04-17
  • 在GO中构造SQL查询时,如何安全地加入文本和值?
    在GO中构造SQL查询时,如何安全地加入文本和值?
    在go中构造文本sql查询时,在go sql queries 中,在使用conting and contement和contement consem per时,尤其是在使用integer per当per当per时,per per per当per. [&​​&&&&&&&&&&&&&&&默元组方法在...
    编程 发布于2025-04-17
  • 解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    编程 发布于2025-04-17
  • 为什么使用Firefox后退按钮时JavaScript执行停止?
    为什么使用Firefox后退按钮时JavaScript执行停止?
    导航历史记录问题:JavaScript使用Firefox Back Back 此行为是由浏览器缓存JavaScript资源引起的。要解决此问题并确保在后续页面访问中执行脚本,Firefox用户应设置一个空功能。 警报'); }; alert('inline Alert')...
    编程 发布于2025-04-17
  • CSS强类型语言解析
    CSS强类型语言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    编程 发布于2025-04-17

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

Copyright© 2022 湘ICP备2022001581号-3