Notify a content resolver when normal sql insert or update - android

I have created a small content provider (which I only use to query a db table and fetch some value). I have confirmed that the provider works fine.
The table values get updated on a regular basis through normal sql insertions(and not through anycontent provider)
Whenever an insert/update or delete occurs through a normal sqlite operation as mentioned above, I need to notify the content resolvers which was written to communicate with the content provider just for quering database and fetch some values.
Is this, possible? If yes what need to be done?
Any help is appreciated.
EDITED to include my DB insert method:
public void insert(ArrayList<Integer> profileValues, String tableName){
String duplicationCheck = " WHERE NOT EXISTS (SELECT 1 FROM profiles WHERE devID = "+"'"+profileValues.get(0)+"'"+");";
if(tableName.equals(PROFILES_TABLE)){
profilesDB.execSQL("INSERT INTO " +
PROFILES_TABLE +
"(devID,alert,findme,proximity,timep,conn_status) SELECT "+"'"+profileValues.get(0)+"'"+","+profileValues.get(1)+","+profileValues.get(2)+","+profileValues.get(3)+","+profileValues.get(4)+","+profileValues.get(5)+duplicationCheck);
}
getContentResolver().notifyChange(MY_CONTENT_URI, null);
}

Any time you manually update the underlying database and need to notify registered ContentObserver instances, call notifyChange() on the ContentResolver present for the Context.
So, for instance, let's say you had registered a ContentObserver with the constant value MY_CONTENT_URI:
//Insert, update, or delete data in the database
//If you are within a Context, like Activity or Service
getContentResolver().notifyChange(MY_CONTENT_URI, null);
//Otherwise pass in a Context you can call on
context.getContentResolver().notifyChange(MY_CONTENT_URI, null);
All registered observers for the particular Uri you pass will be notified.

Related

Android: Query content provider database

In my application I have a sqlite database.The columns in this database are :- id, data,date-added, mydescription.
And android content provider Media.Image.External has following columns in its database:- _id , _data , _title , _date-added ,....and so on.
I want that whenever application is launched, my database gets synced with content provider database(only id, data, and date-added columns). So If android content provider database has an addition of row, my database also adds that row and if any row is deleted, then my database also deletes that row.
So how to achieve this thing.
Thanks
You can use Application class.
It is a singleton and guaranteed to start before your any Activity.
Inside it query data with the help of Cursor Loader. If the content provider correctly implemented you will get new data for every update in the DB.

Cursor loader pointing to join query in content provider not updating list

I have multiple cursor loaders set up pointing to different URIs in my content provider and they work without any issues. Each loader is for a specific table in my database.
However I have now created a new URI in my content provider to execute a join query on my tables. I have created a new loader that points to the URI to be used for performing a join query but the loader doesn't update the UI.
If I close the app and then open it then the new data appears but after inserting new data in one activity and then returning to my main activity, the data hasn't updated. The loader isn't being called despite the database have new data inserted to it.
I am calling cursor.setNotificationUri(getContext().getContentResolver(), uri); for my new join URI.
Is there any particular reason why this isn't working? Like I said the loaders work fine for standard querying of individual tables but a loader with a join query doesn't.
Is it that a loader can only listen to a single table being updated hence why it can't listen to the join?
EDIT:
Some more information about the workflow...
Activity 1 reads data using a join query of the separate tables and displays to the UI
Activity 2 inserts data into separate tables to the database
Activity 1 launches Activity 2 which finishes after inserting data
Activity 1 has a loaders to update the UI. Loaders reading from individual tables works fine but a loader reading from a join query doesn't get called when data is updated. It is only called when the activity is created.
I Know this question was asked a long time ago but hopefully it will help some others experiencing the same problem... I had exactly the same issue
In your Query method in your Content Provider Class, before you set the notification Uri. Make sure the Update and Delete Uri's are the same as the query Uri's.
uri = Uri.parse("content://com.casselsinthecloud.cloudbeats.provider/playlist_contents");
Then call setNotificationUri(...) with the new Uri..
cursor.setNotificationUri(getContext().getContentResolver(), uri);
This will ensure the CursorLoader is updated dynamically..

Android Cursor retrieve belongsTo relationshoips

I have two data models Item and Category with the relationship "Item belongs to Category"
Naturally my database has an Item.category_id column.
When I retrieve data using SQLiteDatabase#query() it returns a cursor with the data for the passed table name. How can it also retrieve related data (in this case, the category)?
PS: I'm trying to avoid rawQuery() but if that's the only way then...
This can be achieved with a regular Query. I'm making the assumption you have the id of the item and want to fetch the Category.
I'm also making the assumption you know what I mean by/how to create your own Contract & Provider, if you don't, look up database providers on the official docs or let me know
String[] args = { String.valueOf(myItemId) };
getContentResolver().query(MyCategoryContact.CONTENT_URI, null, MyCategoryContact.ITEM_ID + " = ?", args, null);

My Content Provider to Rest with Broadcast is having Infinite loop

