How can I observe for any changes to a contact - android

In Android, how can I observe for any changes made to a contact?
I know I need to register for a content observer? But what should be the URI for passing to the registerContentObserver function?
Here is what I tried:
registerContentObserver( ContentUris.withAppendedId(People.CONTENT_URI, personId), true, myContactsObserver);
But I don't get notified when I change the phone number of the contact.
Thank you for any pointers.

More information would make it easier to figure out.
I wonder if it's because your Activity is no longer running when the contact changes. If you're changing the contact through the built-in Contacts application, that would imply that your activity is no longer at the top of the stack, so there's no guarantee that it's still resident.
You might try registering the contact observer in a service that you explicitly start and stop.

Related

Prevent ContentObserver from getting a "specific" change on URI

I have an app that allow users to edit the ContractsContacts DB.
When a user edits the ContractsContacts DB using the functions of my app, I don't want that my ContentObserver is aware of that changes.
I want my ContentObserver to be aware only of changes generated from other apps. For example when users edit ContractsContacts DB by using the mobile apps.
So, my question is: is there a way to tell the ContentObserver "hey, don't listen to this change, because I'm aware of it, dont call your onChange() method":
The only solution I found is:
unregister the ContentObserver before starting the "edit function" of my app
register again the ContentObserver after my function did all its work.
Thank you
This is not your ContentProvider, and so you cannot prevent Android from updating registered observers. Your observer is nothing special to Android.
So, in addition to your unregister-modify-register flow, you could tell your observer to ignore the next update (have it track that in a boolean or something), then modify the data. The observer would skip whatever work it normally does when that boolean is set, just flipping it to false to pick up future changes.
Both of these suffer from race conditions (you and another app modifying the provider at the same time).
Ideally IMHO, you modify whatever logic is being triggered by the observer to live with triggers coming from your own updates, so that all changes of the data are treated equally, whether coming from your app or not.

Android SQLite adding contacts 'dynamically'

In my Android app, an Activity performs a query to get the contacts on the phone and stores them into a sqlite database. For now, this is performed only once during the first launch of the Activity because that operation takes about two seconds to execute (which is actually a lot of time)
However that workaround comes with an issue: if the phone user adds some contact my app will never be able to get them. Then, I was wondering if it was possible for my app to ´listen ´ for that event and add the contact in the database when it occurs.
Is such a thing possible?
You can do it by using ContentObserver.
You have to simply
Implement a subclass of ContentObserver
you have to register your ContentObserver to listen the change.
For more detail how to do it you can follow this article Use Android’s ContentObserver in Your Code to Listen to Data Changes

How to determine where a contact was added?

I have been struggling with an approach to this problem for some time now. There is no Intent action fired off when a contact is added (as far as I know). What are my options to solve this issue?
Here are some ideas I have been playing with:
Firstly I kept a record of user locations with timestamps and periodically scan the Contacts DB and add new entries to my own DB with a timestamp. I could then compare these and try to find a decent match. I do not like this approach as it is very error prone.
Recently I've been looking at a ContentObserver for the Contacts DB, but I am not sure how to set this up so that it will constantly be observing, and not just when my app is in focus. Perhaps in a service? The documentation isn't clear to me about the life-cycle of a content observer, i.e does it die after the service/activity that registered it dies?
So really what I want is a seamless way to record where and when a user adds a contact when my app is installed on the device. It is not enough that the app should be in focus/running.
The second idea of yours is the correct one. The observer needs to be in a service as you had rightly guessed. Register the observer in the onCreate(). You will use contentProvider in the onChange of the contentObserver. You will need to maintain time when you last read the database using shared preferences. Note the changes of entries after the time stored in shared preferences. Now update the time of shared preferences to current time. Also unregister the content observer in onDestroy().

Android SQLite DB notifications

I am writing an Android app that needs to be notified whenever a given SQLite database changes (any new row added, deleted or updated).
Is there any programmatic way to listen to these notifications ?
Is writing DB triggers for each table the only way ?
SQLite provides Data Change Notification Callbacks. I don't think that Android exposes them directly but it does have for example CursorAdapter which provides some change notifications.
As thinksteep asked however, do you expect your DB to be changed outside the scope of your own application?
You can register an observer class such as DataSetObserver
Then whenever you change something you can call cursor.registerDataSetObserver(..) to register observe changes.
It's not well documented but I'm sure that there are some examples out there
You can use also use the getContentResolver().registerContentObserver but unfortunately it doesn't tell you what kind of change was made, it could be a delete, insert or update.
If you control the ContentProvider that interfaces with the DB then you could fire an Intent or use getContentResolver().notifyChange to send a special Uri notification that identifies both the table and action. An example Uri you could notify with might be: content://my-authority/change/table-name/insert
But even then you don't know exactly which rows were effected by the change.
Seems like triggers that write to a change log table will guarantee you hear about all changes regardless of where they came from, and you can know the exact id and action that occurred. Unfortunately it means slower inserts/updates/deletes and it means you probably need a Service of some kind to process and delete changes.
I'd love to hear if these is some better solution out there!

Can you determine what contact changes w/ registerContentObserver?

Just trying to determine if there is an easy way to determine what contact changes when using registerContentObserver, or some other method? I can tell when the database changes, but not sure I want to check all the records each time an update/change happens.
Basically if I have a list of contacts, and one gets updated via manual method (i.e. I change phone number for a contact or add a new contact), or automatic (say ActiveSync photo gets added, changed). I want to be able to A) Know that something changed, and B) Know what contact had some data changed.
I am trying to look for certain users where I may be able to match their photos from a remote service. If more information gets added to a user account, I want to be able to examine it to see if it provides for a match. I don't want to schedule it though, I would like to do it after an update happens.
Chris.
I'm not sure which Uri you are currently registering for updates, but when you register your ContentObserver, can't you just register an individual Uri that points directly to the contact you are interested in? Then your observer will only get notified when your interesting contact is modified. The section in the SDK Documentation title "Lookup URI" talks more about this:
http://developer.android.com/resources/articles/contacts.html
The lookup key is unique to each record (row), so I would imagine doing something like this is what you are after?
Uri lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
getContentResolver().registerContentObserver(lookupUri, false, myObserver);
And do that for each individual contact in your list.
For Added Contacts
The best way that I can see to do this is to re-query a cursor to the Contacts table each time the ContentObserver changes (re-query is fast, even if you're doing it often with lots of data), and maintain the highest known CONTACT_ID value. Whenever the cursor contains an ID beyond what you have stored, it was just added.
Also, if you haven't seen this conversation yet, it might be a good read. Dianne seems pretty adament that they keep specifics of content changes out of ContentObserver
Cheers.
Since this question was answered, there is a new callback method available in the ContentObserver class that has the uri of the changed content: http://developer.android.com/reference/android/database/ContentObserver.html#onChange(boolean, android.net.Uri)
This is available starting with the Android API Level 16

Categories

Resources