I have a table in a database and I would like to show only one row of this table. The table has 3 fields (ID, Title and Description).
I want to filter the rows depending on the Title.
I have this code:
Cursor cursor = db.query(TABLE_NAME, FROM, null, null, null, null, ORDER_BY);
where the third field is the selection one (a String). But I don't know what I have to put exactly to select only the row that I want to show. Thanks
String[] FROM = { // ID of the column(s) you want to get in the cursor
ID,
Title,
Description
};
String where = "Title=?"; // the condition for the row(s) you want returned.
String[] whereArgs = new String[] { // The value of the column specified above for the rows to be included in the response
"0"
};
return db.query(TABLE_NAME, FROM, where, whereArgs, null, null, null);
This should give you a cursor with all your columns but only containing the rows where the value of the Title column is equal to 0.
try this
Cursor cursor = db.query("TABLE_NAME",new String[]{"ColumnName"}, "ColumnName=?",new String[]{"value"}, null, null, null);
You can search by following code in SQLite;
In MainActivity;
search.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s.toString());
}
});
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return
//Here you can filter data by any row , just change text replace of "subject"
dbManager.fetchdatabyfilter(constraint.toString(),"subject");
}
});
DatabaseHelper.java
public Cursor fetchdatabyfilter(String inputText,String filtercolumn) throws SQLException {
Cursor row = null;
String query = "SELECT * FROM "+DatabaseHelper.TABLE_NAME;
if (inputText == null || inputText.length () == 0) {
row = database.rawQuery(query, null);
}else {
query = "SELECT * FROM "+DatabaseHelper.TABLE_NAME+" WHERE "+filtercolumn+" like '%"+inputText+"%'";
row = database.rawQuery(query, null);
}
if (row != null) {
row.moveToFirst();
}
return row;
}
Related
I am using a AutoCompleteTextView (will later be changing this to an editText but one problem at a time) to filter the results of my listView implementing a textWatcher:
fqp = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String itemName = constraint.toString();
return getSearch(itemName);
}
};
Cursor getSearch(String itemName) {
String searchSelect = "(" + MediaStore.Audio.Media.TITLE + " LIKE ? )";
String[] selectArgs = { "%" + itemName + "%"};
Cursor searchCursor = getContentResolver().query(
queryUri,
projection,
searchSelect,
selectArgs,
MediaStore.Audio.Media.TITLE + " ASC"
);
return searchCursor;
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String empty = "";
if(s.toString() == empty){
adapter.changeCursor(getAll());
adapter.notifyDataSetChanged();
}else{
adapter.getFilter().filter(s.toString());
adapter.notifyDataSetChanged();
}
}
This filter works just fine, but i need to figure out a way to reset my list once my autoCompleteTextView is empty. Surely there is a correct way to do this other than testing if it's empty but that's what i tried to no avail. Also should i just create two Cursors: one containing my full list and the other my filtered list so i don't have to re-query the content provider?
The issue seems to lie in this line
if(s.toString() == empty)
In Java, you cannot compare Strings like this, you need to use
if(s.toString().equals(empty))
Also TextWatcher is not getting called because the listener is not linked to your AutoCompleteTextView.
Also should i just create two Cursors: one containing my full list and the other my filtered list so i don't have to re-query the content provider?
If the filtered list will have the same data every time, then yes it's better to keep a reference to it instead of doing a new query.
Example using EditText:
adapter.setFilterQueryProvider(fqp);
search.addTextChangedListener(watch);
fqp = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
String itemName = constraint.toString();
return getSearch(itemName);
}
};
Cursor cursor = getContentResolver().query(
queryUri,
projection,
null,
null,
MediaStore.Audio.Media.TITLE+" ASC"
);
Cursor getSearch(String itemName) {
String searchSelect = "(" + MediaStore.Audio.Media.TITLE + " LIKE ? )";
String[] selectArgs = { "%" + itemName + "%"};
Cursor searchCursor = getContentResolver().query(
queryUri,
projection,
searchSelect,
selectArgs,
MediaStore.Audio.Media.TITLE + " ASC"
);
return searchCursor;
}
TextWatcher watch = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String empty = "";
if (s.toString().equals(empty)) {
adapter.changeCursor(cursor);
adapter.notifyDataSetChanged();
} else {
adapter.getFilter().filter(s.toString());
adapter.notifyDataSetChanged();
}
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
};
I have created a database in sqlite for android with variables like Acc No, name, date etc etc.
i have many edit text in my activity. when the acc no is entered in Acc No edit text, the corresponding name should appear in below Name edit text. how to do that.
my DB code is given below
public void getName(Editable account_edit_txt){
"Acc_No " + account_edit_txt, null, null, null, null);
Cursor cursor = db.query(DATABASE_TABLE, new String[] {"Cust_Name","Acc_No"}, "Acc_No=?",new String[]{"account_edit_txt"}, null, null, null);
Log.e("running", "cursor run");
if(cursor!=null)
{
Log.e("running", "curosr is not null");
while(cursor.isFirst())
{
Log.e("running", "cursor while loop enter");
String temp = (cursor.getString(cursor.getColumnIndex("Cust_Name")));
String temp2 =(cursor.getString(cursor.getColumnIndex("Acc_No")));
Log.e("running", "id acc num" +temp+ " name"+temp2);
}
}
Activity code is given below
public class TransactionActivity extends Activity {
EditText acc_edit;
TextView acc_txt;
Editable account_edit_txt;
Connection connection;
String name;
SQLiteDatabase sdb;
AccountDBAdapter db = new AccountDBAdapter(this);
//
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.transaction_page);
acc_edit = (EditText) findViewById(R.id.edittext_Acc_No);
acc_txt = (TextView) findViewById(R.id.text_show_name);
final String editable = String.valueOf(acc_edit.getText());
Log.e("editable value", "" + account_edit_txt);
acc_edit.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int count,
int after) {
if (start >= 2) {
db.open();
account_edit_txt = acc_edit.getText();
db.getName(account_edit_txt);
db.close();
}
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
}
Below function will help you to retrieve account holder name for given account number.
Non need to fecth Acc_No again. Ad you are already have account number which user has inserted.
Also assuming that there will be only one record associated with the give account number.
public String getAccountHolderName(String accountNumber) {
String accountHolderName = null;
Cursor cursor = db.query(DATABASE_TABLE, new String[] { "Cust_Name" },
"Acc_No=?", new String[] { accountNumber }, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
accountHolderName = (cursor.getString(cursor
.getColumnIndex("Cust_Name")));
cursor.close();
}
return accountHolderName;
}
I have a listview with a problem. I want to implement the classic search with the edittext, i am using the addTextChangedListener with TextWatcher(). The Listview gets the elements from a database so I use cursor and simplecursoradapter so i have to use the setFilterQueryProvider. The problem appears when I write something in the edittext, if I write the name of a product it changes all the names of the elements in the list.So i dont know what to do. Appreciate the help.
here is my java code with the listview:
public class Lista_general extends ListActivity {
SimpleCursorAdapter adapter;
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lista_general);
list = getListView();
EditText edit =(EditText)findViewById(R.id.edit);
// open database
AdminSQLiteOpenHelper dbhelper = new AdminSQLiteOpenHelper(
getBaseContext());
SQLiteDatabase db = dbhelper.getReadableDatabase();
// array for SimpleCursorAdapter
String columns[] = new String[] { "PRODUCTO._id",
"nombre","category","CATEGORIAS._id","categoryid" };
String orderBy = "category";
// query database
Cursor c = db.query("PRODUCTO, CATEGORIAS WHERE CATEGORIAS._id = categoryid ",
columns,null,null, null, null, orderBy);
c.moveToFirst();
// array for SimpleCursorAdapter
String from[] = new String[] { "nombre", "category", };
//String from[] = new String[] { "nombre", "categoria", };
int to[] = new int[] { R.id.name, R.id.cate, };
// Adapter
adapter = new SimpleCursorAdapter(getBaseContext(),
R.layout.productos, c, from, to,
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
list.setTextFilterEnabled(true);
//Listener edit text
edit.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
adapter.getFilter().filter(s.toString());
}
});
adapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
// TODO Auto-generated method stub
AdminSQLiteOpenHelper dbhelper = new AdminSQLiteOpenHelper(
getBaseContext());
SQLiteDatabase db = dbhelper.getReadableDatabase();
Cursor mCursor = null;
if (constraint == null || constraint.length () == 0) {
mCursor = db.query("PRODUCTO, CATEGORIAS", new String[] {
"PRODUCTO._id", "nombre","CATEGORIAS._id","category"},
null, null, null, null, null);
}
else {
mCursor = db.query(true,"PRODUCTO, CATEGORIAS", new String[]
{"PRODUCTO._id", "nombre", "category","CATEGORIAS._id"},
"nombre" + " like '%" + constraint + "%'", null,
null, null, null, null);
}
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
});
}
Here is a visual of my error:
first my normal list:
http://i40.tinypic.com/2111k0p.png
after I wrote:
http://i44.tinypic.com/23j04kg.png
It looks like the queries generated in the FilterQueryProvider are not joining the tables properly, so that you end up with every possible combination of PRODUCTO and CATEGORIAS (which are then filtered by PRODUCTO.nombre to give the impression that all the names have changed).
There's also a potential security risk with inserting constraint directly into the query, this opens the door to SQL injection attacks. I'm not sure how serious this is in the context of Android apps, but in for example a PHP web application this would allow anyone to execute any SQL they wished by entering a carefully crafted constraint.
From the answers to this question it looks like a rawQuery() call is needed in order to use SQL JOIN so I would change your queries as follows...
For querying with no filter (i.e. in onCreate(); and in runQuery() where there is no constraint):
cursor = db.rawQuery("SELECT PRODUCTO._id, nombre, category, CATEGORIAS._id FROM PRODUCTO INNER JOIN CATEGORIAS ON PRODUCTO.categoryid = CATEGORIAS._id", null);
For querying with a filter:
String[] params = { constraint.toString() };
cursor = db.rawQuery("SELECT PRODUCTO._id, nombre, category, CATEGORIAS._id FROM PRODUCTO INNER JOIN CATEGORIAS ON PRODUCTO.categoryid = CATEGORIAS._id WHERE nombre LIKE ('%' || ? || '%')", params);
Im having a problem about filtering my listView. Whenever Im trying to input a text in my editText, nothing changed.
Maybe the problem is about this.. my mCursor declaration
Cursor mCursor = myDatabaseHelper.getDirectoryList(null);
I tried to change the parameter from null to "Android", the output shows the term Android in my listView.. but if the parameter is set to null, then every term in my dictionary is displayed in the listView.
I have another code fragment in the same class that calls the getDirectoryList but it seems that the parameter in that fragment is ignored. Please help me..
Here is the code
public class SearchActivity extends Activity{
private DatabaseHelper myDatabaseHelper;
/* Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_layout);
myDatabaseHelper = new DatabaseHelper(this);
try {
myDatabaseHelper.createDataBase();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myDatabaseHelper.openDataBase();
Cursor mCursor = myDatabaseHelper.getDirectoryList(null);
String[] from = new String[]{DatabaseHelper.KEY_CONTENT};
int[] to = new int[]{R.id.text1};
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.row, mCursor, from, to);
startManagingCursor(mCursor);
ListView listContent = (ListView)findViewById(R.id.contentlist);
listContent.setAdapter(cursorAdapter);
listContent.setFastScrollEnabled(true);
listContent.setTextFilterEnabled(true);
EditText etext=(EditText)findViewById(R.id.editText1);
etext.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
ListView listContent = (ListView)findViewById(R.id.contentlist);
SimpleCursorAdapter filterAdapter = (SimpleCursorAdapter)listContent.getAdapter();
filterAdapter.getFilter().filter(s.toString());
//Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
});
myDatabaseHelper = new DatabaseHelper(this);
cursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
//myDatabaseHelper = new DatabaseHelper(this);
//int x = constraint.toString().length();
myDatabaseHelper.getDirectoryList(constraint);
Toast.makeText(getApplicationContext(), constraint, Toast.LENGTH_SHORT).show();
return myDatabaseHelper.getDirectoryList(constraint);
}
});
myDatabaseHelper.close();
and my getDirectory class
public Cursor getDirectoryList (CharSequence constraint) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DB_NAME);
String[] columns = new String[]{KEY_ID, KEY_CONTENT, KEY_DESCRIPTION, KEY_NETWORKING, KEY_HARDWARE, KEY_SOFTWARE, KEY_INTERNET, KEY_TECHNOLOGY};
if (constraint == null || constraint.length () == 0) {
// Return the full list
//String[] columns = new String[]{KEY_ID, KEY_CONTENT, KEY_DESCRIPTION, KEY_NETWORKING, KEY_HARDWARE, KEY_SOFTWARE, KEY_INTERNET, KEY_TECHNOLOGY};Toast.makeText(getContext(), constraint, Toast.LENGTH_SHORT).show();
Cursor cursor = myDataBase.query("MY_TABLE",
columns, KEY_TECHNOLOGY + "='Y'", null, null, null, null);
return cursor;
} else {
String value = constraint.toString()+"%";
Cursor cursor2 = myDataBase.query("MY_TABLE", columns, KEY_CONTENT + " like ?", new String[]{value}, null, null, null);
return cursor2;
}
}
}
I want to ask a little question. I want to know which is the best way I can filter my list view which I am populating from sqlite database and I want to filter it depending on users entered letters in edit text. I'm not showing any code because I have only sqlite statements and that's it. I have to change the sqlite statement which I'm using to populate the database.
So my question is, how can I change my sqlite statement when user entered letters in edit text, and how can I update my listview with the new data filtered with the new sql statement.
I had the same issue and solved it as follows:
//Search text and changed handler
EditText tbSearch = (EditText)findViewById(R.id.android_searchbox);
tbSearch.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
ListView av = getListView();
SimpleCursorAdapter filterAdapter = (SimpleCursorAdapter)av.getAdapter();
filterAdapter.getFilter().filter(s.toString());
}
});
entries.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
return mDbHelper.fetchAllEntries(constraint);
}
});
With this approach you will need a method similar to FetchAllEntries(string sFilter)
/*
* Override to return a Cursor over the list of Entries filtered by a
* constraint
*
* #return Cursor over filtered Entries
*/
public Cursor fetchAllEntries(CharSequence constraint) {
if (constraint == null || constraint.length() == 0) {
// Return the full list
return fetchAllEntries();
} else {
String value = "%" + constraint.toString() + "%";
String[] columns = new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_USER_PROFICIENCY };
return mDb.query(DATABASE_TABLE, columns,
KEY_TITLE + " like ? OR " + KEY_BODY + " like ? ", new String[] { value, value }, null, null,
KEY_TITLE + " ASC ");
}
}
Here I have a table with two columns (title, body)
Check the answer to your previous question, they are very similar : search bar