Friday, November 6, 2009

[android-developers] Re: Working with the new ContactContracts API

Hey Vettley,

I found there is a trigger in the contacts2.db database:

-- Describe RAW_CONTACTS_DELETED
CREATE TRIGGER raw_contacts_deleted BEFORE DELETE ON raw_contacts
BEGIN DELETE FROM data WHERE raw_contact_id=OLD._id; DELETE
FROM phone_lookup WHERE raw_contact_id=OLD._id; DELETE FROM
name_lookup WHERE raw_contact_id=OLD._id; DELETE FROM
agg_exceptions WHERE raw_contact_id1=OLD._id OR
raw_contact_id2=OLD._id; DELETE FROM contacts WHERE
_id=OLD.contact_id AND (SELECT COUNT(*) FROM
raw_contacts WHERE contact_id=OLD.contact_id )=1;
END

So as i think all you need is to delete a contact from raw_contacts.
And the trigger will delete all other data.


On Nov 5, 1:12 pm, Vettey <vettey....@gmail.com> wrote:
> 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+unsubscribe@googlegroups.com<android-developers%2Bunsubscribe@googlegroups.com><android-developers%2Bunsubs
> > > cribe@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+unsubscribe@googlegroups.com<android-developers%2Bunsubscribe@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+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment