Prevent ContentObserver from getting a "specific" change on URI - android

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.

Related

Firebase: for notifications use childEventLisetener or SingleEvent?

I have an android app that uses Firebase for the backend. In my database, I have a section called USER_NOTIFICATIONS which gets populated with some information when user's post gets liked.
Now, in the app, should I have a ChildEventListener that gets triggered any time a notification happens or should I have a SingleValueEventListener inside a function and call it every 20 seconds inside a Runnable? Is it expensive to run SingleEventListener in a Runnable?
The majority of the resource usage of a listener comes from the data it reads. When you attach a listener to a location, it reads the data from that location and fires the relevant events.
If you use addListenerForSingleValueEvent that's all it does. But if you use addValueEventListener or addChildEventListener, the listener stays active and will also be called if the data is updated afterwards.
a listener on a piece of data that never changes is quite cheap. But keeping a listener on data that changes frequently is as expensive as the size of the data changes.
In other words: there is no way to tell what to do without knowing all of the above. Without knowing those, I'd go for the simplest possible approach, put some measurements in place, and optimize as you discover more about your app's behavior.
I'm assuming you want to your app to respond to changes in the database, in which case you should use ChildEventListener. You can specify different behavior for 4 actions (onChildAdded, onChildChanged, onChildMoved and onChildRemoved).

Android Wear DataLayer API usage for synchronizing when phone app is closed

So, I want to learn this synchronization strategy instead of just using the simpler MessageAPI, but am really struggling with how to successfully implement this.
My project is like this: I make queries to download a small amount of text from an API, via my phone. I will make these queries every so often, haven't really decided on how often just yet. The data will update the watch, which should hold onto the last data received. After that first download occurs, I send data using a DataMap, to the Android Watch. I only send that once, because I believe that sets up a channel to continually send updates when ready. If that is wrong, please correct me.
My main question is this: what if the Android phone's app closes? Then the data object goes to null, and gets sent to the Watch as null? Or, should I send an object from a long-running service or shared preferences on the Android phone, so that the object is never null?
Think of the Data Layer as more of an event system, i.e., you update your data and you're notified on the other side when the data is updated (created, changed, or deleted). You don't have to worry about if the Activity is killed after that. Even if the data was 'deleted', you would be notified it was deleted.
On the Wear device, you would listen for the changes via a Service or Activity and update UI, DB, etc. accordingly.
It probably make sense to read through this Android training guide. (It isn't too long.) The Handling Data Layer Events section is probably the most useful.

Finding Caller of ContentResolver.notifyChange

I have an activity for updating a table which holds configuration data for a service. I am using a SimpleCursorLoader and the SupportLoaderManager to update the listview in that Activity. I destroy the loader in In the activity's onDestroy. This may not be relevant, since the issue I'm seeing happens even without visiting this Activity.
I have a service as well, that registers a ContentObserver on the URI to the table that is modified in the Activity above. It reads its configuration, sets itself up and registers a ContentObserver on that table in the Service's onCreate. In the Service's onDestroy, that listener is unregistered.
This is only 1 of a few databases/tables that I have in my system. What I'm seeing is that when I make an update to a completely different table, the ContentObserver on this configuration URI is being triggered. The Authorities are completely different, they interact with different SqlLite databases, they're even running in different processes within the application. I removed all "notifyChange" calls that I could find which would trigger the ContentObservers, yet they still are firing.
My question is, is there any way to find out who is calling the notifyChange that is causing the ContentObserver to fire? Does the system outside of my application have any reason to notify observers of a URI? I'm trying to track it down, but without having any clue where the notify is coming from, I'm running into a wall.
Again, only a few hours away from the answer. I apparently didn't find all of the notifyChange calls in my code. The offender was:
getContentResolver.notifyChange(new Uri.Builder().build(), null);
which was calling notify on a blank Uri. It doesn't appear to be noted in the documentation, but the behavior I saw was that this triggered all of the registered ContentObservers to be fired in my application. I got that line out of there, and now everything is notifying as it should.
The answer to my original question, "Is there a way to find out who called notifyChange on a Uri?," I think the answer is "Look harder for calls to notifyChange in your code. Other than that, you're on your own."

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!

Categories

Resources