Content URI TO Android Room (SQLite conversion) - android

I am given a task where I need to change the activity. The Activity uses Cursor Loaders, Cursor and Content Uri.
Uri tempUri = some function call; That calls // BASE_CONTENT_URI.buildUpon().appendPath(PATH_ROUTES).build();
This will give
content://com.companyname.android/route/routeID/stops/sRcH
My task involves converting this URI to an SQL Query. How can I do that? I have a little idea about cursor since I have worked mostly in Room DB. How can I convert this into a query? I am unable to convert this into a SQL Query because I am not able to figure out what is the database in this, what is the table name or subtable name. Help will be appreciated. Thanks.

Related

Android Content Provider - Using Query Method To Insert, Delete, and Update

I have been studying Content Providers by reading Android Developer Fundamentals (Version 1).
Under section "11.1 Share Data Through Content Providers" / "The query() method" there is a note that states
Note: The insert, delete, and update methods are provided for
convenience and clarity. Technically, the query method could handle
all requests, including those to insert, delete, and update data.
How can query method be used to insert / delete / and update data? The query method has the following signature and does not take in custom SQL strings.
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder){}
I have not been able to find any resources that shows how this can be done. All seems to utilize the provided methods.
Frankly, that is a really poor job in that training guide. All it will do is confuse people.
I presume what they mean is that there is nothing magic about query() that forces it to only perform SQL SELECT statements. A ContentProvider is a facade — you can use it to store and retrieve from pretty much whatever you want, not just SQLite.
So, you could have your query() method:
Examine the Uri
Look for it to be of the form content://your.authority/something/insert/put/data/here
Parse the Uri to get the put, data, and here values
Insert those in a table under some pre-determined columns
Return an empty MatrixCursor
Or, it could:
Examine the Uri
Look for it to be of the form content://your.authority/something/insert
Insert a row using the projection for the columns and the selectionArgs as the values to put in those columns
Return an empty MatrixCursor
I do not know why anyone would do that, but it is certainly possible.

Distinct Query For CursorLoader

I am using CursorLoader to populate my listView.
But I need to get distinct result set.
But CursorLoader has no constructor to set distinct parameter.
Any Suggestions?
Yes!
In the CursorLoader constructor you specify a URI. Part of that URI is the ContentProvider Authority. The rest, though, is up to you! So create a virtual table!
If you have a table "songbirds", perhaps your URI is:
content://my.content.provider/songbirds
Simply teach your ContentProvider (add one more clause to your UriMatcher) to recognize the URI:
content://my.content.provider/distinctSongbirds
Process the "distinct" URI exactly as you do the non-distinct one, except add a "distinct" param to the actual DB query, when you make it.

How to Close SQLite Cursor and other open SQLite database?

I am trying to write a code in Android and going through following errors. I am opening a SQLite database and using Cursor.
Java Code
for(int y3=0;y3<10;y3++)
{
String sql_query5= "SELECT * FROM Data WHERE Id="+y3+"";
Cursor cur5 = SQLiteDatabase.openDatabase(db, null, SQLiteDatabase.OPEN_READWRITE).rawQuery(sql_query5, null);
if(cur5.moveToNext())
{
//
}}
So i need to display the Age in the layout but i am facing SQLiteCantOpenDatabaseException and Database object not closed. I don't understand the errors.
Please let me know some solution and suggestion !!!
Do not use hard-coded file paths. You have no guarantees about the structure of the filesystem.
Learn to use SQLiteOpenHelper. This is what helps you create and maintain your SQLite database. Instead of trying to open the database yourself, you create a new SQLiteOpenHelper and call getReadableDatabase().
When you are done reading from a Cursor, call cursor.close().
If you want to close the database, you can call close() on it as well; just be aware that any cursors you got by querying it will no longer be able to give you data, so make sure you are finished them those before closing the database.
add '' in your
String sql_query5= "SELECT * FROM Data WHERE Id='"+y3+"' ";

android contentProvider notifyChange

I am baffled by notifyChange machenism used in contentProvide:
// Tell the cursor what uri to watch, so it knows when its source data changes
c.setNotificationUri(getContext().getContentResolver(), uri);
and
getContext().getContentResolver().notifyChange(noteUri, null);
Here are the questions (suppose the provider and the client are in different packages):
Is the contentResolver returned by Provider the same as Resolver returned by the client?
Is the cursor the same as returned by the provider and the client?
what is the Uri resolution to be notified changes? the entire table uri or a row?
Please clarify
I know this is an old question. I am answering so that it is helpful for someone who comes across this question.
Is the contentResolver returned by Provider the same as Resolver returned by the client?
Yes, it is the same.
Is the cursor the same as returned by the provider and the client?
I suppose, you are asking this in the context of your first code snippet which is seen inside query() method. Here, you are setting the notification uri on the cursor which is to be returned to the client. So, obviously, the client and the provider are using the same cursor.
what is the Uri resolution to be notified changes? the entire table uri or a row?
Uri for notification depends on the operation:
insert() - The notification Uri is the table Uri appended with the
id of the newly inserted row.
delete() and update() - Here, the Uri is the table Uri appended with the id of the deleted or updated row.

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