Manipulating database output in Android strings - java

I'm trying to manipulate the output of an SQLite query so into two parts - KEY_DATE and KEY_ROWID + KEY_TYPE. Here's the code without the KEY_TYPE bit:
DataBaseAdapter db = new DataBaseAdapter(this);
db.open();
// get last test date
int whichItem = 1;
int upDown = 1; // use 1 for descending ordering
Cursor mCursor = db.getLogType(whichItem, upDown);
String[] columns = new String[] {DataBaseAdapter.KEY_DATE, DataBaseAdapter.KEY_ROWID};
startManagingCursor(mCursor);
ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_2, mCursor, columns, new int[] {android.R.id.text1, android.R.id.text2}){
public boolean areAllItemsEnabled(){
return false;
}
public boolean isEnabled(int position){
return false;
}
};
setListAdapter(adapter);
db.close();
It works fine, but when I replace:
String[] columns = new String[] {DataBaseAdapter.KEY_DATE, DataBaseAdapter.KEY_ROWID};
with:
String[] columns = new String[] {DataBaseAdapter.KEY_DATE, DataBaseAdapter.KEY_ROWID + DataBaseAdapter.KEY_TYPE};
it doesn't work.
All help much appreciated!

What you are doing in the:
String[] columns = new String[] {DataBaseAdapter.KEY_DATE, DataBaseAdapter.KEY_ROWID + DataBaseAdapter.KEY_TYPE}
You are concat strings DataBaseAdapter.KEY_ROWID + DataBaseAdapter.KEY_TYPE that will leads you to some new column name that is hybrid of both of them (e.g if KEY_ROWID="_id" and KEY_TYPE="device" then the new column name will be "_iddevice"). This might affect the result. Make sure you have column that has the same name as the concationation of these two column names I mentioned above. But if you want to include the KEY_TYPE in your result, add KEY_TYPE as separate element of the array that holds your column names. Then concat the result from both columns in result rows. (I'm assuming this is what you were trying to achieve)
String[] columns = new String[] {DataBaseAdapter.KEY_TYPE, DataBaseAdapter.KEY_ROWID};
List<MyResult> list = new ArrayList<MyResult>();
Cursor result_of_query = database.query(DataBaseAdapter.TABLE_NAME, columns, null, null, null, null, null);
if(result_of_query.moveToFirst())
{
while(result_of_query.isAfterLast()==false)
{
MyResult result = new MyResult();
result.setId(result_of_query.getInt(result_of_query.getColumnIndex(DataBaseAdapter.KEY_ROWID))));
result.setType(result_of_query.getString(result_of_query.getColumnIndex(DataBaseAdapter.KEY_TYPE))));
result_of_query.moveToNext();
list.add(result);
}
}
result_of_query.close();
---
public class MyResult
{
private String type;
private int id;
public void setType(String t)
{
type=t;
}
public String getType()
{
return type;
}
public void setId(int t)
{
id=t;
}
public int getId()
{
return id;
}
}
---

Okay so I found a simpler answer. The problem was really with the concatenation. I was trying to do it in String[] columns... but actually what I needed to do was to concatenate at as part of the SELECT query and use an alias. Hence I changed the String[] columns to include the column alias name KEY_ROWID_TYPE as follows:
String[] columns = new String[] {DataBaseAdapter.KEY_DATE, DataBaseAdapter.KEY_ROWID_TYPE};
And the query is then:
Cursor mCursor = db.query(true, DATABASE_LOGTABLE, new String[] {KEY_ROWID, KEY_TYPE, KEY_DATE, KEY_ROWID + " || \"-\" || " + KEY_TYPE + " as " + KEY_ROWID_TYPE}, null, null, null, null, null, null);
And of course I defined the KEY_ROWID_TYPE too.
Thanks to everyone for your help.

I would try concatenation and then insert into array
String tempStr = DataBaseAdapter.KEY_ROWID + DataBaseAdapter.KEY_TYPE;
String[] columns = new String[] {DataBaseAdapter.KEY_DATE,tempStr};

Related

How can i insert one array list of data to another array list which some fields are same?

