热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android导入vCard联系人流程

本博客基于android7.1版本分析,仅用于沟通学习使用上一篇博客介绍了android导出vCard联系人流程紧接着我们在这篇博客来看看它是如何导入一个vCard

本博客基于android7.1版本分析,仅用于沟通学习使用

上一篇博客介绍了 android导出vCard联系人流程 紧接着我们在这篇博客来看看它是如何导入一个vCard联系人的。


整体流程总结


  1. 通过在contacts联系人中界面跳转,我们跳转到了 DocumentsActivity 界面并选择我们需要导入的以 .vcf 结尾的vCard文件,将Uri以intent的方式返回给ImportVCardActivity。
  2. 通过readUriToLocalUri方法将uri指向的文件copy到本地临时目录。
  3. 启动一个线程开始解析文件,并指定vCard类型为 text/x-vcard 版本为2.1,后面就只会创建2.1版本对应的解析器,所以其它版本的vCard导入可能会出现问题。
  4. 然后通过VCardParserImpl_V21来具体解析文件中的每一行,最后通过VCardEntryCommitter.pushIntoContentResolver批量插入contacts的数据库

几个重点类的作用


  • ImportVCardActivity : 一个中间控制类,它控制了界面dialog、notification、service、thread的启动和消失
  • VCardParserImpl_V21 : 负责vCard2.1版本内容的逐行解析
  • VCardEntryConstructor : 负责将解析出来的数据以VCardEntry的形式暂存在内存中
  • VCardEntryCommitter : 负责将解析出来的数据存储到contacts数据库中

整体操作图

这里写图片描述


整体流程图

这里写图片描述


部分重点方法介绍


VCardParserImpl_V21