I watched the virgil's android rest google io video and trying to implement it.
In short this is the problem but please read on for details.
ContentResolver query -> Content Provider Query -> Start Database update Service, make query, return cursor
The service -> update database ->Broadcast database update
Activity -> register broadcast -> on receive Contentresolver query. (we are back in the beginning)
This became an infinite loop.
In my content provider, for query method. I start Intent service which uses the rest service. Then the query method queries the local database and returns the cursor. In the onhandle() method of the intent service, I retrieve new content from web service and writes to the database. Then I send a local broadcast with an action.
In my activity I register the broadcast and onreceive(). I call the contentresolver.query to get new content from the database. This apparently is creating a circular problem. I am back in content provider query..service..broadcast.
I want to be able to stop the broadcast after its received.
How can I solve this. Should I use SQLitedatabase query rather than content resolver? or should I send the broadcast differently. can I send another parameter with content resolver query like broadcastAfterUpdateOn and Off? Should I derive content resolver and create a custom query method?
Don't send notification if there is no new item in the REST result.
long id = db.insertWithOnConflict(getTableName(), null, values, SQLiteDatabase.CONFLICT_IGNORE);
if (id < 0) {
return null;
}
Uri newUri = ContentUris.withAppendedId(getContentURI(), values.getAsInteger(getIdFieldName()));
Log.d(TAG, "New profile URI: " + newUri.toString());
getContext().getContentResolver().notifyChange(newUri, null);

How to properly insert values into the SQLite database using ContentProvider's insert() method through a CursorLoader?

I was reading the doc, but I am still not too sure. Its says to use getContentResolver(), but then that really isn't using CursorLoader. So is there a way to do it through CursorLoader? I know how to do it with query(). Are the steps very similar? Even just a link that explains exactly this would be helpful.
Please note, do not link me to the Google doc as they do not have an example that ever uses the insert() method from ContentProvider using a CursorLoader.
Thanks in advance!!
Edit: I should probably mention the reason I am confused with this is because calling a new CursorLoader automatically calls ContentProviders query() method. But how can I do the same for insert?
Check out my blog post on the subject:
Content Resolvers and Content Providers
The CursorLoader has nothing to do with it.
Insertion is a totally different concept... it has absolutely nothing to do with the CursorLoader. When coupled with the LoaderManager, the CursorLoader automatically queries your database and updates itself when the ContentObserver is notified of a datastore change. It has nothing to do with the actual process of inserting data into your database.
How requests to the ContentResolver are resolved
When you insert (or query or update or delete) data into your database via the content provider, you don't communicate with the provider directly. Instead, you use the ContentResolver object to communicate with the provider (note that the ContentResolver is a private instance variable in your application's global Context) . More specifically, the sequence of steps performed is:
You call getContentResolver().insert(Uri, ContentValues);
The ContentResolver object determines the authority of the Uri.
The ContentResolver relays the request to the content provider registered with the authority (this is why you need to specify the authority in the AndroidManifest.xml).
The content provider receives the request and performs the specified operation (in this case insert). How and where the data is inserted depends on how you implemented the insert method (ContentProvider is an abstract class that requires the user to implement insert, query, delete, update, and getType).
Hopefully you were able to wrap your head around that at least a little. The reason why there are so many steps involved is because Android (1) allows applications to have more than one content provider, and (2) needs to ensure that apps can securely share data with other third-party apps. (It wasn't because it wanted to confuse you, I promise).
Inserting data via the ContentProvider
Now that you (hopefully) have a better idea of how the ContentResolver is able to relay these requests to the content provider, inserting the data is fairly straight forward:
First, decide which uri you want to have matched by your content provider. This depends on how you decided to match your uris with the UriMatcher. Each uri you have represents a different means of inserting data into your internal database (i.e. if your app has two tables, you will probably have two uris, one for each table).
Create a new ContentValues object and use it to package the data you wish to send to the content provider. The ContentValues object maps column names to data values. In the below example, the column name is "column_1" and the value being inserted under that column is "value_1":
ContentValues values = new ContentValues();
values.put("column_1", "value_1");
Once received, the content provider will (in your case) pass the values object to your SQLiteDatabase (via the SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values) method). Unlike the ContentProvider, this method is implemented for you... the SQLiteDatabase knows how to handle the values object and will insert the row into the database, returning the row id of the inserted row, or -1 if the insertion failed.
... and that's how you insert data into your database.
TL;DR
Use getContentResolver().insert(Uri, ContentValues);
Convert Cursor to ContentValues for easy database insertion.
Its says to use getContentResolver(), but then that really isn't using CursorLoader
Besides what Alex said, there's nothing preventing you from iterating through the Cursor returned, putting them into ContentValues and then inserting that (say, to a different DB).
Just an example from the top of my head (a simple Cursor of two String columns):
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (cursor.moveToFirst()) {
ArrayList<ContentValues> values = new ArrayList<ContentValues>();
do {
ContentValues row = new ContentValues();
DatabaseUtils.cursorStringToContentValues(cursor, fieldFirstName, row);
DatabaseUtils.cursorStringToContentValues(cursor, fieldLastName, row);
values.add(row);
} while (cursor.moveToNext());
ContentValues[] cv = new ContentValues[values.size()];
values.toArray(cv);
getContentResolver().bulkInsert(CONTENT_NAMES, cv);
}
}
There are probably more efficient ways to do that (and definitely some integrity checks), but that was my first thought...

Categories

Resources