Alternate way to access multiple columns independently from a database? - android

My application stores three items: "name", "email", "mobile" in its database under the same table. I want to access each of them independently so that I could display their value under their respective TEXTVIEWs. I access them independently because if I access them all through one single function I won't be able to display the values
Currently, I have to write a function for each column so as to get information from it.
Example to get "email"
public String getUserEmail(String mobile) {
String[] columns = new String[] {USER_EMAIL};
Cursor c = MainDataBase.query(REG_INFO_TABLE, columns, USER_MOBILE_NUMBER + "=" + mobile, null, null, null, null);
String result = "";
int email = c.getColumnIndex(USER_EMAIL);
while(c.moveToNext()) {
result = result + c.getString(email);
}
return result;
}
So, if I need the the "name", I'll have to write another function similar to above to get it.
Now, if I need to access 50 such columns, I'll have to make 50 such functions which does not sound good. Is there any other way I can do this? Can arrays be used here?

You should consider creating a User class that holds the data for each User. Then you change getAllRegInfo() to return a User object. This has the advantage that the rest of your app only accesses Users and has no idea where the data comes from. It is also much more expressive to write
User user = getAllRegInfo();
String name = user.getName();
rather than
String[] user = getAllRegInfo();
String name = user[0];
In addition, a User class can have fields of any type rather than being forced to convert all data to String.

Okay, so I found an alternative. It is using arrays only.
Here is the code:
public String[] getAllRegInfo() {
String[] columns = new String[] {USER_NAME, USER_EMAIL, USER_MOBILE_NUMBER};
Cursor c = MainDataBase.query(REG_INFO_TABLE, columns, null, null, null, null, null);
String[] result = new String[3];
for(int j=0; j<3; j++) {
result[j] = "";
}
int[] column = new int[3];
column[0] = c.getColumnIndex(USER_NAME);
column[1] = c.getColumnIndex(USER_EMAIL);
column[2] = c.getColumnIndex(USER_MOBILE_NUMBER);
while(c.moveToNext()) {
for(int i = 0; i<3; ++i) {
result[i] = c.getString(column[i]);
}
}
return result;
}
Of course, one will have to manually asign the array indexes to the columns. Like this:
column[0] = c.getColumnIndex(USER_NAME);
column[1] = c.getColumnIndex(USER_EMAIL);
column[2] = c.getColumnIndex(USER_MOBILE_NUMBER);
The solution seems to be working fine but I'm not sure how scalable it is.

Related

Query Database with an array list and get an array list of results back

I have setup an application which currently can lookup an input id with one on the database to then give a single result. E.g. user enters id = 1 , database contains a record with an id of 1 then returns the name or number etc...
Now I want to improve the system slightly by querying my database with an arraylist which contains a range of id's e.g. 3, 456, 731 etc... which I want my database to search for. I have also grouped multiple values to certain id's for example the database might search for an id of 3 it will then find 5 results I want it to return the telephone number of each one of those results into another arraylist which I can print to the logs.
I hope I have explained this enough, but please ask questions if you require more information.
The code below demonstrates the modified version of the query used to gain a single result, but I cannot see what I'm doing wrong to gain multiple results.
Activity....
// New array list which is going to be used to store values from the database
ArrayList<String> contactsList;
// This arrayList has been received from another activity and contains my id's
ArrayList<String> contacts = intent.getStringArrayListExtra("groupCode");
// The database which i'm using
ContactDBHandler contactDBHandler = new ContactDBHandler(getApplicationContext(), null, null, 1);
//getAllValues is used to pass my arraylist id's to the database.
contactsList = contactDBHandler.GetAllValues(contacts);
// Simple log statement to loop and display results
for (int i = 0; i < contactsList.size(); i++){
Log.i("Numbers", contactsList.get(i));
}
ContactDBHandler
Query
// I'm telling it to get the contact number from the contact_list
// when the groupcode matches the code recieved.
public ArrayList<String> GetAllValues(ArrayList groupCode)
{
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = null;
String alarmName = "";
ArrayList<String> list = new ArrayList<>();
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code=?", new String[]{groupCode+ ""});
if (cursor.moveToFirst())
{
do
{
list.add(cursor.getString(0));
}
while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed())
{
cursor.close();
}
return list;
}
Thanks
Can you see where I have gone wrong?
Try this:
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code IN (" + TextUtils.join(",", Collections.nCopies(groupCode.size(), "?")) + ")", groupCode.toArray(new String[groupCode.size()]));
Your current code fails to pass the list in the sql-format: = does only support single values, for lists you have to use IN.
Your code would result in a query like this:
SELECT contact_number FROM contact_list WHERE grp_code=["some_id","other_id"]
But what you need (and my code produces) is:
SELECT contact_number FROM contact_list WHERE grp_code IN ('some_id','other_id')
References:
SQL query to find rows with at least one of the specified values
WHERE IN clause in Android sqlite?
IN clause and placeholders
https://developer.android.com/reference/android/text/TextUtils.html#join(java.lang.CharSequence,%20java.lang.Iterable)
You cannot pass an ArrayList to an SQLQuery. To check for multiple values in the same field you have to use the 'in' keyword.
Ex:
SELECT * FROM `table1` where column in ( 'element1', 'element2', 'element3')
In your case,
String str = "";
for(String s: groupCode){
str = str+","+"\'"+s+"\'";
}
//to remove the extra ' in the begining
str = str.substring(1);
return str;
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code IN (?)", new String[]{str});