I am stuck with small problem.I have two ArrayLists and I want to compare some values in the ArrayLists.
List<TriangleInfo> arrayList = dataGridTable.selectLastvalueNoAverage(equipid);
if fire this query i have get one arraylist.
public List<TriangleInfo> selectLastvalueNoAverage(int equipid)
{
List<TriangleInfo> list = new ArrayList<TriangleInfo>();
cursor = database.query(DatabaseHelper.DGADATATABLE, columns, "equipid = '"+equipid+"' ", null, null,null, "dateadded DESC");
while(cursor.moveToNext())
{
triangleInfo = new TriangleInfo();
triangleInfo.setDgaid(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.DGAID)));
triangleInfo.setDateadded(cursor.getString(cursor.getColumnIndex(DatabaseHelper.DATEADDED)));
triangleInfo.setCh4(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.CH4)));
triangleInfo.setC2h2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.C2H2)));
triangleInfo.setC2h4(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.C2H4)));
list.add(triangleInfo);
}
cursor.close();
return list;
}
In the same way the second query is
List<ThresholdsInfo> Threshold = thresholdsTable.selectAllRecords();
Here also I get one ArrayList.
public List<ThresholdsInfo> selectAllRecords()
{
List<ThresholdsInfo> list = new ArrayList<ThresholdsInfo>();
cursor = database.query(DatabaseHelper.THRESHOLDS, columns, null, null, null, null, null);
while(cursor.moveToNext())
{
info = new ThresholdsInfo();
info.setThresholdid(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.THRESHOLDID)));
info.setH2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.H2)));
info.setCh4(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.CH4)));
info.setC2h2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.C2H2)));
info.setC2h4(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.C2H4)));
info.setC2h6(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.C2H6)));
info.setCo(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.CO)));
info.setCo2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.CO2)));
info.setO2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.O2)));
info.setN2(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.N2)));
info.setTdcg(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.TDCG)));
list.add(info);
}
cursor.close();
return list;
}
So my problem is I have to compare the ch4,c2h2,c2h6 values in both ArrayList. So I did like
public String ThresholdCheck(List<TriangleInfo> arrayList)
{
thresholdsTable = new ThresholdsTable(context);
int ch4=0,tch4=0;
String color = "Black";
List<ThresholdsInfo> Threshold = thresholdsTable.selectAllRecords();
for(TriangleInfo info : arrayList)
{
info.getC2h2();
}
for(ThresholdsInfo info : Threshold)
{
tch4 = info.getCh4();
}
if(ch4>=tch4)
{
}
return color;
}
I wrote like that but that is long procedure. Please tell me is there any simple solution.

Getting one column of SQLite DB to ListView not working in Android

I'm trying to retrieve a column (a database column where names are saved) and puting them to a listview. I have a class called Data with "getters" and "setters".
The following code is placed in a DBHandler class which extends SQLiteOpenHelper. This code is called from the MainActivity.java where the listview is meant to be updated with an onClickButton event.
public String[] getNames (int a, int b) {
String[] names = new String[] {};
String selectQuery = "SELECT * FROM " + TABLE_NAME
+ " WHERE " + KEY_ONE + " = ? AND " + KEY_TWO + " = ?";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, new String[]{String.valueOf(a), String.valueOf(b)});
if (cursor.moveToFirst()) {
int i = 0;
do {
Data myData = new Data();
names [i] = cursor.getString(1); //Names in cursor
++i;
} while (cursor.moveToNext());
}
return names;
}
In the MainActivity.java I call the following code before updating and notifying the update of the listview adapter:
values = db.getNames (1, 1);
I don't know why but this isn't working, it throws many errors with String lengths and crashes the app when I click the button that is suposed to enter the onClickButton.
Thanks
Follow the laalto answer and at last convert your ArrayList to Array like below:
String[] arrRecords = names.toArray(new String[names.size()]);
String[] names = new String[] {};
...
names [i] = cursor.getString(1); //Names in cursor
You're assigning to an empty array which causes ArrayIndexOutOfBoundsException.
Consider using a list such as ArrayList where you can append your values, e.g.
List<String> names = new ArrayList<String>();
...
names.add(cursor.getString(1));
If you really need to return a String[], you can convert the list with toArray():
String[] arr = new String[names.size()];
names.toArray(arr);
return arr;
Also, when posting questions that involve exceptions, always include the exception stacktrace from logcat in the question itself.
Why use like this
String[] names = new String[] {}; //no size
names [i] = cursor.getString(1); //it can work?
Use ArrayList<String>
List<String> names = new ArrayList<String>(); //declare
names.add(<column-val>); //add column value to list

