Limit number of rows in Cursor query - android

I need to get contacts from an android phone. so I am using this code:
Cursor phones = getActivity().getContentResolver().query(Phone.CONTENT_URI,
new String[] { Phone.NUMBER, Phone.TYPE },
" DISPLAY_NAME = ?", new String[] { displayName }, null);
while (phones.moveToNext()) {
//do work here
}
I want to tell the cursor to limit the response to 50 with something like "LIMIT 50". Where do I pass that information to the cursor? Please copy and paste my code and make edit there.

There is no limit in Android API, but you can apply it in your code like this:
Cursor phones = getActivity().getContentResolver().query(Phone.CONTENT_URI,
new String[] { Phone.NUMBER, Phone.TYPE },
" DISPLAY_NAME = ?", new String[] { displayName }, null);
for (int i = 0; i < 50 && phones.moveToNext(); ++i) {
// do work here
}
phones.close();

Order by id DESC Limit 1:
db.query("table", null, "column=?", new String[]{"value"}, null, null, "id DESC", "50");

If you have the DB and the table name you can use that, but Content providers don't have a limit argument in their query statement.
mDb = new DBHelper (this);
Cursor c = mDB.getReadableDatase().query(
<Phone_Table_Name>,
new String[] { Phone.NUMBER, Phone.TYPE },
"DISPLAY_NAME = ?",
new String[] { displayName }, null),
null,
null,
null,
"50");

Related

Android database query with multiple selection

I know how to query for a single selection with the following:
Cursor cursor = database.query(true, TABLE, COLUMNS, "name = ?", new String[]{"Bob"},null,null,null,null);
But suppose I want to make a function as follows:
public Cursor queryNames(String[] names)
where the function returns a cursor where the name = names[0] OR name = names[1] ... etc. So for example, if I called the function queryNames(new String[] {"Alice","Bob","Charlie"}), the function should return a cursor where the name is any of the three (Alice, Bob, or Charlie). How would I write this? Thanks!
Your method might want to look like this:
public Cursor queryNames(String[] names) {
SQLiteDatabase mDb = this.getReadableDatabase();
String whereStatement = "";
for(int i = 0; i < names.length; i++) {
if (i != (names.length - 1))
whereStatement = whereStatement + "name = ? OR "
else
whereStatement = whereStatement + "name = ?"
Cursor cursor = mDb.query(true, TABLE, COLUMNS, whereStatement, names, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
mDb.close();
return cursor;
}
Hope this helps!
try:
Cursor cursor = db.query(true, TABLE, COLUMNS, "name IN (?)", new String[]{" 'moe', 'larry', 'curly'"}, null, null, null, null);
It would probably be best to build the String[] separately than to guess at the number of names.
Enclose the whole thing in double quotes, the individual names in single quotes, comma-separated.

SELECT and WHERE in android (SQlite)

I want to search if there are exact course_no, semester ,and year value in the table.
I problem is that I can only filter course_no.
Cursor cursor = database.query(DatabaseHelper.TABLE_COURSE, CourseItemDataSource.allColumns, DatabaseHelper.KEY_COURSE_COURSE_NO + "=?", new String[] { notiItem.getCourseNo() }, null, null, null);
When I tried to add other filter it doesn't seems to work
[Edited] Sorry for being not informative, the problem is that when I pass the below code filter don't work. Note that notiItem.getCourseNo() and notiItem.getYear() is a String.
The following column in the table is a TEXT.
Cursor cursor = database.query(DatabaseHelper.TABLE_COURSE, CourseItemDataSource.allColumns, DatabaseHelper.KEY_COURSE_COURSE_NO + "=? AND "+DatabaseHelper.KEY_COURSE_YEAR+"=?", new String[] { notiItem.getCourseNo() ,notiItem.getYear()}, null, null, null);
This is code the method I tried
public CourseItem searchToCourse(NotificationItem notiItem){
/**Check if exact course_no, semester, year of notiItem exist in Course Table
* return null if not found
*
*/
String [] columns = new String[]{ "*"};
Cursor cursor = database.query(DatabaseHelper.TABLE_COURSE, CourseItemDataSource.allColumns, DatabaseHelper.KEY_COURSE_COURSE_NO + "=?", new String[] { notiItem.getCourseNo() }, null, null, null);
Log.i("DATA SOURCE", "AFTER QUERY ");
if (cursor != null) {
cursor.moveToFirst();
}
CourseItem courseItem = CourseItemDataSource.cursorToCourseItem(cursor);
return courseItem;
}
How can I search multiple column at a time??

Android Sqlite concat two columns

I have made the concatenation so far, but in the results, it displays
UncleSam.
What I want to do is to put a space between the two columns so the result would be
Uncle Sam.
This is the code I'm working on:
public Cursor getAllPatients()
{
Cursor localCursor = //
this.myDataBase.query(DB_TABLE, new String[] {
KEY_ID, KEY_FNAME + "||" + KEY_LNAME, KEY_DIAGNOSIS, KEY_LASTFFUP }, null, null, null, null, null);
if (localCursor != null)
localCursor.moveToFirst();
return localCursor;
}
from DBHelper.java
and
Cursor cursor = dbHelper.getAllPatients();
String[] data = new String[]{
DBHelper.KEY_FNAME + "||" + DBHelper.KEY_LNAME, DBHelper.KEY_DIAGNOSIS, DBHelper.KEY_LASTFFUP};
//
int[] to = new int[] {R.id.fullname, R.id.diagnosis, R.id.lastffup};
dataAdapter = new SimpleCursorAdapter(this, R.layout.custom_row, cursor, data, to, 0);
from my MainActivity.
Any help will do. Thanks.
You can concat like this:
Cursor localCursor = this.myDataBase.rawQuery("SELECT (KEY_FNAME || ' ' || KEY_LNAME) AS fullname, KEY_ID, KEY_DIAGNOSIS, KEY_LASTFFUP FROM DB_TABLE");
Your concated full name will be in the cursor column 'fullname'.
In main activity:
String[] data = new String[]{ "fullname", DBHelper.KEY_DIAGNOSIS, DBHelper.KEY_LASTFFUP};
(You should probably assign a DBHelper constant for "fullname").
Android Sqlite concat two columns
After a little conversation with author of this thread i suggest you to don't concat columns (you really don't need it) and concat Strings retrieved from Cursor. Your statement will be more human-readable and solution cleaner.
Explanation:
Generally is very useful and efficient approach to represent your table on application layer with objects which will represent tables. For example if you had table User, so create new class User and columns in table will be equal to properties in this class. This way is i guess pretty elegant (if someone else will see your code, he won't be confused and scared)
Finally you can simply concat fname and lname when you'll add them to ListAdapter
So i prefer this way:
List<User> users = new ArrayList<User>();
User u = null;
String query = "select * from Table";
Cursor c = db.rawQuery(query, null);
if (c != null && c.moveToFirst()) {
do {
u = new User();
u.setFirstName(c.getString(c.getColumnIndex("fname")));
u.setLastName(c.getString(c.getColumnIndex("lname")));
...
users.add(u);
} while (c.moveToNext());
}
And then somewhere in ListAdapter you can do:
textView.setText(u.getFirstname() + " " + u.getLastName());
Hope it helps.
I finally got it working.
public Cursor getAllPatients()
{
Cursor localCursor = //
this.myDataBase.query(DB_TABLE, new String[] {
KEY_ID, KEY_FNAME + "|| ' ' ||" + KEY_LNAME, KEY_DIAGNOSIS, KEY_LASTFFUP }, null, null, null, null, null);
if (localCursor != null)
localCursor.moveToFirst();
return localCursor;
}
and
Cursor cursor = dbHelper.getAllPatients();
String[] data = new String[]{
DBHelper.KEY_FNAME + "|| ' ' ||" + DBHelper.KEY_LNAME, DBHelper.KEY_DIAGNOSIS, DBHelper.KEY_LASTFFUP};
//
int[] to = new int[] {R.id.fullname, R.id.diagnosis, R.id.lastffup};
dataAdapter = new SimpleCursorAdapter(this, R.layout.custom_row, cursor, data, to, 0);

Get a contact's groups?

I'm trying to make a many-to-many mapping of contacts to groups.
For example, if I have:
User 1, belongs to group 701, 702, 704
User 2, belongs to no groups
User 3, belongs to group 702
I'm hoping to get a relation that looks like this:
userID | groupID
1 | 701
1 | 702
1 | 704
3 | 702
I've tried this:
Cursor cursor = contentResolver.query(ContactsContract.Data.CONTENT_URI, null, new String[] {
ContactsContract.CommonDataKinds.GroupMembership.CONTACT_ID,
ContactsContract.CommonDataKinds.GroupMembership.GROUP_SOURCE_ID
}, null, null, null);
But that doesn't quite work. The GROUP_SOURCE_ID column returns weird numbers that aren't the ID of any groups. Sometimes it even returns 0 or a negative number.
I could construct a mapping of this by going through each group, and finding all contacts in that group, but that would take a lot of queries, and I'm trying to stay fast (apparently, just those few queries are quite slow!).
Can anyone tell me how I can get this contacts-to-groups mapping in one query?
Thanks!
Cursor dataCursor = getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DATA1
},
ContactsContract.Data.MIMETYPE + "=?",
new String[]{ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE}, null
);
By using this dataCursor you will get the contact_id and group_id of all contacts in the contact database.
Cursor groupCursor = getContentResolver().query(
ContactsContract.Groups.CONTENT_URI,
new String[]{
ContactsContract.Groups._ID,
ContactsContract.Groups.TITLE
}, null, null, null
);
By using this groupCursor you will get the group_id and group_title of all groups in the contact database.
So if you want to get all groups associated with a contact_id the first get the dataCursor using suitable select statements. Using dataCursor you can get all the group_id associated with that contact_id. Now using groupCursor you can get the information about all groups associated with that specific contact.
A complete answer will be:
First the fetch the group cursor (same as the answer above)
Cursor groups_cursor= getContentResolver().query(
ContactsContract.Groups.CONTENT_URI,
new String[]{
ContactsContract.Groups._ID,
ContactsContract.Groups.TITLE
}, null, null, null
);
Store all the group_id and group_title in a groups HashMap using this code:
if(groups_cursor!=null){
while(groups_cursor.moveToNext()){
String group_title = groups_cursor.getString(1);
String id = groups_cursor.getString(0);
groups.put(id, group_title);
}
}
Then using the above answer's data_cursor, fetch contacts_ids and their group_ids.
Cursor dataCursor = getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DATA1
},
ContactsContract.Data.MIMETYPE + "=?",
new String[]{ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE}, null
);
Now using the dataCursor and the groups HashMap.
if(dataCursor!=null){
while(dataCursor.moveToNext()){
String id = dataCursor.getString(0);
String group_id= dataCursor.getString(1);
String groupTitle = groups.get(group_id);
Log.d(TAG, "groupTitle : " + groupTitle + " contact_id: " + id );
}
}
public static HashMap<String, String> getContactsForGroup(String groupID, Activity activity){
Cursor dataCursor = activity.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{ // PROJECTION
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.DISPLAY_NAME, // contact name
ContactsContract.Data.DATA1 // group
},
ContactsContract.Data.MIMETYPE + " = ? " + "AND " + // SELECTION
ContactsContract.Data.DATA1 + " = ? ", // set groupID
new String[]{ // SELECTION_ARGS
ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE,
groupID
},
null
);
dataCursor.moveToFirst();
HashMap<String, String> map = new HashMap<>();
while (dataCursor.moveToNext()) //
{
String s0 = dataCursor.getString(0); //contact_id
String s1 = dataCursor.getString(1); //contact_name
String s2 = dataCursor.getString(2); //group_id
Log.d("tag", "contact_id: " + s0 + " contact: " + s1 + " groupID: "+ s2);
map.put(s0, s1);
}
return map;
}

Android - How to fetch a contact name and number without using Cursors?

I have a big performance issue in my app. After going through traceview i found that most of my app's performance has been consumed by cursors. So i was wondering is there any alternative to Cursors for dealing with device contact list. And if there is no alternative then please advise me how to deal with cursors so it won't slow down your app.
Please HELP!!
Thanks.
This part of my code has performance issue :-
public void getDisplayName()
{
Cursor c1 = this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
String personName = null, number = null;
try
{
Log.e(TAG, "I am here!!");
if(c1.getCount() > 0)
{
Log.e(TAG, "I am here2!!");
while(c1.moveToNext())
{
HashMap<String,String> item = new HashMap<String,String>();
String id = c1.getString(c1.getColumnIndex(Contacts._ID));
personName = c1.getString(c1.getColumnIndex(Contacts.DISPLAY_NAME));
item.put("Name", personName);
Cursor cur = this.getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, null, CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id}, null);
while(cur.moveToNext())
{
Log.e(TAG, "I am here!!3");
number = cur.getString(cur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
item.put("Number", number);
}
displayName.add(item);
}
}
}
finally
{
c1.close();
}
}
How to fetch a contact name and number without using Cursors?
That is not possible.
I have a big performance issue in my app.
Rather than using a single query, you use N+1 queries, where N is the number of rows returned by the other query. This is guaranteed to give you poor performance compared to just doing a single query.
You can get the user's name and _ID along with the phone numbers:
String[] PROJECTION=new String[] { Contacts._ID,
Contacts.DISPLAY_NAME,
Phone.NUMBER
};
Cursor c=a.managedQuery(Phone.CONTENT_URI, PROJECTION, null, null, null);
Also, never call getColumnIndex() in a loop, since the value never changes.
I was working on same code and I need email and phone numbers both in first approach It took around 35 seconds to fetch 612 contacts, when I optimized it, it took 2 seconds to fetch 612 contacts
my code.
ContentResolver cr = context.getContentResolver();
String[] projection = new String[] { Contacts.DISPLAY_NAME, Phone.NUMBER };
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
String[] selectionArgs = { String.valueOf(1) };
Cursor cur = cr.query(Phone.CONTENT_URI, projection, selection, selectionArgs, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phNo = cur.getString(cur.getColumnIndex(Phone.NUMBER));
ContactModel contactModel = new ContactModel();
contactModel.setName(name);
contactModel.setPhoneNumber(phNo);
contactList.add(contactModel);
}
}
String[] projectionEmail = new String[] { Contacts.DISPLAY_NAME, Email.ADDRESS };
String selectionEmail = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
String[] selectionArgsEmail = { String.valueOf(1) };
Cursor curEmail = cr.query(Email.CONTENT_URI, projectionEmail, selectionEmail, selectionArgsEmail, null);
if (curEmail.getCount() > 0) {
while (curEmail.moveToNext()) {
String Emailname = curEmail.getString(curEmail.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String email = curEmail.getString(curEmail.getColumnIndex(Email.ADDRESS));
ContactModel contactModel = new ContactModel();
contactModel.setName(Emailname);
contactModel.setEmailId(email);
contactList.add(contactModel);
}
}
`

Categories

Resources