32

I am able to get a generic notification "that there was a change to the contacts DB", but I want to know the specific record that was inserted, updated, or deleted. Following is the code that gets registered and gets the onChange notification. Unfortunately, it is not specific which makes my processing exhaustive and inefficient.

Here is the code stub:

            if ((mNativeContactsObserver == null) && (mHandler == null)) {
            mHandler = new Handler(this.getMainLooper()) {
            };
            mNativeContactsObserver = new ContentObserver(mHandler) {
                @Override
                public void onChange(boolean selfChange) {
                    super.onChange(selfChange);

                    Bundle data = null;
                    Message message = mHandler.obtainMessage();
                    if (message != null) {
                        data = message.getData();
                        if (data != null) {
                            Logs.d(TAG, "Message = [" + message.toString() + "] data=[" + data.toString() + "]");
                            Logs.d(TAG, "Contents = [" + message.describeContents() + "]");
                        }
                    }

                    if (!selfChange) {
                        final Account accountListen = MySyncAdapter.lookupAccount(TAG, getApplicationContext(), getUserProfile().getAccountId(), AUTHORITY_MY_SYNC);
                        Logs.d(TAG, "onChange!? account: " + accountListen.name);
                        if (!ContentResolver.isSyncPending(account, ContactsContract.AUTHORITY) 
                                && (!ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY))) {
                            Bundle extras = new Bundle();
                            extras.putInt(MySyncAdapter.EXTRA_SYNC_TYPE, MySyncAdapter.REQUEST_SYNC_NATIVE_CHANGED);
                            ContentResolver.requestSync(accountListen, ContactsContract.AUTHORITY, extras);
                        } else {
                            Logs.w(TAG, "There is a pending sync.  This request is ignored.");
                        }
                    }
                }
            };
        }
        Uri uriContactsListen = ContactsContract.Contacts.CONTENT_URI.buildUpon().appendEncodedPath("#").build();
        Logs.i(TAG, "Register listening for native contacts changes. [" + uriContactsListen + "]");
        cr.registerContentObserver(uriContactsListen, true, mNativeContactsObserver);
mobibob
  • 8,670
  • 20
  • 82
  • 131

4 Answers4

5

Finally at least i am able to detect is this Update/Delete/Insert look at my OnChange method as below

 @Override
       public void onChange(boolean selfChange) {
           super.onChange(selfChange);
           Log.e("ContactChangeObserver", "onChange");

           // 0 Update , 1 Delete , 2 Added
 // Get count from phone contacts
           final int currentCount = contactDBOperaion.getContactsCountFromPhone();

 // Get count from your sqlite database
           int mContactCount= DbContacts.getInstance().getContactsCount();

           if (currentCount < mContactCount) {
               // DELETE HAPPEN.
               Log.e("Status", "Deletion");
               contactDBOperaion.SyncContacts(1);
           } else if (currentCount == mContactCount) {
               // UPDATE HAPPEN.
               contactDBOperaion.SyncContacts(0);
           } else {
               // INSERT HAPPEN.
               Log.e("Status", "Insertion");
               contactDBOperaion.SyncContacts(2);
           }
       }

When Update occurred i update all contacts

When Insert occurred i am inserting newly added row , after checking isExist in existing database

When Delete occurred not found solution yet

IshRoid
  • 3,696
  • 2
  • 26
  • 39
3

I have this code in my Application base class.

private ContentObserver contactObserver = new ContactObserver();

private class ContactObserver extends ContentObserver {

    public ContactObserver() {
        super(null);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        // Since onChange do not sent which user have been changed, you 
        // have to figure out how to match it with your data.
        // Note: Contact is  one of my classes.
        for (Contact contact : getContacts()) {
            if (!contact.isLinked())
                continue;

            String selection = ContactsContract.Data._ID + " = ?";
            String[] selectionArgs = new String[] { contact.getSystemId() };
            String[] projection = new String[] { ContactsContract.Data.DISPLAY_NAME };
            Cursor cursor = getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI, projection,
                    selection, selectionArgs, null);

            if (!cursor.moveToFirst())
                return;

            String name = cursor.getString(0);

            if (contact.getUsername().equalsIgnoreCase(name))
                continue;

            contact.setUserName(name);

        }
    }
}

Regarding about what you can put in projection check here

Unfortunately, it is not specific which makes my processing exhaustive and inefficient.

Would be great if into next Android releases also will send the contact id which had been just changed.

Hope this helps

Agna JirKon Rx
  • 2,321
  • 2
  • 29
  • 44
vsm
  • 3,373
  • 2
  • 25
  • 36
  • Can you help me i want to do when any new contact is added in the phonebook.then i would be notified and that new contact is send to the webservice on server... @ – Parin Parikh Jul 25 '15 at 12:56
  • To get more help from the whole community, please create a new question about your blockers, issues, concern, etc. – vsm Jul 29 '15 at 19:19
1

First of all, you have to register your contentObserver to receive change notification.

Do this by calling :

registerContentObserver();

Here's the specs : registerContetObserver

After than you'll want to notify all the listeners when a modification happens :

contentResolver.notifyChange();

Here's the specs for that one : notifyChange

Hope it helps ;)

Cheers !

oberthelot
  • 1,310
  • 1
  • 11
  • 23
  • oops! I didn't mention that I am doing the registration and getting the notification (i.e., from someone using the Android Address Book - Contacts App). What I am trying to get is the record of the contact so I can capture a reference in my data structure -- instead, what I have to do is search the entire address book for any changes. My thinking is that I may need to provide a more specific URI to observe, or there is a way to extract a key from the notification. Oooorrrr ... something completely different :) – mobibob May 18 '11 at 20:17
  • Ok. I don't have your full code structure here so it's a bit hard to figure all of it...But, can't you make each record register to an observer so that you get notified directly by the record when something has changed ;) – oberthelot May 20 '11 at 16:34
  • Actually all of the code is in the description. As for registering for each record is not practical. There could be 500+ aggregated contacts which would be double (or more) raw contacts to register for. That is why I was hoping that the URI can be specified to include the sub-query. For example, you can see that I tried ContactsContract.Contacts.CONTENT_URI.buildUpon().appendEncodedPath("#").build(); -- it did not have the effect I was hoping. – mobibob May 20 '11 at 17:29
  • Ok I see....Then maybe you could override the URI object....defining your own custom objects and embed the needed sub-query infos yourself... ;) – oberthelot May 24 '11 at 14:14
  • how does one override a URI? i would have to subclass the content provider of the URI. – mobibob May 25 '11 at 04:02
  • Yup ! Extends the ContentProvider class and define your own method implementation. Lookup that following example ;) http://thinkandroid.wordpress.com/2010/01/13/writing-your-own-contentprovider/ – oberthelot May 25 '11 at 19:23
-2

Use Loaders to query and display the list of contacts on your android device on your emulator. They automatically detect changes in the underlying data and reflect that on your UI.

Udit Jain
  • 1
  • 2