Selecting RawContacts with special requirements in Android

Whenever I want to add new data to an existing Android contact, I use the following function to retrieve all RawContacts IDs for the given contact ID:
protected ArrayList<Long> getRawContactID(String contact_id) {
ArrayList<Long> rawContactIDs = new ArrayList<Long>();
String[] projection = new String[] { ContactsContract.RawContacts._ID };
String where = ContactsContract.RawContacts.CONTACT_ID + " = ?";
String[] selection = new String[] { contact_id };
Cursor c = getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, where, selection, null);
try {
while (c.moveToNext()) {
rawContactIDs.add(c.getLong(0));
}
}
finally {
c.close();
}
return rawContactIDs;
}
After that, I just insert the data using the ContentResolver:
getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
This is done for all RawContacts IDs that have been found previously. The effect is, of course, that all data is added repeatedly. Thus I want to return only one result now, but this has to meet special requirements.
I would like to adjust my function above so that its result meets the following requirements:
ContactsContract.RawContactsColumn.DELETED must be 0
The RawContacts entry must not be a secured one like Facebook's
ContactsContract.SyncColumns.ACCOUNT_TYPE is preferably "com.google". So if there is one entry that meets this requirement, it should be returned. If there is none, return any of the remaining entries.
How can I do this (most efficiently)? I don't want to make the query to complex.
I have given this some thought, from my experience with contact r/w, and with your needs in mind. I hope this helps you solve the issue and or points you in the direction you are looking for.
Please note that i have no device available with any sync adapters such as facebook so unfortunately i cannot confirm my answer viability (the read only bit mainly which might changeable to a simple != '' ).
Same getRawContactID function with some adjustments
protected ArrayList<Long> getRawContactID(String contact_id) {
HashMap<String,Long> rawContactIDs = new HashMap<String,Long>();
String[] projection = new String[] { ContactsContract.RawContacts._ID, ContactsContract.RawContacts.ACCOUNT_TYPE };
String where = ContactsContract.RawContacts.CONTACT_ID + " = ? AND " + ContactsContract.RawContacts.DELETED + " != 1 AND " + ContactsContract.RawContacts.RAW_CONTACT_IS_READ_ONLY + " != 1" ;
String[] selection = new String[] { contact_id };
Cursor c = getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, where, selection, null);
try {
while (c.moveToNext()) {
rawContactIDs.put(c.getString(1),c.getLong(0));
}
}
finally {
c.close();
}
return getBestRawID(rawContactIDs);
}
And another getBestRawID function to find the best suited account -
protected ArrayList<Long> getBestRawID(Map<String,Long> rawContactIDs)
{
ArrayList<Long> out = new ArrayList<Long>();
for (String key : rawContactIDs.KeySet())
{
if (key.equals("com.google"))
{
out.clear(); // might be better to seperate handling of this to another function to prevent WW3.
out.add(rawContactIDs.get(key));
return out;
} else {
out.add(rawContactIDs.get(key));
}
}
return out;
}
Also note - I wrote most of the code without running / testing it. Apologies in advance.

Retrieve specific column of data and store it in string array

