I was just going through the ContactsContract API in Android and I am stuck with the overview part of it.
Then I got this link https://developer.android.com/guide/topics/providers/contacts-provider but I am still having difficulty understanding Contacts in android.
Can any of you provide me with links or explanation what is a Contact is, in Android perspective, for me it is just the number we save on our phone but I now know it is some thing more. Please explain to me (or provide link to a simpler or clearer explanation which is not the android documentation itself) what these three tables contain as I am unable to understand it from the docs.
ContactsContract.Contacts table
ContactsContract.RawContacts table
ContactsContract.Data table
Thanks in advance.
As I wrote in many answers before in various phrasing:
The Contacts DB is organized in three main tables:
Contacts - each entry represents one contact, and groups together one or more RawContacts
RawContacts - each entry represents data about a contact that was synced in by some SyncAdapter (e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entries
Data - The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a single RawContact
Usually what happens is that an app (e.g. Google, Whatsapp, Linkedin) that wishes to create a new contact will create a new row in the RawContacts table that will usually contain just a name, and then use that row's _ID to add rows into the Data table for phones, emails, addresses, photos, etc.
Android will then either create a new row in Contacts to assign to that new raw-contact (i.e. a new contact was created), or if it decides that raw-contact contain similar enough information to an existing contact, will have an existing contact row assigned to that new raw-contact (i.e. the new information will be added to an existing contact).
The "assigning" part is done like this - each row in Data has a column RAW_CONTACT_ID which tells the contacts app which raw-contact does this info belong to, and each row in RawContacts has a column CONTACT_ID which tells the contacts app which row in Contacts this raw-contact belong-to.
So to get information on contact with _ID = 1234, you could first query info from Contacts where _ID = 1234, then query more info from RawContacts where CONTACT_ID = 1234, then query for more info from Data where RAW_CONTACT_ID IN (X) where X is the list of raw-contact ids you found previously.
The Data table also has a CONTACT_ID column, so you can basically skip the RawContact query, and get all the data (phones, emails, etc.) directly from the contact-id.
Hope that's clear.
Related
How do I query all contacts matching a certain criteria on Android?
Let´s say, I want to have all contacts, which have a name, a phone number, but no profile picture.
As I understand the SQL thing, I need some kind of selection, which is passed to my query, but how would it exactly look in the example above?
I´m asking, because I´m currently running an app which first queries all contacts and after that I iterate through it and filter it, which seems much less performant then querying directly the right contacts
You are correct in the sense that contacts are stored in a SQLite database, but they are accessed via the Contacts Content Provider.
The Contacts Content Provider is organized in a three table fashion. At the bottom of the data structure lies the Data table. Here you will find all data that pertains to a specific RawContact (will discuss shortly). The Data table stores information like phone numbers, emails, addresses,etc. It does so by using MIME name value pairs defined on the mimetypes database. Up one level is the RawContacts database. Here all the information that pertains to the same account (i.e. Contact John Doe may have a twitter and Facebook account). In short, the RawContacts table keeps track of Data MIME types that pertain to the same person so there is no need to store the same information multiple times for different accounts. At the top of the data structure you have the Contacts table that groups all the information for a single person. It is basically a way of unifying all account information into one contact. Think of this contacts as you regularly would.
You should take a look at the Loader class which will allow you to perform queries on a background Thread. If you use this class once you implement the Loader callback for the Cursor, you will create a CursorLoader. One of its constructors parameter is
A typical MySQL where clause where you can specify the constraints you want to include as part of your query.
Here you would find a guide to Loaders to query a database.
I'm writing a class that handles Android contact information and after some struggle, I've written a function that retrieves all information about the user's contacts, including all phone numbers, email addresses, postal addresses, etc. However, I still don't understand how this information is stored in the phone, so I'm hoping someone can give me some insight on this.
So, a user can have multiple phone numbers, multiple email addresses, etc. For contacts you have ContactsContract.Contacts.CONTENT_URI for the table containing all contacts and for phone numbers you have ContactsContract.CommonDataKinds.Phone.CONTENT_URI. But then there is also ContactsContract.RawContacts.CONTENT_URI, which is supposed to contain all the data for your contacts, I think. My assumption is that in the Contacts table, contact ID is the unique identifier for separate rows, whereas for the Phone table, phone number is the unique row identifier. If RawContacts contains all columns of the ContactsContract classes, then there would be no unique identifier for each row, since each contact might be assigned multiple phone numbers, multiple email addresses, etc. In other words, I don't understand how such a table is structured.
So my question is this: Are the various tables containing contact information--Contacts, Phone, Email, StructuredPostal, etc.--completely separate or is the information for each of those tables extracted from the larger RawContacts table? Or am I misunderstand what RawContacts is? Since the class I am writing will help move contacts from the phone contact list into a separate database, knowing this information will help me understand whether I should store the information in multiple databases or just one (similar to how I described the RawContacts database above).
The android API Guide on Contacts Provider gives a nice description of how the Contacts tables are stored (it's a bit convoluted, allowing the merge of many contacts)
picture of data hierarchy
your Q:
So my question is this: Are the various tables containing contact
information--Contacts, Phone, Email, StructuredPostal,
etc.--completely separate or is the information for each of those
tables extracted from the larger RawContacts table?
Looking over the docs again (I've not coded against these tables, only read docs), the Phone, Email... tables appear to be separate. However, the information looks to be stored in both tables, the contact and also in the RawContacts.
According to the official documentation, when there is a new RawContact inserted to the contact's database, the system initiates the mechanism of aggregation to find a Contact which the inserted RawContact will be aggregated with.
In the case of presence similar contact information in the contacts database the inserted RawContact will be aggregated with the existing Contact and in the case of absence of such information the system will create a new Contact and will aggregate the inserted RawContact with it.
I have already looked through the ContactsContract.AggregationExceptions and ContactsContract.Contacts.AggregationSuggestions but haven't found any information which could help me to figure out how to forcibly tell the system to create a new Contact when I insert a new RawContact in my application.
If anybody knows how to do that, I would be glad to get your suggestions.
Thanks
To create a new contact, insert values for ACCOUNT_NAME and ACCOUNT_TYPE in ContactsContract.RawContacts and get the new row's _ID. Then use this _ID to fill in RAW_CONTACT_ID when inserting contact data to ContactsContract.Data.
The new _ID in ContactsContract.RawContacts is not supposed to be already present, hence no aggregation until corresponding data is inserted/updated in ContactsContract.Data.
ContactsContract.Contacts is just an auto aggregated table to ease data query. You are not supposed to alter it directly.
I've got an app in the market which stores details against contacts by using a contact picker. When I've returned from the contact picker I had been using the following to obtain the contact:
cursor.getColumnIndex(ContactsContract.Contacts._ID)
I've found that using this is ok until somebody flashes a new rom or gets a new phone and then all the ID's have changed.
I've looked at the android documentation and I've seen references to using ContactsContract.Contacts.LOOKUP_KEY, but the description confuses me "An opaque value that contains hints on how to find the contact if its row id changed as a result of a sync or aggregation."
So what should I be using to store the contact ID?
Lookup Key is the correct reference for contacts.
Contacts Provider / Contacts:
The ContactsContract.Contacts table also has the column LOOKUP_KEY
that is a "permanent" link to the contact row. Because the Contacts
Provider maintains contacts automatically, it may change a contact
row's _ID value in response to an aggregation or sync. Even If this
happens, the content URI CONTENT_LOOKUP_URI combined with contact's
LOOKUP_KEY will still point to the contact row, so you can use
LOOKUP_KEY to maintain links to "favorite" contacts, and so forth.
This column has its own format that is unrelated to the format of the
_ID column.
Add a type of contact (RawContact), sometimes they are combined with telephone contacts LOOKUP_KEY. It turns out that some contacts entries contain two RawContact'a one integrated phone, one of mine. The question is how to find out whether there is a Contacts RawContract my type? Or learn to RawContacts to which he refers Contacts?
Match the "_id" of the contact to the "contact_id" of the raw contact.