Hi Dmitri,

Thanks for introducing the database structure and the sample on how to
insert contact with 2.0 API.

I'd like to know how to manage "Contacts", "RawContacts", and "Data"
table when deleting contacts.
Any better way to delete a contact with specific name from database?

- Vettey

On Nov 5, 10:47 am, Dmitri Plotnikov <dplotni...@google.com> wrote:
> Hi Jake,
>
> The database structure is actually extremely straightforward:
>
> "Contacts" represents an aggregated contact
> "RawContacts" represents a contact as it was inserted by the sync adapter.
>  RawContact has a CONTACT_ID field that binds it to a Contact.
> "Data" represents everything about a RawContact: emails, phone numbers,
> notes, birthday, high school graduation year, you name it.  Data has a
> RAW_CONTACT_ID field that binds it a  RawContact.  The other important field
> is MIMETYPE.  That's what determines the kind of data stored in a Data row.
>  Everything else is just convenience API.
>
> So here's the most common way of inserting a data row:
>
> values.put(Data.RAW_CONTACT_ID, rawContactId);
> values.put(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE);
> values.put(Note.NOTE, "Blah blah blah");
> resolver.insert(Data.CONTENT_URI, null, values);
>
> I hope this helps.
>
> - Dmitri
>
> On Wed, Nov 4, 2009 at 6:11 PM, jak. <koda...@gmail.com> wrote:
> > Thank you Dmitri,
>
> > Your response was very helpful. Along with that, and the sample you
> > posted on another thread about using both Contact Apis from one app,
> > I've gotten most of the way there. It is much appreciated.
>
> > I'm still however having some problems that I'm hard pressed to find a
> > solution for.
> > I'd be grateful if anyone could help me.
>
> > The biggest challenge I'm  having with this API is that it's hard for
> > me to picture how the tables are laid out so I know which URI to query
> > to get the parts of the contact that I'm interested in.
> > I found to get the email address for a contact I'm looking at I can
> > query the uri:ContactsContract.CommonDataKinds.Email.CONTENT_URI,
> > looking at rows of the contact id i'm interested in.
>
> > However to get the note from the same contact I can't use a similar
> > pattern, because there is no
> > ContactsContract.CommonDataKinds.Note.CONTENT_URI
> > The Note type exists in CommonDataKinds but it doesn't have an
> > associated CONTENT_URI.
>
> > I'm finding it very frustrating to use this API because every time I
> > go to try to pull out another piece of data from the contact, the
> > method to access it seems to change (as I can't find a consistent way
> > to get a given field from a contact). And the documentation never
> > describes how these keys, tables, and URIs are related. Basically the
> > ContactsContract documentation just gives you a giant list of Objects
> > containing constants that describe indexes into some database that is
> > basically a black box without some basic documentation.
>
> > I'm I the only one that finds this frustrating?
>
> > Thanks again for your help.
>
> > -Jake
>
> > On Nov 2, 5:24 pm, Dmitri Plotnikov <dplotni...@google.com> wrote:
> > > You can always delegate contact creation to the Contacts app using the
> > > ContactsContract.Intents.UI.Insert intent with extras. This will show the
> > > edit UI.
>
> > > If you want to explicitly create the contact by yourself, that's now a
> > bit
> > > tricky because Android 2.0 support multiple accounts.
>
> > > First of all, you will need to figure out which account you want to
> > create
> > > the contact in. Get a list of all available accounts from AccountManager:
>
> > > AccountManager am = AccountManager.get(getContext());
> > > Account[] accounts = am.getAccounts();
>
> > > Also, get a list of all sync adapters and find the ones that support
> > > contacts:
>
> > > SyncAdapterType[] syncs
> > > = ContentResolver.getContentService().getSyncAdapterTypes();
>
> > > for (SyncAdapterType sync : syncs) {
> > >      if (ContactsContract.AUTHORITY.equals(sync.authority) &&
> > > sync.supportsUploading()) {
> > >           contactAccountTypes.add(sync.accountType);
> > >      }
>
> > > }
>
> > > Now you have a list of all accounts and a list of account types that
> > support
> > > contacts.  So here's your account list:
>
> > > for (Account acct: accounts) {
> > >    if (contactAccountTypes.contains(acct.type)) {
> > >       contactAccounts.add(account);
> > >    }
>
> > > }
>
> > > If the contactAccounts list contains nothing - use accountType = null and
> > > accountName = null
> > > If it contains exactly one account, use it.
> > > If it contains multiple accounts, build a dialog and ask the user which
> > > account to use.
>
> > > From here on it gets easier.
>
> > > Let's start with a more traditional method.  Insert a raw contact first:
>
> > > ContentValues values = new ContentValues();
> > > values.put(RawContacts.ACCOUNT_TYPE, accountType);
> > > values.put(RawContacts.ACCOUNT_NAME, accountName);
> > > Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI,
> > > values);
> > > long rawContactId = ContentUris.parseId(rawContactUri);
>
> > > Then insert the name:
>
> > > values.clear();
> > > values.put(Data.RAW_CONTACT_ID, rawContactId);
> > > values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
> > > values.put(StructuredName.DISPLAY_NAME, "Some Body");
> > > getContentResolver().insert(Data.CONTENT_URI, values);
>
> > > You are done.
>
> > > Now here's a much better way to do the same.  Use the
> > > new ContentProviderOperation API, which will ensure that the raw contact
> > and
> > > its name are inserted at the same time.
>
> > > ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
> > > ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
> > >         .withValue(RawContacts.ACCOUNT_TYPE, accountType)
> > >         .withValue(RawContacts.ACCOUNT_NAME, accountName)
> > >         .build());
>
> > > ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
> > >         .withValueBackReference(Data.RAW_CONTACT_ID, 0)
> > >         .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
> > >         .withValue(StructuredName.DISPLAY_NAME, "Some Body")
> > >         .build());
>
> > > getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
>
> > > I hope this helps.
> > > - Dmitri
>
> > > On Mon, Nov 2, 2009 at 4:23 PM, jak. <koda...@gmail.com> wrote:
> > > > Hello,
>
> > > > I'm currently working on porting our Android app to 2.0 but I'm having
> > > > a rather hard time figuring out what is required to interact with the
> > > > new Contacts API.
> > > > I'm using reflection to decide whether the new API is available, if it
> > > > is I attempt to use the new features, otherwise I fall back to our old
> > > > methods.
>
> > > > However, I'm having a hard time finding analogs to the old
> > > > functionality in the new API.
> > > > For example in the past I was adding contacts to the database from an
> > > > external text source by creating a ContentValues object, filling it
> > > > with information on the contact and then adding it with a call to:
> > > > Contacts.People.createPersonInMyContactsGroup(...);
>
> > > > i.e.:
> > > > ...
>
> > > > ContentValues personValues = new ContentValues();
> > > > personValues.put(Contacts.People.NAME, "Some Body");
> > > > Uri personUri = Contacts.People.createPersonInMyContactsGroup
> > > > (curContext().getContentResolver(), personValues);
>
> > > > ...
> > > > How can I achieve the same goal in the new API?
>
> > > > I appreciate all the hard work going into improving the APIs but I
> > > > must admit I'm a bit frustrated by the lack of documentation and
> > > > examples.
> > > > I realize we have plenty of Javadocs on developer.android.com to
> > > > reference, but those only really show us what the new interfaces are.
> > > > I'm having a really hard time finding any discussion in terms of how
> > > > the new API is intended to be used.
>
> > > > Any help would be greatly appreciated!
> > > > Thanks!
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups "Android Developers" group.
> > > > To post to this group, send email to
> > android-developers@googlegroups.com
> > > > To unsubscribe from this group, send email to
> > > > android-developers+unsubscr...@googlegroups.com<android-developers%2bunsubscr...@googlegroups.com><android-developers%2Bunsubs
> > cr...@googlegroups.com>
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/android-developers?hl=en
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Android Developers" group.
> > To post to this group, send email to android-developers@googlegroups.com
> > To unsubscribe from this group, send email to
> > android-developers+unsubscr...@googlegroups.com<android-developers%2bunsubscr...@googlegroups.com>
> > For more options, visit this group at
> >http://groups.google.com/group/android-developers?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to