How to gets some metadata when cursor observer notify change - android

When i got some cursor i want to be aware for changes, so i have used the registerContentObserver() on my cursor and when change occur i just notify that change happened.
i looked into the notifyChange method on android developer and i didnt see any way to pass some metadata .
when i said metadata i meant any other object which tell me what change happen like delete/update/insert

You can't specifically add any metadata per se, but you can bend the system to pass this information anyway.
When registering your content observer, set the notifyForDescendants parameter to true. Then in your ContentProvider, generate a different uri to add information.
For example if the uri you normally use is content://com.example.app.provider/item/42, you can use one of the following uris to add information :
content://com.example.app.provider/item/42/inserted
content://com.example.app.provider/item/42/updated
content://com.example.app.provider/item/42/deleted

Related

How to see the before and after snapshot of the changed document in Firestore?

Scenario
I am using onSnapshot() to listen to document changes in Firestore. My document contains an array field. I would like to see which items were added/deleted from the nested array in the document. Is there any way to achieve this?
Possible Solution
I see there is an oldDocuments() field in the QuerySnapshot.snapshot object which could be used to achieve my goal. I could just compare the oldDocument with the returned snapshot to see what changed in the nested array. The problem is oldDocument is a private field that I can't access through the API.
I am using Android Kotlin as my client.
There is nothing built in that can help you see what exactly in a document has changed. However, there are two workarounds.
The first one would be to attach a persistent listener and view changes between snapshots. That means that when you attach the listener you get a list of all documents your query returns. As soon as a document is changed, onEvent will fire. This means that you'll be able to know the document that has changed. Knowing that you already have a list with the initial documents, you can find the old document based on the ID and compare it against the new one.
Another solution would be to save a new document each time something changes. This is some kind of document versioning. In this way, you'll always be able to check the new document against the old one using only two document reads.

How can I show a Downloads List using RecyclerView?

I need to track and update download status(start,pause,play,done) of multiple files in a list that I get from some Api (can't share), onto a RecyclerView.
I am also getting a fileId so each file can be distinguished.
I need download tracking based on the fileId because the Download list is also searchable, it means that the position of items will change and so we can't rely on position based ViewHolder refreshing.
Also if for some reason you close the app, and then go back to the list, search the file, it should show the file download status.
Now there are three options :
a) WorkManager based implementation (how this option can be implemented?)
b) PRDownloader (how this option can be implemented?)
c) Or Android's download manager? (Need to be sure that we need to show progress of multiple files at
same time in a list.)
Which one is better and more reliable?
Which one is the shortest method?
Also can someone share if you have code based on work manager?(how
will you manage to relate fileId to workManger's work id. Do I
need to make a DB table for keeping track of downloads by the Worker?
How to use LiveData from workManager, iff we can in the ViewHolder )
[Reference to Blog/Code/Repos will be most helpful]
Answering my own question(strange!).
I used Fetch Downloader Library
Initialized and used the "Fetch Instance" as a Singleton
Added the download using tag (Maybe I wrongly used the tag. It was supposed to be used for group of downloads. But I used one tag for each download. But it worked.)
Now I did following in the ViewHolder's bind() method :
Took the file Id as a "tag" and removed the FetchObserver linked to
the "tag" i.e. Id using the method of "Fetch Instance" (//will update
the method)
Then again find the download in the "Fetch
Instance" using the Id as "tag".(getDownloadsByTag() method)
If there is a download, you will receive a downloadList whose 0th
element will be your download because I am using one tag per download
and not for group.
Now add the FetchObserver again for that
"tag".
Inside the FetchObserver's lambda, update the progress and other values.
Note : The code can not be shared for non-disclosure purposes. Can share small snippets if you find this confusing.

In what circumstances is uri passed to Android's ContentObserver.onChange() callback?

The onChange() method of Android's ContentObserver class says, "Includes the changed content Uri when available." In what circumstances is the URI available? In what circumstances is it not available?
The uri parameter was added in API level 16 (Android 4.1) and so I would expect it to be set in Android 4.1 and newer. However I'm seeing a case on Android 4.3 where uri is not set.
Method 1: Works
MyContentObserver.onChange() is called and is passed a valid uri:
contentResolver.registerContentObserver(myUri, true, new MyContentObserver());
Method 2: Doesn't work--why not?
MyContentObserver.onChange() is called but the uri parameter is null:
contentResolver.query();
cursor.registerContentObserver(new MyContentObserver);
Is this expected? Is one of these preferred over the other? I've tested this using "content://com.google.android.gm/me#example.com/labels" and using my own custom ContentProvider.
This is an old question, but still unanswered. So I will add my answer in case people is still curious about it.
When your content provider notifies the registered observer using getContext().getContentResolver().notifyChange(URI, "your_uri");, it asks the ContentResponder for it. The return value from that method is the ContentObserver that you registered with the registerContentObserver() method of the content responder, which is what you did in the first case. However, in the second case, you registered the observer in the Cursor using the registerContentObserver() method of the Cursor, so the ContentResponder doesn't know about it.
If you are setting ContentObserver upon common tables(e.g people, mediaprovider etc) then unfortunately you might not receive any Uri as an argument, it might be blank as it depends upon underneath content provider implementation. To receive an valid Uri upon change, respective ContentProvider has to be modified to notify change along with URI.
e.g getContext().getContentResolver().notifyChange(Uri, "your_uri"); // this notifies all the registered ContentObserver with Uri of modified concerned dataset.
If you are writing your own ContentProvider then use above mentioned line whenever you perform update, delete or insert operation on your database.

Calling a Java method from a sqlite trigger (android)

I want registered callback method using sqlite trigger
for example,
public void printLog(){
Log.i("TAG","1 row added");
}
this method calling after insert any row in sqlite.
Is it possible?
How to do that?
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.
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!
You can set content observer this link will help Receives call backs for changes to content http://developer.android.com/reference/android/database/ContentObserver.html

Pass a parameter to a Custom Search Suggestion ContentProvider

I have a working custom search suggestions class (via http://developer.android.com/guide/topics/search/adding-custom-suggestions.html). It currently returns one type of information - "product names".
I've added some additional activities (screens) to my app so that if a person is on a product page, starting up a search should return results from "product names", but if they are in another activity, I would like the search suggestions to pull "manufacturer names".
I saw Accessing appSearchData bundle from ContentProvider, but the custom search suggestions provider extends ContentProvider which doesn't work with the answer
Bundle b = intent.getBundleExtra(SearchManager.APP_DATA);
This Bundle is available to the search results class, but not the contentprovider.
How best to pass a parameter ("product" or "manufacturer") to a search suggestions content provider?
This doesn't seem like an ideal solution, but I had the same need and I found I could get the job done by adding a public ivar or method to the subclass of ContentProvider that handles the search suggestions. Prior to initiating the search, you can configure your provider as needed. You can access the provider instance from an activity like so:
ContentProviderClient client = getContentResolver().acquireContentProviderClient("my.searchsuggestionprovider");
MyProviderClass provider = (MyProviderClass) client.getLocalContentProvider();
Now you can configure with provider.setParameter("product") or whatever you need. You might need to reset the parameter to a default or something after building your cursor.
Edit: This turned out to be impractical, at least in my case, since the content provider is called with query() every time a character is typed. Instead, I have employed a workaround similar to what is described in set-search-hint-dynamically. By creating an alternate "searchable" XML definition and activity, you can alter the URI that's passed to the content provider in query(), adding a path component to provide the additional parameter or context you need.
I just made a static variable for the parameter on my content provider, and set it from the activity. I been thinking about it, and it's the cleanest workaround I have found!

Categories

Resources