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)
Related
I have added multiple number under different categories for single user
like,
If I delete the one of the numbers , I want to detect which number got deleted from contact using ContactsContract content uris
The ContactsContract APIs can tell you that something changed in the Contacts table (via ContentObserver), but not what exactly.
If you want to detect the change that happened you'll need to keep and maintain a cache copy of all contacts in your app, you don't need to actual data itself, just the hash of each data row for each contact.
Then when you get your onChange called, you can go over all the data rows in the DB and compare them to the hashes you found the last time, and see if any were added/modified/deleted.
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.
In my application I want to show an option like Sync Contacts with App.
It should synchronize all the contacts with my app (Just like Facebook does when we go to the Contact tab of Find Friends page).
So when all the contacts are synchronized, I'll match the contacts with the server and the latter will return all the members which are in my contact list as well as those ones registered on the server but not in my friends list.
So can anyone help me?
How to synchronize the device contacts with my application?
For Syncing the contacts, you will require to get all the contacts from your contact list. Then you need to get the contacts from your server and compare contacts from both the places and choose the common ones.
Here is code for getting contacts from your Contact list.
public void getPhoneNumbers() {
String PHONE_NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{PHONE_NUMBER}, null, null, null);
ArrayList<String> phones = new ArrayList<>();
while (cur.moveToNext()) {
String number = cur.getString(0);
number = number.replaceAll(" ", "");
if (!phones.contains(number)) phones.add(number);
}
cur.close();
}
Since i don't know your server side code, i cannot help you in getting your contacts from the server but a simple query should do the job and matching the contacts will require for loop inside a for loop.
You should create sync adapter and inside that you should sync and observe content provider for contacts.
For detailed explanation you can take reference from below reference.
http://blogs.quovantis.com/syncing-contacts-with-an-android-application-2/
You should check official docs, it's pretty well explained there, and not very difficult. Then, if you still have some problems when implementing it, just come back here and ask for a concrete help with your code.
Hope it helps. Thanks.
All you need is a SyncAdapter, if you want to sync your contacts with your application. If you don't add it, then Contacts won't be shown. When you add the sync adapter you will also need an Authenticator.
So you mean you want to sync the local data with the server data?
Build the connection between local data and server data.
Load from server and check the local data./ Upload the local data to server and the server check the data and mark it.
It depends on you situation. Just like the relation. You can use the phone number to build the connection between two person. If Jack has registered, so your server has Jack's phone number and his id. When Mary register, the client upload mary's local contacts. Then the server check the data. Having found Jack's phone, that means Jack is Mary's friend. So when Jack or Mary load the 'Frinds', it shows the data.
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).
Let me try and clarify my intentions.
I'm developing an app that accesses to the Android contacts provider. I have already implemented a mechanism for pulling contacts from the contacts provider and storing the results in an SQLite table. Currently, when I query for the results of a contact's _ID, I can retrieve all the data for that contact, phone numbers, email addresses, etc.
However, in order to specify which of those my app should use on future occasions, I have to store the resulting contact data (e.g. CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.TYPE etc) in the SQL table.
This presents a problem if the data in the Android contacts provider has changed. One solution I have considered is to re-query the _ID and store the data that has changed. However, implementing such a solution requires gathering all data for that contact, making it difficult to determine the correct contact data to use.
My question is thus:
Is there a unique record key used in the Android Provider's contact data, in the same way as there is in the Provider's contact entry itself? A phone number or email address equivalent of Contact._ID?
Failing that, does the Android contacts provider store the last modified date and time? I'm hoping that if I can't reference the contact data in the provider, I can at least run a check to see if anything has changed since the contact was selected for use in the app, allowing my app to alert the user that the data has changed.
Yoi may use ContentObserver with the help of a service to monitor for contacts change or update.
for example-
extend contentObserver-
public class Contact_change extends ContentObserver
register contentobserver-
Contact_change changeObserver = new Contact_change();
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true,chageobserver);
By using this you can monitor for contact changes and update your database.
So while looking to see what was possible, I've come across some interesting findings by doing a localised record dump to my tablet.
I incorrectly referred to the phone _ID when asking my question. It's there, but it references individual records in any given contact. This might be useful, it might be exactly what I hoped, but it might also be a dead end.
So far, I've retrieved a contact using the Android Contacts Provider, which returns the contact's data including the fields that follow
ContactsContract.Contacts._ID
ContactsContract.Contacts.DISPLAY_NAME
After assigning the _ID to a String and using it in a query, I initially searched for the _ID in the ContactsContract.Data._ID field, which did not work as intended.
That's when I realised I was doing it wrong. I needed to apply the search to ContactsContract.Data.CONTACT_ID, which then retrieved all related data records for my selected contact.
Having corrected the error and re-ran my query, I found a series of records for the CONTACT_ID, each of which had its' own unique _ID (with the exception of photos and binary data, which all had a null reference to _ID instead.
Now the question is: Does this data reference change even if a phone number, email address or IM entry is modified, as opposed to deleted and re-created? I'll probably find out through further testing, but I wanted to ask if anyone had already tried this first.
Ultimately, I am hoping my internal SQL table can store only the CONTACT_ID and the _ID for each entry, relying on callbacks to the Android Provider to pull the relevant values. That way, I can be sure the data displayed in my app is up to date between the app and the stored contact data on the device.
Combined with the change notifier code provided here, I should be able to alert the user to any changes that may require action on their part.
Update:
More investigation reveals that the UID associated with a given contact entry is preserved through entry edits.
The UID is lost obviously on deletion, and in my brief testing, I have not found UID's being recycled. This solves a referential integrity issue for me at least, as that UID won't suddenly reference another record out of nowhere.
The upshot for anyone else wanting to reference individual entries in the Contacts Provider is that it's possible, and you can store only the _ID and still retrieve individual entries in the provider.