Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4ddea76 authored by Daisuke Miyakawa's avatar Daisuke Miyakawa
Browse files

Refactor VCard handling code, phase 2, 3, 4, 5

Phase 2
Make VCard Importer use Data structures in ContactsContract instead of
using old Conatacts structure.

Phase 3
Developed VCardComposer, which was originally in Contacts package, but
now in base/core/java. Also made it use queryEntries() as per jsharkey's
suggestion.

Phase 4
Added VCardUtils and moved some common methods to it, some of which should be
in public API, but hidden for now.

Phase 5
Made VCardComposer emits (almost) valid vCard 3.0 data.
Confirmed with vCard data emitted by Mac.

Related issue:
1784580, 1728351, 1967349

Note:
Probable next step:
- Add "fast parse" mode in VCradBuilder, in which, VCardBuilder skip parsing the value of
each property. It will make the parsing faster.
-- Note that parsing the parameters of each entry cannot be skipped, since it may contains
the information about Encoding of the property. In other words, if the line is
in Quoted-Printable format, the next line may be the part of the property, not a
separated property, which should be parsed accordingly.

- Needs test
parent 2e951b55
Loading
Loading
Loading
Loading
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.pim.vcard;

/**
 * Constants used in both composer and parser.
 */
/* package */ class Constants {

    public static final String ATTR_TYPE = "TYPE";
    
    public static final String VERSION_V21 = "2.1";
    public static final String VERSION_V30 = "3.0";
    
    // Properties both the current (as of 2009-08-17) ContactsStruct and de-fact vCard extensions
    // shown in http://en.wikipedia.org/wiki/VCard support are defined here.
    public static final String PROPERTY_X_AIM = "X-AIM";
    public static final String PROPERTY_X_MSN = "X-MSN";
    public static final String PROPERTY_X_YAHOO = "X-YAHOO";
    public static final String PROPERTY_X_ICQ = "X-ICQ";
    public static final String PROPERTY_X_JABBER = "X-JABBER";
    public static final String PROPERTY_X_GOOGLE_TALK = "X-GOOGLE-TALK";
    public static final String PROPERTY_X_SKYPE_USERNAME = "X-SKYPE-USERNAME";
    // Phone number for Skype, available as usual phone.
    public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER";
    // Some device emits this "X-" attribute, which is specifically invalid but should be
    // always properly accepted, and emitted in some special case (for that device/application).
    public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
    
    // How more than one TYPE fields are expressed is different between vCard 2.1 and vCard 3.0
    //
    // e.g.
    // 1) Probably valid in both vCard 2.1 and vCard 3.0: "ADR;TYPE=DOM;TYPE=HOME:..." 
    // 2) Valid in vCard 2.1 but not in vCard 3.0: "ADR;DOM;HOME:..."
    // 3) Valid in vCard 3.0 but not in vCard 2.1: "ADR;TYPE=DOM,HOME:..."
    //
    // 2) has been the default of VCard exporter/importer in Android, but we can see the other
    // formats in vCard data emitted by the other softwares/devices.
    //
    // So we are currently not sure which type is the best; probably we will have to change which
    // type should be emitted depending on the device.
    public static final String ATTR_TYPE_HOME = "HOME";
    public static final String ATTR_TYPE_WORK = "WORK";
    public static final String ATTR_TYPE_FAX = "FAX";
    public static final String ATTR_TYPE_CELL = "CELL";
    public static final String ATTR_TYPE_VOICE = "VOICE";
    public static final String ATTR_TYPE_INTERNET = "INTERNET";

    public static final String ATTR_TYPE_PREF = "PREF";

    // Phone types valid in vCard and known to ContactsContract, but not so common.
    public static final String ATTR_TYPE_CAR = "CAR";
    public static final String ATTR_TYPE_ISDN = "ISDN";
    public static final String ATTR_TYPE_PAGER = "PAGER";

    // Phone types existing in vCard 2.1 but not known to ContactsContract.
    // TODO: should make parser make these TYPE_CUSTOM.
    public static final String ATTR_TYPE_MODEM = "MODEM";
    public static final String ATTR_TYPE_MSG = "MSG";
    public static final String ATTR_TYPE_BBS = "BBS";
    public static final String ATTR_TYPE_VIDEO = "VIDEO";

    // Phone types existing in the current Contacts structure but not valid in vCard (at least 2.1)
    // These types are encoded to "X-" attributes when composing vCard for now.
    // Parser passes these even if "X-" is added to the attribute.
    public static final String ATTR_TYPE_PHONE_EXTRA_OTHER = "OTHER";
    public static final String ATTR_TYPE_PHONE_EXTRA_CALLBACK = "CALLBACK";
    // TODO: may be "TYPE=COMPANY,PREF", not "COMPANY-MAIN".
    public static final String ATTR_TYPE_PHONE_EXTRA_COMPANY_MAIN = "COMPANY-MAIN";
    public static final String ATTR_TYPE_PHONE_EXTRA_RADIO = "RADIO";
    public static final String ATTR_TYPE_PHONE_EXTRA_TELEX = "TELEX";
    public static final String ATTR_TYPE_PHONE_EXTRA_TTY_TDD = "TTY-TDD";
    public static final String ATTR_TYPE_PHONE_EXTRA_ASSISTANT = "ASSISTANT";

    // DoCoMo specific attribute. Used with "SOUND" property, which is alternate of SORT-STRING in
    // vCard 3.0.
    public static final String ATTR_TYPE_X_IRMC_N = "X-IRMC-N";

    private Constants() {
    }
}
 No newline at end of file
