Android CallLog.Calls provider query problem - android

I am trying to get call log by using the CallLog.Calls content provider. However, I am little lost about the query I need to make. I am able to make a query and load the result in a ListView. But the query return all types of call.
Of course I can use a switch-case and take appropriate action as per the types of call returned. But for my program I only need the outgoing call logs.
So, how do I modify the query to get only outgoing call types. (I believe I have to use CallLog.Calls.OUTGOING_TYPE somewhere?). I have tried to modify the query in various ways but I keep getting error. If I try to supply the CallLog.Calls.OUTGOING_TYPE as an selection arg I get an error as its an int type and the query looks for String type.
I may be missing something simple, but can't figure it out. Any help would be much appreciated. Thank You. Here's my query below,
getContentResolver().query(CallLog.Calls.CONTENT_URI,null, null, null, ORDER_BY );

Try this code snippet:
Cursor c = getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
CallLog.Calls.TYPE + "=?",
new String[] { String.valueOf(CallLog.Calls.OUTGOING_TYPE) },
ORDER_BY);

Related

Should my function to get an Android Contact by name return a Cursor or something else?

I'm working on a class that is supposed to handle the user's Android contacts and interact with an SQL database where you can move your phone's contacts to (the information in the database will be displayed as a ListView). I've made a function that is supposed to retrieve an Android contact by name and return all of that contact's information. My function is as follows:
public Cursor getContactByName(String name)
{
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = null;
String selection = Data.DISPLAY_NAME + "=?";
String[] selectionArgs = new String[]{name};
String sortOrder = null;
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}
So the idea is that this would be called by another function, which would first check if the contact existed. This function would return a cursor containing only that contact's information. First I want to know if I'm right in returning a Cursor containing the contact's information or should I instead create a class that stores this information and return an object of the class? Or perhaps I should return a string? Keeping in mind that what I'm returning is the contact that I intend to move to my database, I feel like returning a Cursor isn't what I should be aiming for. And as a side-question, is there any reason to use ContentResolver.query instead of managedQuery for my purposes?
It depends on what you are going to be using the data for. If you're going to be adding it to another database (as your question suggests) you are probably best off leaving it as a cursor and simply entering that cursor in your second database. If you like mapping your database rows to objects, then do that. Keep in mind Object Relational Mapping takes more memory and cycles but usually results in clearer code. It's really up to you as the programmer (sorry I know that's not what you want to hear).
Personally i would prefer to create an object Contact. So you are more flexible and you can also implement functions related to your objects in this class (or the related DAO).
Passing the values as Cursor or even as String gives more trouble than it will help you. In an object you can see exactly the propertynames for everything, with a cursor you have to know the names or the positions of the corresponding fields, and in a string you even have to parse your results.
EDIT:
As #DavidCowden metioned, it depends strongly on what you are trying to achieve. So my guess was, that you want to load your data and display it somewhere.
And as already mentioned, in this case i would prefer a seperate class as it's much cleaner and maintainable.

How to print query executed by query() method of android

We pass so many parameters to query() method of android. Android has simplified our work by giving query method. Is there any way so that i can print the sql query which android will form from this query method arguments which android creates and sends to sqlite.
According to a previous post, I have tried and I got the following solution in order to print the query string in the log.
Use buildQueryString method of SQLiteQueryBuilder. It takes almost same parameters as query() method takes .........
String sqlQry = SQLiteQueryBuilder.buildQueryString(false,TABLE_NAME, null, COLUMN_NAME_PATIENTID +"="+ patientID, null, null, COLUMN_NAME_PATIENTFIRSTNAME, null);
Log.i(TAG, sqlQry);
cursor = db.query(TABLE_NAME, null, COLUMN_NAME_PATIENTID +"="+ patientID, null, null, null, COLUMN_NAME_PATIENTFIRSTNAME);
For what it's worth, if you run under the debugger you can view the private member variable mQuery, which shows you the exact SQL query executed on that cursor - it's handy and can be used on demand without mucking with any code.
Since the query methods are of cursor type, I am not sure whether It will be printed or not.
If you want to debug any query, you can use EXPLAIN QUERY PLAN keyword along with the query or use SQLiteQueryBuilder() or simply run the SQL query by using rawQuery() method.
You can take references from:
http://developer.android.com/reference/android/database/sqlite/SQLiteQueryBuilder.html
http://www.sqlite.org/eqp.html

Default order of records returned by cursor was not same for mobile & tablet

I wrote a select query to access set of records from database by setting null for the argument 'orderBy' in the query(). I found that order of records returned by query() method when I run the application in mobile is completely different when I run the same sample application in tablet.
My Query:
Cursor cursor = database.query(true, tableName, downloadQueueTableColumnNames, selection, null, null, null, null, null);
Here, in the query orderBy field is null.
I hope someone to explain the reason behind this...
If you aren't ordering the results, they can be returned in any order. The same device doesn't have to give the same order if you call it twice in a row. If you want it in the same order every time, you must use an order by.

How to solve all in one query?

In my search module I am using SQLite database. Sometimes I'm searching more than two values. So I am using AND condition and sometimes searching only one value. These two cases I need to implement in a single query. Please help me.
This is the query:
Cursor dbcur = myDB.rawQuery("select * from "+dbtable+" where Status='"+item+"'AND ball_court='"+ball+"'AND Tovendor='"+vendor+"'", null);
Sometimes I am searching status and ball_court, tovendor and sometimes I am searching status only. How to solve this problem?
Build the query string in stages, rather than all at once. If you're always going to select against the status, put that in the basic WHERE clause, then add any additional expressions. Use parameters (which you can do with SQLiteDatabase.query) rather than concatenating values into the query itself to prevent SQL injection. dbtable better not come from untrusted sources (e.g. users, the database itself). My Java's a little rusty, but try something like the following to start:
List<String> argList = new LinkedList<String>();
String selection = "Status=?";
argList.add(item);
if (ball != null && ball.length()) {
selection += " AND ball_court=?";
argList.add(ball);
}
if (vendor != null && vendor.length()) {
selection += " AND Tovendor=?";
argList.add(vendor);
}
String[] argArray = new String[argList.length()];
argList.toArray(argArray);
// columns is a String[] of column names
Cursor dbcur = myDB.query(false, dbtable, columns, selection, argArray, null, null, null);
Rather than appending strings, you might want to use a StringBuilder.
As for SELECT *, read "What is the reason not to use SELECT *?"
You might be able to get some answers if you post a sample query as well as what you might search for! I didn't totally understand your question, as I would/should be able to help out.

how add limit clause to manageQuery on android

Android's API provides a clean mechanism via SQLite to make queries into the contact list. However, I am not sure how to limit the results:
Cursor cur = ((Activity)mCtx).managedQuery(
People.CONTENT_URI,
columns,
"LIMIT ? OFFSET ?",
new String[] { Integer.toString(limit), Integer.toString(offset) },
null
);
Doesn't work.
Actually, depending on the provider you can append a limit to the URI as follows:
uri.buildUpon().appendQueryParameter("limit", "40").build()
I know the MediaProvider handles this and from looking at recent code it seems you can do it with contacts too.
You are accessing a ContentProvider, not SQLite, when you query the Contacts ContentProvider. The ContentProvider interface does not support a LIMIT clause directly.
If you are directly accessing a SQLite database of your own, use the rawQuery() method on SQLiteDatabase and add a LIMIT clause.
I found out from this bug that Android uses the following regex to parse the LIMIT clause of a query:
From <framework/base/core/java/android/database/sqlite/SQLiteQueryBuilder.java>
LIMIT clause is checked with following sLimitPattern.
private static final Pattern sLimitPattern = Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
Note that the regex does accept the format offsetNumber,limitNumber even though it doesn't accept the OFFSET statement directly.
I think you have to do this sort of manually. The Cursor object that is returned from the managedQuery call doesn't execute a full query right off. You have to use the Cursor.move*() methods to jump around the result set.
If you want to limit it, then create your own limit while looping through the results. If you need paging, then you can use the Cursor.moveToPosition(startIndex) and start reading from there.
You can specify the "limit" parameter in the "order" parameter, maybe even inside other parameters if you don't want to sort, because you'll have to specify a column to sort by then:
mContentResolver.query(uri, columnNames, null, null, "id LIMIT 1");

Categories

Resources