android导入vCard联系人流程

来源:互联网 发布:lk在linux的哪一层 编辑:程序博客网 时间:2024/06/15 17:57

本博客基于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

    /**     * <code>     * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF     *         items *CRLF     *         "END" [ws] ":" [ws] "VCARD"     * </code>     * @return False when reaching end of file.     */    private boolean parseOneVCard() throws IOException, VCardException {        // reset for this entire vCard.        mCurrentEncoding = DEFAULT_ENCODING; //8BIT        mCurrentCharset = DEFAULT_CHARSET; //UTF-8        boolean 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:vCard            if (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 + "\"");        }    }