+708 −730

File changed.

Preview size limit exceeded, changes collapsed.

+7 −47
Original line number Diff line number Diff line
@@ -15,11 +15,7 @@
 */
package android.pim.vcard;

import android.content.AbstractSyncableContentProvider;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.IContentProvider;
import android.provider.Contacts;
import android.util.Log;

/**
@@ -29,60 +25,24 @@ public class EntryCommitter implements EntryHandler {
    public static String LOG_TAG = "vcard.EntryComitter";

    private ContentResolver mContentResolver;
    
    // Ideally, this should be ContactsProvider but it seems Class loader cannot find it,
    // even when it is subclass of ContactsProvider...
    private AbstractSyncableContentProvider mProvider;
    private long mMyContactsGroupId;
    
    private long mTimeToCommit;
    
    public EntryCommitter(ContentResolver resolver) {
        mContentResolver = resolver;
        
        tryGetOriginalProvider();
    }

    public void onFinal() {
        if (VCardConfig.showPerformanceLog()) {
            Log.d(LOG_TAG,
                    String.format("time to commit entries: %ld ms", mTimeToCommit));
    public void onParsingStart() {
    }
    }
    
    private void tryGetOriginalProvider() {
        final ContentResolver resolver = mContentResolver;
    
        if ((mMyContactsGroupId = Contacts.People.tryGetMyContactsGroupId(resolver)) == 0) {
            Log.e(LOG_TAG, "Could not get group id of MyContact");
            return;
        }

        IContentProvider iProviderForName = resolver.acquireProvider(Contacts.CONTENT_URI);
        ContentProvider contentProvider =
            ContentProvider.coerceToLocalContentProvider(iProviderForName);
        if (contentProvider == null) {
            Log.e(LOG_TAG, "Fail to get ContentProvider object.");
            return;
        }
        
        if (!(contentProvider instanceof AbstractSyncableContentProvider)) {
            Log.e(LOG_TAG,
                    "Acquired ContentProvider object is not AbstractSyncableContentProvider.");
            return;
    public void onParsingEnd() {
        if (VCardConfig.showPerformanceLog()) {
            Log.d(LOG_TAG, String.format("time to commit entries: %d ms", mTimeToCommit));
        }
        
        mProvider = (AbstractSyncableContentProvider)contentProvider; 
    }

    public void onEntryCreated(final ContactStruct contactStruct) {
        long start = System.currentTimeMillis();
        if (mProvider != null) {
            contactStruct.pushIntoAbstractSyncableContentProvider(
                    mProvider, mMyContactsGroupId);
        } else {
        contactStruct.pushIntoContentResolver(mContentResolver);
        }
        mTimeToCommit += System.currentTimeMillis() - start;
    }
}
 No newline at end of file
+9 −4
Original line number Diff line number Diff line
@@ -16,18 +16,23 @@
package android.pim.vcard;

/**
 * Unlike VCardBuilderBase, this (and VCardDataBuilder) assumes
 * Unlike {@link VCardBuilder}, this (and {@link VCardDataBuilder}) assumes
 * "each VCard entry should be correctly parsed and passed to each EntryHandler object",
 */
public interface EntryHandler {
    /**
     * Able to be use this method for showing performance log, etc.
     * TODO: better name?
     * Called when the parsing started.
     */
    public void onFinal();
    public void onParsingStart();

    /**
     * The method called when one VCard entry is successfully created
     */
    public void onEntryCreated(final ContactStruct entry);

    /**
     * Called when the parsing ended.
     * Able to be use this method for showing performance log, etc.
     */
    public void onParsingEnd();
}
+1433 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading