Android SQLite DB notifications - android

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!

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 - Listen to changes in android contacts and get the deltas

I'm trying to understand the whole concept of sync adapters from last couple of weeks and have few questions regarding the functionality.
I want to listen to all the changes in android contacts
Approach 1:
I have created a custom account and also created a sync adapter.
Written a broadcast listener listening to ContactsContract.Contacts.CONTENT_URI and in
public void onChange(boolean selfChange) of ContentObserver class i'm calling ContentResolver.requestSync(account,ContactsContract.AUTHORITY,bundle) which is acting as a trigger point to start the sync adapter when ever there is a change to contacts data.
Everything looks fine till here but in the SyncAdapter class i'm not getting any data in SyncResult variable in onPerofmSync
So how Can I get the delta changes from contacts?
Correct me if this is not the way to trigger sync adapter.
Approach 2:
I have followed some example where they were talking about querying the contacts database where dirtyFlag is set to 1.
I was able to get the changes but my question is
who will set that dirtyFlag value back to '0' ?
If I have to do that then lets say there are multiple applications on the phone which does the same thing. If some application sets the flag to '0' before my application tries to access the information. I'll be missing out on all the changes.
Approach 3:
Query the database and keep track of version for each contact in my own database and if 'version' has changed consider that as a change in contact. This looks like a heavy process.
Finally my question is what is the best way to listen to changes in
contacts on user's device?
What you can do is persist (possibly using a local MySql database) a mapping between Contacts.LOOKUP_KEY and its RawContacts.VERSION values.
Once you get a broadcast that a change happened in the Contacts DB (via onChange) you query for all RawContacts.VERSIONs and their Contacts.LOOKUP_KEY and compare it to the state your have persisted before, if one of them changed, you'd know that contact changed.

can anyone teach me how to make android notification that occur from trigger SQLITE db event?

i am currently making an android application. then i need to make a notification that only occur when there is certain event occur like insert or update.
what i want to try is how to use SQLITE trigger to make the notification occur on the android apps whenever user insert or update their data
thanks.
Take a look at the TRIGGER syntax
and you will discover there's no place to do it (unless you create your own function).
However, your application is the only one invoking insert() or update() so you know even before the trigger is invoked whether you want to send a notification. Then, do it where you invoke these methods.

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().

How to determine which row in contacts database has been updated

I am writing a backup application and need to know which records in the contacts database have been updated, so that I can backup only those records. I have looked at the documentation and it seems that there is a "DIRTY" constant field in ContactsContract.RawContacts class, which is supposed to be set to "1", for the rows that are updated. But it is not clear to me as to when will this field get cleared to "0". Can someone provide me example code on how to use this? Can this field be used to determine if a contact has been added or updated?
If this is not the correct way to achieve what I am trying to do can anyone suggest me another way. I am also aware that I can use the RegisterContentObserver() call to identify whenever there is a change in the Contacts database but this will require my application to be running always in the background, which is way too expensive and I do not want to do that.
If there is anyway to extract the timestamp when the various contacts have been added or updated that would be perfect too, but I cannot find how to do that.
Any help is very much appreciated.
I have looked at the documentation and it seems that there is a "DIRTY" constant field in ContactsContract.RawContacts class, which is supposed to be set to "1", for the rows that are updated. But it is not clear to me as to when will this field get cleared to "0".
In my experience, whenever there is a 'dirty' indicator of some sort, it is the responsibility of the backup/sync app to reset it once the data has been successfully committed during a backup/sync operation.
This can cause problems, however, when more than one application is used - the first one run at any time after data has been updated will reset the flag and the next one run wont find anything to backup/sync.
In this case if you require that a user is able to use a 'sync' app (for example) but you also want to have a 'backup' operation then registering a ContentObserver would serve a better purpose and there's no reason why this should be 'expensive' on resources if implemented correctly.
EDIT: Although there is no 'timestamp' there is a 'VERSION' field which is updated (which is when 'DIRTY' is set). If you backup this field, you could simply leave the 'DIRTY' flag set and compare current VERSION in the contacts DB with your most recent backup.

Categories

Resources