I got a sqlite database and i wanted to retrieve a specific column of data and store it into a string array. Inside the database there are two columns. There will be multiple row of data with the same username and I wanted to retrieve the user's "ContentPath" and store it into a string array. But I don't know how to retrieve that specific column data...
public String[] get_contentByEmailID(String emailid){
String[] returnMsg = null;
helper = this.getReadableDatabase();
Cursor c = helper.rawQuery("SELECT tableid, emailid, contentpath" +
" from w_content where emailid='"+emailid"' ", null);
int contentpathColumn = c.getColumnIndex("contentpath");
if (c.moveToFirst()) {
do {
returnMsg = new String[2];
String contentpath = c.getString(contentpathColumn);
returnMsg[0] = emailid_sync;
returnMsg[1] = contentpath;
} while (c.moveToNext());
}
if (c != null && !c.isClosed()) {
c.close();
}
if (helper!=null){
helper.close();
};
return returnMsg;
}
When I called this function to retrieve the data. It comes up with emailid and contentpath.
String values[] = helper.get_contentByEmailID(SettingConstant.EMAIL);
Any comments will be appreciated.
The reason you got array filled with emailid and contentpath is, because you always reset the returnMsg on each row and fill it with such value. Since there will be varying row count, it is generally suggested that you use ArrayList, instead of building static length array.
To fix it, change:
String[] returnMsg = null;
to:
ArrayList<String> returnMsg = new ArrayList<String>();
And then, in your do{}, do something like this:
do {
String contentpath = c.getString(contentpathColumn);
returnMsg.add(contentpath);
} while (c.moveToNext());
Finally, change your return statement to:
return returnMsg.toArray();

How to get all single column values then pass it to String[]?

I got a big problem here. I create databasehelper class to handle all of my query function.
Now I try to make a function that will load all values of a column from my database but I dont know how to do it. FYI I got 3 columns inside my database table. Here is my code so far:
(UPDATED, it works and gives me values now)
public List<Content> getSearchKeys() {
List<Content> contentList = new ArrayList<Content>();
// The query
String selectQuery = "SELECT * FROM " + TABLE_SEARCH;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// I use do.. while here and it works now, should I better use for loop?
if (cursor.moveToFirst()) {
do {
Content content = new Content();
content.setID(Integer.parseInt(cursor.getString(0)));
content.setsKeys(cursor.getString(1));
content.setAct(cursor.getString(2));
// Adding content to list
contentList.add(content);
} while (cursor.moveToNext());
}
// return content list
return contentList;
}
The problem now is how to pass the result of above function into String[] ? In my Activity I try to use it like this and it's not working:
(Updated)
...
setContentView(R.layout.page_search);
DatabaseHandler db = new DatabaseHandler(this);
List<Content> contents = db.getAllContacts();
final String[] searchQ = new String[contents.size()];
int i =0;
for (Content cn : contents) {
searchQ[i] = cn.getsKeys().toString();
}
final String[] SearchQueries = searchQ;
If I comment the code above and change it to string array like this, then it works:
static final String[] SearchQueries = new String[] { "iPhone", "Mac", "Apple",};
My aim is to replace array above into Array I retrieve from my database. So what's wrong and what's the correct method to handle this? Many thanks for your help.
Problem 1: if cursor is empty but not null, your do while loop fails (change it to a while loop)
Problem 2: to convert to string, you'll need a toString method in your Content class. Then you will write a loop:
String[] queryAsStrings = new String[query.size()];
int i = 0;
for (Content c : query) {
queryAsStrings[i] = c.toString();
}

ListView using two cursoradapters?

I have some code which executes two queries against a database and returns two cursor objects. Is there any way that I can combine these two cursors so that all the ListView gets the data from both?
There's MergeCursor for that (if there's no way to join tables).
FYI - An example of using MergeCursor()
c = Cursor containing Contacts columns from Contacts.CONTENT_URI
private Cursor mergeCursorSubset(Cursor c) {
int userMobile = ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,
workMobile = ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE;
String storedNumber = ContactsContract.CommonDataKinds.Phone.NUMBER,
displayName =ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
numberType = ContactsContract.CommonDataKinds.Phone.TYPE,
contactKey = ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,
whereClausePre = contactKey+" = '",
whereClausePost = "AND ("+numberType+" = '"+userMobile+"' OR "+numberType+" = '"+workMobile+"'";
Uri lookupUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;;
Cursor [] m = new Cursor[c.getCount()];
if (c.moveToFirst())
for (int k = 0; k<c.getCount();k++){
//Find the mobile numbers
Cursor u = this.getContentResolver().query(lookupUri,
new String[]{displayName, storedNumber, numberType}
, whereClausePre+c.getString(c.getColumnIndex(Contacts.LOOKUP_KEY))+"') "
+ whereClausePost, null, null);
int i = 0;
if (u.moveToFirst())
m[i++] = u;
} //for Each key
return new MergeCursor(m);
}
You can also use cwac-merge.
cwac-merge: Provides the MergeAdapter,
a ListAdapter that blends multiple
Views or ListAdapters into a single
ListAdapter. Use this for section
headings, blending multiple sources of
data together, etc.
Check out MatrixCursor.
Maybe this will help you also Android - Database Table Join

Categories

Resources