When I add a contact to my phone book, the sync Adapter onPerformSync() method gets triggered. But I am not able to figure out how to retrieve the newly added Contact details within that method. Please help me with some guidance and code snippets. Appreciate your help.
The contacts of your account are stored in the RawContacts table. The data (e.g. phone numbers, email addresses) is stored in the Data table (with RAW_CONTACT_ID pointing to the row _ID of that contact in the RawContacts table).
To detect new contacts, your sync adapter needs to maintain the SOURCE_ID field in the RawContacts table.
The documentation says about SOURCE_ID (in the columns of fields on top):
String that uniquely identifies this row to its source account. Typically it is set at the time the raw contact is inserted and never changed afterwards. The one notable exception is a new raw contact: it will have an account name and type (and possibly a data set), but no source id. This indicates to the sync adapter that a new contact needs to be created server-side and its ID stored in the corresponding SOURCE_ID field on the phone.
So your sync adapter should look for contacts that belong to your account type and have an empty SOURCE_ID. After the contact has been synced it must set the SOURCE_ID to a (non-empty) value that identifies the new contact.
When you sync a new contact from the server you need to set the SOURCE_ID when inserting the new contact on Android. Failure to do so, will result in duplicates (since the contact would be synced back to the server as a new contact on the next sync).
Related
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.
i want to store contacts on sql lite db. The problem was i am unable to identify the new contacts which are created.
Solution for this
I am using source_id to identify this newly added contact. Now the newly created contact source_id is null, here i can identify this.
Problem now: But how can i change this value when it is added in sql lite?
you should not touch the source_id value, it is used by the sync-adapter that synced that contact to your phone, and you might be corrupting the contacts DB by modifying it.
Instead, you can use the Contacts.CONTACT_LAST_UPDATED_TIMESTAMP:
You query for all contacts that have CONTACT_LAST_UPDATED_TIMESTAMP greater then the last time your app ran (that means they were either created or updated since you last updated your local SQLite DB)
Go over the list one-by-one, and see if their contact _ID is already in your DB or not, if it's not, it means this is a new contact - add it.
I am working on Contact Sync in Android and I have successfully done with First time Contact Sync.
Here is what I am doing.
1. Fetching all Contacts and Saving each contact in DB with Contact._ID
2. Fetching Names and Phone Numbers and saving in DB.
After that I am sending my contacts data to server so that server can be updated.
Now the problem is how can i check whether my particular contact is updated or not ?
I have implemented Broadcast Receiver so that my app can get intimated about the updation/Addition/Deletion of Contact. But I want to tract particular contact.
I found one solution which is Dirty Flag. It tells us about the contact whether its updated or not, Here is the reference link : http://developer.android.com/reference/android/provider/ContactsContract.RawContacts.html
But I am not able to use this Dirty Flag, Could someone please help me by implementing Dirty Flag.
Thanks in Advance !
The contacts should have the value ContactsContract.RawContacts.VERSION.
If you save this version on the server (or in a database in your app), you can determine if a contact has changed since it was last sent to the server.
You will get number of contacts updated after a particular time from contact data base using below query.
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP
,try to compare the last uploaded time to your server with this time .Hope then you will get the list of updated contacts after the successful upload to server.
check this
http://developer.android.com/reference/android/provider/ContactsContract.ContactsColumns.html#CONTACT_LAST_UPDATED_TIMESTAMP
When I did I used the ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP, but I had problem to figure out that it was is milliseconds, I was using a column to get the new files and it is in seconds (MediaStore.MediaColumns.DATE_ADDED) so pay attention to use the correct number.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
Cursor cursorNew;
cursorNew = contentResolver.query(uri,
null,
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + ">=?",
new String[]{lastUpdate},
null // Ordering
);
'lastUpdate' is a string with my timestamp
Another thing to pay attention is this Contact's column just appeared on API 18, the latest Jelly Bean version, so to solve this problem once and for all I just changed my gradle file.
As you said that you are storing Contacts._ID in your local database and fetching phone number and other info associated with contact from the Contacts db.
I would suggest you to store the data from the RawContacts table into your local mapping and check the entries associated with the raw_contact_id in the data table of contacts you will get all contacts easily.
To check the modified or deleted contacts
With the raw_contact_id present in your local table check mapping with the data table that if contact field associated with the raw_contact_id's version is changed or isDeleted field is changed (i.e; Contact is deleted from contact application)
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.