Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ContactsContract: Last Modified Time

I would like to clone Android Contacts Phone into my own SQLite db. In order to save time, the cloning should be triggered when the single contact is newly created or being updated in the Android system. Thus, I want to have "last modified time" of each contact.

For API level 18 or above, it seems that i would get the last modified time of a single person contact by using ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP. However for API Level 17 or below, it seems that there are some discussions before which suggested the use of "ContactsContract.RawContacts.VERSION" or "CONTACT_STATUS_TIMESTAMP".

For "CONTACT_STATUS_TIMESTAMP", it always returns ZERO or null. For "ContactsContract.RawContacts.VERSION", the version remained the same when i updated the photo, phone number or email of a person's contact.

Glad if someone would point out the mistakes i have made...

Reference: How to get the last modification date for Contacts list (Add/Delete/Modify)

like image 974
Antoine Murion Avatar asked Feb 06 '15 08:02

Antoine Murion


1 Answers

You can get notified when something changes using a ContentObserver. You will then need to retrieve the correct contact yourself. Of course that means having to have your app open when the contact changes or (more reasonably) running a background service.

In your service, create a content observer:

myObserver = new ContentObserver(new Handler()) {

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        if (!selfChange) {
            //Note: when this (older) callback is used you need to loop through 
            //and find the contact yourself (by using the dirty field)
        }
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        if (!selfChange) {
            //Note: if you receive a uri, it has contact id
            long rawContactId = ContentUris.parseId(uri);
            //Note: be careful which thread you are on here (dependent on handler)
        }
    }

};

//NOTE: Then you need to remember to register and unregister the observer.
//getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, myObserver);
//getContentResolver().unregisterContentObserver(myObserver);

Your suggestion to use dirty is not a good solution alone, as this only temporarily indicates that the aggregate contact (owner) should be updated because something in the RawContact changed. This means if the contact gets synced before your app gets opened, dirty is already false (0) again.

Also note that the documentation for the column mentions that it was added in API 18, so as you are aware, it is only below 18 that you need a workaround. so the first step is to make sure you are using the column when you can

if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.JELLY_BEAN_MR2) {
    //continue with existing code
} else {
    //use workaround (start service, or at least register observer)
}
like image 139
Nick Cardoso Avatar answered Nov 12 '22 04:11

Nick Cardoso