Strange NullPointerException error in android when using custom suggestions provider

I am trying to make custom search suggestions in my app. I’ve started from documentation and Searchable dictionary example. However, this example isn’t so good for me so I’ve started with some tests to find out exactly how to make it, because there is not much tutorials in the Internet also.
Generally my app has right now 2 databases – one normal and second with less number of columns – FTS3. What I would like to achieve is to connect suggestions provider to this FTS3 table.
What I was trying to do was to now was, using simple function, return in suggestions whole DB (around 200 records) after typing any letter in search box. I know about limit 50 records, but I don’t think it is the problem.
This are fragments from Provider’s code. What I found out, that when you type in text, provider goes to option SEARCH_SUGGEST:
// UriMatcher stuff
private static final int SEARCH_WORDS = 0;
private static final int GET_WORD = 1;
private static final int SEARCH_SUGGEST = 2;
private static final int REFRESH_SHORTCUT = 3;
private static final UriMatcher mUriMatcher = buildUriMatcher();
/**
* Builds up a UriMatcher for search suggestion and shortcut refresh queries.
*/
private static UriMatcher buildUriMatcher() {
Log.d(TAG,"urimatcher");
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
// to get definitions...
matcher.addURI(AUTHORITY, "mydb", SEARCH_WORDS);
matcher.addURI(AUTHORITY, "mydb/#", GET_WORD);
// to get suggestions...
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
return matcher;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
switch (mUriMatcher.match(uri)) {
case SEARCH_SUGGEST:
Log.d(TAG,"SEARCH_SUGGEST");
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: " + uri);
}
return getSuggestions(selectionArgs[0]);
case SEARCH_WORDS:
Log.d(TAG,"SEARCH_WORDS");
if (selectionArgs == null) {
throw new IllegalArgumentException(
"selectionArgs must be provided for the Uri: " + uri);
}
return search(selectionArgs[0]);
case GET_WORD:
Log.d(TAG,"GET_WORD");
return null;
default:
Log.d(TAG,"default");
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
private Cursor getSuggestions(String query) {
String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
Log.d(TAG,"query1: " + query);
try{
Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
}
catch(Exception e)
{
Log.d(TAG,e.toString());
}
return tmp;
}
In getSuggestions I put code that should generally work, but it doesn’t. Doesn’t work only when used here. When I used it in other activity to get cursor for listview everything was fine. Here it returns my NullPointerException.
So getting deeper I put also some Log tags in getAllEntriesFTS method and this method looks like this:
public Cursor getAllEntriesFTS(boolean distinct, String[] result_columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit, String query) {
Log.d(TAG,"query db: " + query);
String[] columns = { MyDBAdapter.KEY_TITLE, MyDBAdapter.KEY_ID};
Log.d(TAG,"columns: " + Integer.toString(result_columns.length));
Cursor allRows = null;
try{
allRows = db.query(distinct, DATABASE_TABLE_FTS, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null);
Log.d(TAG,"OK");
}
catch(Exception e)
{
Log.d(TAG, e.toString());//it always goes there with NullPointerExceptionwhen used in provider
}
Log.d(TAG,Integer.toString(allRows.getCount()));
return allRows;
}
So, generalny speaking it should return cursor to whole DB, but instead it throws In place where it shouldn’t NullPointerException.
Can someone please tell me what am I doing wrong and how it should be done?
Thank's to JB Nizet I was able to find my mistake. I was thinking I've studied Google's example good, but I was wrong.
The problem was lack of database open before cursor call. It should look like this:
private Cursor getSuggestions(String query) {
String[] columns = { MyDBAdapter.KEY_TITLE,MyDBAdapter.KEY_ID};
Log.d(TAG,"query1: " + query);
try{
MyDB.open();
Cursor tmp = MyDB.getAllEntriesFTS(false, columns,
null, null, null, null, MyDBAdapter.KEY_TITLE, null, query);
MyDB.close();
Log.d(TAG,"cursor: " + Integer.toString(tmp.getCount()));
}
catch(Exception e)
{
Log.d(TAG,e.toString());
}
return tmp;
}
Thank you all for showing me it.

Retrieving a phone number with ContactsContract in Android - function doesn't work

I wrote the following function in order to retrieve one single phone number that belongs to the contact with id "contactID".
The function which is to retrieve the phone number:
private String getContactPhone(String contactID) {
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection = null;
String where = ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?";
String[] selectionArgs = new String[] { contactID };
String sortOrder = null;
Cursor result = managedQuery(uri, projection, where, selectionArgs, sortOrder);
if (result.moveToFirst()) {
String phone = result.getString(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (phone == null) {
result.close();
return null;
}
result.close();
return phone;
}
result.close();
return null;
}
How this function is called:
ArrayList<Contact> resultContacts = new ArrayList<Contact>();
Cursor result = null;
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Event.CONTACT_ID,
ContactsContract.CommonDataKinds.Event.START_DATE,
};
String where = ContactsContract.Data.MIMETYPE+" = ? AND "+ContactsContract.CommonDataKinds.Event.TYPE+" = "+ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY;
String[] selectionArgs = new String[] {ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE};
String sortOrder = null;
result = managedQuery(uri, projection, where, selectionArgs, sortOrder);
while (result.moveToNext()) {
Long id = result.getLong(result.getColumnIndex(ContactsContract.Contacts._ID));
String phone = getContactPhone(String.valueOf(id));
...
}
...
Unfortunately, it doesn't work. I get null if I call this function with the value that I got from "ContactsContract.Contacts._ID". Why is this so? What is wrong?
Edit: I used to map Contacts._ID to CommonDataKinds.Phone.CONTACT_ID - which didn't work. But now I map Contacts.DISPLAY_NAME to CommonDataKinds.Phone.DISPLAY_NAME and it works suddenly - strange, isn't it? But I would rather like to map the IDs instead of the display names. So the question is still topical. Could this be due to different IDs in those tables? Isn't this why there are lookup IDs?
To get the contact id in the first part, you should use:
ContactsContract.Data.CONTACT_ID
instead of:
ContactsContract.Contacts._ID
So the projection should be:
String[] projection = new String[] {
ContactsContract.Data.CONTACT_ID,
ContactsContract.CommonDataKinds.Event.CONTACT_ID,
ContactsContract.CommonDataKinds.Event.START_DATE,
};
And then of course get the correct row:
Long id = result.getLong(result.getColumnIndex(ContactsContract.Data.CONTACT_ID));
You are getting null because you have set your projection to null. The projection is basically the list of columns that you want returned e.g.
String[] projection = {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER};
Usually, when you find the contact, they may have a list of phone numbers, so you have to use another cursor to iterate through the phone numbers, e.g.
Cursor phones = mContext.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null);
while (phones.moveToNext())
{
phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA));
}
Hope this helps.
Your code for getContactPhone() works fine on my end. I tested by launching a contact picker, selecting a contact, then using the ID that was returned and passed that into your method.
So I suspect you are indeed passing in an invalid ID. Can you post the full stack trace for the null pointer exception?
Yes, lookup keys are available because _IDs are not guaranteed to stay the same since syncs and contact aggregation changes them.

Array constants can only be used in initializers

public String[] getData(){
String[] columns = {KEY_ROWID, KEY_TIME, KEY_TXT};
Object[] data;
Cursor c = database.query(DB_TABLE, columns, null, null, null, null, null);
int iRow = c.getColumnIndex(KEY_ROWID);
int iTime = c.getColumnIndex(KEY_TIME);
int iTxt = c.getColumnIndex(KEY_TXT);
for(c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
data[c.getPosition()+1] = {c.getString(iRow), c.getString(iTime), c.getString(iTxt)};
}
return data;
}
You pretty much get the idea what I wanna do here. Can't update the data variable from for loop. But I would need to do that. How?
You just have to use slightly different syntax:
data[c.getPosition()+1] =
new String[]{c.getString(iRow), c.getString(iTime), c.getString(iTxt)};

Categories