Loading core/java/android/pim/vcard/VCardComposer.java +36 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.EntityIterator; import android.content.Entity.NamedContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.RemoteException; import android.provider.CallLog; import android.provider.CallLog.Calls; Loading Loading @@ -81,7 +82,7 @@ import java.util.Map; public class VCardComposer { private static final String LOG_TAG = "vcard.VCardComposer"; private final static String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET; private static final String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET; public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = "Failed to get database information"; Loading @@ -94,6 +95,14 @@ public class VCardComposer { public static final String NO_ERROR = "No error"; private static final Uri sDataRequestUri; static { Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon(); builder.appendQueryParameter(Data.FOR_EXPORT_ONLY, "1"); sDataRequestUri = builder.build(); } public static interface OneEntryHandler { public boolean onInit(Context context); Loading @@ -116,7 +125,7 @@ public class VCardComposer { @SuppressWarnings("hiding") private static final String LOG_TAG = "vcard.VCardComposer.HandlerForOutputStream"; private OutputStream mOutputStream; // mWriter will close this. final private OutputStream mOutputStream; // mWriter will close this. private Writer mWriter; private boolean mOnTerminateIsCalled = false; Loading Loading @@ -301,8 +310,8 @@ public class VCardComposer { private boolean mIsCallLogComposer = false; private static final String[] sRawContactsProjection = new String[] { RawContacts._ID, private static final String[] sContactsProjection = new String[] { Contacts._ID, }; /** The projection to use when querying the call log table */ Loading Loading @@ -442,7 +451,7 @@ public class VCardComposer { mCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, sCallLogProjection, selection, selectionArgs, null); } else { mCursor = mContentResolver.query(RawContacts.CONTENT_URI, sRawContactsProjection, mCursor = mContentResolver.query(Contacts.CONTENT_URI, sContactsProjection, selection, selectionArgs, null); } Loading @@ -451,7 +460,7 @@ public class VCardComposer { return false; } if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) { if (getCount() == 0 || !mCursor.moveToFirst()) { try { mCursor.close(); } catch (SQLiteException e) { Loading Loading @@ -604,23 +613,19 @@ public class VCardComposer { } private String createOneEntryInternal(final String contactId) { final StringBuilder builder = new StringBuilder(); appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD); if (mIsV30) { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30); } else { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21); } final Map<String, List<ContentValues>> contentValuesListMap = new HashMap<String, List<ContentValues>>(); final String selection = Data.RAW_CONTACT_ID + "=?"; final String selection = Data.CONTACT_ID + "=?"; final String[] selectionArgs = new String[] {contactId}; // The resolver may return the entity iterator with no data. It is possiible. // e.g. If all the data in the contact of the given contact id are not exportable ones, // they are hidden from the view of this method, though contact id itself exists. boolean dataExists = false; EntityIterator entityIterator = null; try { entityIterator = mContentResolver.queryEntities( RawContacts.CONTENT_URI, selection, selectionArgs, null); sDataRequestUri, selection, selectionArgs, null); dataExists = entityIterator.hasNext(); while (entityIterator.hasNext()) { Entity entity = entityIterator.next(); for (NamedContentValues namedContentValues : entity Loading Loading @@ -648,7 +653,18 @@ public class VCardComposer { } } // TODO: consolidate order? (low priority) if (!dataExists) { return ""; } final StringBuilder builder = new StringBuilder(); appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD); if (mIsV30) { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30); } else { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21); } appendStructuredNames(builder, contentValuesListMap); appendNickNames(builder, contentValuesListMap); appendPhones(builder, contentValuesListMap); Loading @@ -660,7 +676,7 @@ public class VCardComposer { appendOrganizations(builder, contentValuesListMap); appendPhotos(builder, contentValuesListMap); appendNotes(builder, contentValuesListMap); // TODO: GroupMembership... What? // TODO: GroupMembership if (mIsDoCoMo) { appendVCardLine(builder, VCARD_PROPERTY_X_CLASS, VCARD_DATA_PUBLIC); Loading core/java/android/provider/ContactsContract.java +16 −0 Original line number Diff line number Diff line Loading @@ -804,6 +804,22 @@ public final class ContactsContract { */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; /** * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward * Data.CONTENT_URI contains only exportable data. * * This flag is useful (currently) only for vCard exporter in Contacts app, which * needs to exclude "un-exportable" data from available data to export, while * Contacts app itself has priviledge to access all data including "un-expotable" * ones and providers return all of them regardless of the callers' intention. * <P>Type: INTEGER</p> * * @hide Maybe available only in Eclair and not really ready for public use. * TODO: remove, or implement this feature completely. As of now (Eclair), * we only use this flag in queryEntities(), not query(). */ public static final String FOR_EXPORT_ONLY = "for_export_only"; /** * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} Loading Loading
core/java/android/pim/vcard/VCardComposer.java +36 −20 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.EntityIterator; import android.content.Entity.NamedContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.RemoteException; import android.provider.CallLog; import android.provider.CallLog.Calls; Loading Loading @@ -81,7 +82,7 @@ import java.util.Map; public class VCardComposer { private static final String LOG_TAG = "vcard.VCardComposer"; private final static String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET; private static final String DEFAULT_EMAIL_TYPE = Constants.ATTR_TYPE_INTERNET; public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = "Failed to get database information"; Loading @@ -94,6 +95,14 @@ public class VCardComposer { public static final String NO_ERROR = "No error"; private static final Uri sDataRequestUri; static { Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon(); builder.appendQueryParameter(Data.FOR_EXPORT_ONLY, "1"); sDataRequestUri = builder.build(); } public static interface OneEntryHandler { public boolean onInit(Context context); Loading @@ -116,7 +125,7 @@ public class VCardComposer { @SuppressWarnings("hiding") private static final String LOG_TAG = "vcard.VCardComposer.HandlerForOutputStream"; private OutputStream mOutputStream; // mWriter will close this. final private OutputStream mOutputStream; // mWriter will close this. private Writer mWriter; private boolean mOnTerminateIsCalled = false; Loading Loading @@ -301,8 +310,8 @@ public class VCardComposer { private boolean mIsCallLogComposer = false; private static final String[] sRawContactsProjection = new String[] { RawContacts._ID, private static final String[] sContactsProjection = new String[] { Contacts._ID, }; /** The projection to use when querying the call log table */ Loading Loading @@ -442,7 +451,7 @@ public class VCardComposer { mCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, sCallLogProjection, selection, selectionArgs, null); } else { mCursor = mContentResolver.query(RawContacts.CONTENT_URI, sRawContactsProjection, mCursor = mContentResolver.query(Contacts.CONTENT_URI, sContactsProjection, selection, selectionArgs, null); } Loading @@ -451,7 +460,7 @@ public class VCardComposer { return false; } if (mCursor.getCount() == 0 || !mCursor.moveToFirst()) { if (getCount() == 0 || !mCursor.moveToFirst()) { try { mCursor.close(); } catch (SQLiteException e) { Loading Loading @@ -604,23 +613,19 @@ public class VCardComposer { } private String createOneEntryInternal(final String contactId) { final StringBuilder builder = new StringBuilder(); appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD); if (mIsV30) { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30); } else { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21); } final Map<String, List<ContentValues>> contentValuesListMap = new HashMap<String, List<ContentValues>>(); final String selection = Data.RAW_CONTACT_ID + "=?"; final String selection = Data.CONTACT_ID + "=?"; final String[] selectionArgs = new String[] {contactId}; // The resolver may return the entity iterator with no data. It is possiible. // e.g. If all the data in the contact of the given contact id are not exportable ones, // they are hidden from the view of this method, though contact id itself exists. boolean dataExists = false; EntityIterator entityIterator = null; try { entityIterator = mContentResolver.queryEntities( RawContacts.CONTENT_URI, selection, selectionArgs, null); sDataRequestUri, selection, selectionArgs, null); dataExists = entityIterator.hasNext(); while (entityIterator.hasNext()) { Entity entity = entityIterator.next(); for (NamedContentValues namedContentValues : entity Loading Loading @@ -648,7 +653,18 @@ public class VCardComposer { } } // TODO: consolidate order? (low priority) if (!dataExists) { return ""; } final StringBuilder builder = new StringBuilder(); appendVCardLine(builder, VCARD_PROPERTY_BEGIN, VCARD_DATA_VCARD); if (mIsV30) { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V30); } else { appendVCardLine(builder, VCARD_PROPERTY_VERSION, Constants.VERSION_V21); } appendStructuredNames(builder, contentValuesListMap); appendNickNames(builder, contentValuesListMap); appendPhones(builder, contentValuesListMap); Loading @@ -660,7 +676,7 @@ public class VCardComposer { appendOrganizations(builder, contentValuesListMap); appendPhotos(builder, contentValuesListMap); appendNotes(builder, contentValuesListMap); // TODO: GroupMembership... What? // TODO: GroupMembership if (mIsDoCoMo) { appendVCardLine(builder, VCARD_PROPERTY_X_CLASS, VCARD_DATA_PUBLIC); Loading
core/java/android/provider/ContactsContract.java +16 −0 Original line number Diff line number Diff line Loading @@ -804,6 +804,22 @@ public final class ContactsContract { */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; /** * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward * Data.CONTENT_URI contains only exportable data. * * This flag is useful (currently) only for vCard exporter in Contacts app, which * needs to exclude "un-exportable" data from available data to export, while * Contacts app itself has priviledge to access all data including "un-expotable" * ones and providers return all of them regardless of the callers' intention. * <P>Type: INTEGER</p> * * @hide Maybe available only in Eclair and not really ready for public use. * TODO: remove, or implement this feature completely. As of now (Eclair), * we only use this flag in queryEntities(), not query(). */ public static final String FOR_EXPORT_ONLY = "for_export_only"; /** * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} Loading