/*** * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF* items *CRLF* "END" [ws] ":" [ws] "VCARD"* * @return False when reaching end of file.*/private boolean parseOneVCard() throws IOException, VCardException {// reset for this entire vCard.mCurrentEncoding = DEFAULT_ENCODING; //8BITmCurrentCharset = DEFAULT_CHARSET; //UTF-8boolean allowGarbage = false;if (!readBeginVCard(allowGarbage)) {return false;}for (VCardInterpreter interpreter : mInterpreterList) {interpreter.onEntryStarted(); //解析vCard中一个联系人开始标志}parseItems();//逐行解析for (VCardInterpreter interpreter : mInterpreterList) {interpreter.onEntryEnded(); //解析完vCard中一个联系人结束标志}return true;}

protected boolean readBeginVCard(boolean allowGarbage) throws IOException, VCardException {// TODO: use consructPropertyLine().String line;do {while (true) {line = getLine();if (line == null) {return false;} else if (line.trim().length() > 0) {break;}}final String[] strArray = line.split(":", 2);final int length = strArray.length;// Although vCard 2.1/3.0 specification does not allow lower cases,// we found vCard file emitted by some external vCard expoter have such// invalid Strings.// e.g. BEGIN:vCardif (length == 2 && strArray[0].trim().equalsIgnoreCase("BEGIN")&& strArray[1].trim().equalsIgnoreCase("VCARD")) { //判断是否是开头?return true;} else if (!allowGarbage) {throw new VCardException("Expected String \"BEGIN:VCARD\" did not come "+ "(Instead, \"" + line + "\" came)");}} while (allowGarbage);throw new VCardException("Reached where must not be reached.");}

/** item = [groups "."] name [params] ":" value CRLF / [groups "."] "ADR"* [params] ":" addressparts CRLF / [groups "."] "ORG" [params] ":" orgparts* CRLF / [groups "."] "N" [params] ":" nameparts CRLF / [groups "."]* "AGENT" [params] ":" vcard CRLF*/protected boolean parseItem() throws IOException, VCardException {// Reset for an item.mCurrentEncoding = DEFAULT_ENCODING;final String line = getNonEmptyLine();final VCardProperty propertyData = constructPropertyData(line);final String propertyNameUpper = propertyData.getName().toUpperCase();final String propertyRawValue = propertyData.getRawValue();if (propertyNameUpper.equals(VCardConstants.PROPERTY_BEGIN)) {if (propertyRawValue.equalsIgnoreCase("VCARD")) {handleNest();} else {throw new VCardException("Unknown BEGIN type: " + propertyRawValue);}} else if (propertyNameUpper.equals(VCardConstants.PROPERTY_END)) {if (propertyRawValue.equalsIgnoreCase("VCARD")) {return true; // Ended.} else {throw new VCardException("Unknown END type: " + propertyRawValue);}} else {parseItemInter(propertyData, propertyNameUpper);}return false;}

private void parseItemInter(VCardProperty property, String propertyNameUpper)throws IOException, VCardException {String propertyRawValue = property.getRawValue();if (propertyNameUpper.equals(VCardConstants.PROPERTY_AGENT)) {handleAgent(property);} else if (isValidPropertyName(propertyNameUpper)) {if (propertyNameUpper.equals(VCardConstants.PROPERTY_VERSION) &&!propertyRawValue.equals(getVersionString())) {throw new VCardVersionException("Incompatible version: " + propertyRawValue + " != " + getVersionString());}handlePropertyValue(property, propertyNameUpper); //解析里面每个属性} else {throw new VCardException("Unknown property name: \"" + propertyNameUpper + "\"");}}

推荐阅读
  • 深入解析Unity3D游戏开发中的音频播放技术
    在游戏开发中,音频播放是提升玩家沉浸感的关键因素之一。本文将探讨如何在Unity3D中高效地管理和播放不同类型的游戏音频,包括背景音乐和效果音效,并介绍实现这些功能的具体步骤。 ... [详细]
  • 春季职场跃迁指南:如何高效利用金三银四跳槽季
    随着每年的‘金三银四’跳槽高峰期的到来,许多职场人士都开始考虑是否应该寻找新的职业机会。本文将探讨如何制定有效的职业规划、撰写吸引人的简历以及掌握面试技巧,助您在这关键时期成功实现职场跃迁。 ... [详细]
  • 随着Linux操作系统的广泛使用,确保用户账户及系统安全变得尤为重要。用户密码的复杂性直接关系到系统的整体安全性。本文将详细介绍如何在CentOS服务器上自定义密码规则,以增强系统的安全性。 ... [详细]
  • 本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ... [详细]
  • 本文探讨了如何在 Spring MVC 框架下,通过自定义注解和拦截器机制来实现细粒度的权限管理功能。 ... [详细]
  • JavaScript 页面卸载事件详解 (onunload)
    当用户从页面离开时(如关闭页面或刷新页面),会触发 onunload 事件,此时可以执行预设的脚本。需要注意的是,不同的浏览器对 onunload 事件的支持程度可能有所不同。 ... [详细]
  • 默认情况下,Git 使用 Nano 编辑器进行提交信息的编辑,但如果您更喜欢使用 Vim,可以通过简单的配置更改来实现这一变化。本文将指导您如何通过修改全局配置文件来设置 Vim 作为默认的 Git 提交编辑器。 ... [详细]
  • 在Notepad++中配置Markdown语法高亮及实时预览功能
    本文详细介绍了如何在Notepad++中配置Markdown语法高亮和实时预览功能,包括必要的插件安装和设置步骤。 ... [详细]
  • 探讨如何在映射文件中处理重复的属性字段,以避免数据操作时出现错误。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
  • 在Android应用开发过程中,开发者经常遇到诸如CPU使用率过高、内存泄漏等问题。本文将介绍几种常用的命令及其应用场景,帮助开发者有效定位并解决问题。 ... [详细]
  • 为何Compose与Swarm之后仍有Kubernetes的诞生?
    探讨在已有Compose和Swarm的情况下,Kubernetes是如何以其独特的设计理念和技术优势脱颖而出,成为容器编排领域的领航者。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
author-avatar
右心1477
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有