AutoCompleteTextView filter not working - android

I have two AutoCompleteTextView (group and instalation).
After I choose group, Instalation should filter the information depending on the group but it's not working.
If in the sql line i take out the WHERE part it works fine (but shows me all the information and i don't want that).
List<String> instalacao = new ArrayList<String>();
Cursor cursor=mydb.rawQuery("SELECT DISTINCT instalacao FROM registo WHERE grupo like '"+txGrupo.getText().toString()+"';",null);
while (cursor.moveToNext()){
instalacao.add(cursor.getString(cursor.getColumnIndex("instalacao")));
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.select_dialog_item,instalacao);
txInstalacao.setThreshold(0);
txInstalacao.setAdapter(adapter);
The dropdown:
txInstalacao.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
txInstalacao.showDropDown();
}
});
What am I doing wrong?

If you want to match a prefix, you should use '%' at the end of the parameter.
"WHERE grupo like '" + txGrupo.getText().toString() + "%'"
As an aside, I would strongly recommend using the query() method instead of rawquery(). Building an SQL statement like this will lead to problems (for example if the contents of txGrupo contains quotes).

I figured out why it wasnt showing anything. When i start the intent i call the method, at this time the TextField is empty so it has nothing there. when i choose my group i have to refresh the method and i was not doing that :)

Related

Should I use extra arraylist for efficient data operations while using Sqlite db with recyclerviews?

I hope straightforward questions.
1) I managed to get the data from Sqlite db and showing them on recyclerview. The question is for example when i click on the recyclerview items and do some operations (for example copying the content or updating) is it better to use an arraylist and get the data first when application loads then do the operations on this arraylist elements (then notifying db eventually)?
2) If there is no need for extra arraylist on onContextItemSelected() operations while clicking recyclerview item again, i ve some trouble in choosing the element and its values.
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.idshare :
//implicit intent
shareImplicitIntent();
return true;
......
for the shareImplicitIntent() method
private void shareImplicitIntent() {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Cursor cursor=WordListOpenHelper.mReadableDB.rawQuery("SELECT * FROM
diary", null);
cursor.moveToPosition(XYZ);
Entry_Model entry_model= new Entry_Model();
entry_model.setmEntry(cursor.getString(cursor.getColumnIndex(WordListOpenHelper.KEY_ENTRY)));
String title = entry_model.getmEntry(); ......
basically using cursor and getting the title of the cursor at XYZ position.
But how can I choose that XYZ position ?
Working hours on it but couldnt find a clue. Please help me.Thanks a lot
To answer my question myself, shortly no, for example for getting input from the user and putting them in the arraylist then doing the database operations on the arraylist not very useful nor necessary. (Yet if your database is planned to hold only small amount of entries though you can use arraylist/linkedlists for fast CRUD manipulations on the recyclerview adapter).
For the second part of the question it s easy to copy the content of the clicked recyclerview element by creating setonclicklistener in the viewholder constructor of the viewholder innerclass, for example;
(note unlike in the example you dont have to use contentresolver if you dont plan to share the datas in the database with other applications)
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
int pos =getAdapterPosition();
String entry = "";
String[] mProjection =
{ Contract.WordList.KEY_ENTRY, // Contract class constant for the _ID column name };
Cursor cursor = mContext.getContentResolver().query(Uri.parse(
queryUri), mProjection, null, null, sortOrder);
if (cursor != null) {
if (cursor.moveToPosition(pos)) {
int indexEntry = cursor.getColumnIndex(Contract.WordList.KEY_ENTRY);
entry = cursor.getString(indexEntry);
}
}
Toast.makeText(v.getContext(), "copied entry is " + entry, Toast.LENGTH_LONG).show();
return false;
}
});

Searching a SQLite database using SearchView

I have an actionbar SearchView that I'm trying to get working to let users search a database of wines.
I'm trying to get it to search while the user types, like if they type "na" it'll show all results that contain "na" and so on.
Here is my menu search button if statement:
if (id == R.id.action_wine_search) {
SearchView searchView = getActivity().findViewById(R.id.action_wine_search);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String newText) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
mCursorAdapter.getFilter().filter(newText);
//mCursorAdapter is selecting id,name,price,etc. columns from the table
wineListView.setAdapter(mCursorAdapter);
return false;
}
});
}
As I understood it (which I might just be thinking about this in the wrong way) is that the filter is getting the text from the SearchView and is applying that text to the CursorAdapter.
This isn't doing anything though. The list doesn't change at all no matter what you type in.
I followed along to a youtube video for this. I don't quite understand how it was applying to the CursorAdapter though.
I ended up attempting it on my own (this also fails, the list doesn't change at all):
public boolean onQueryTextChange(String newText) {
SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
//Selecting what details I want to put into each row in the list
String[] projection = {
WineContract.WineEntry.COLUMN_ID,
WineContract.WineEntry.COLUMN_WINE_NAME,
WineContract.WineEntry.COLUMN_WINE_PRICE,
WineContract.WineEntry.COLUMN_WINE_RATING,
WineContract.WineEntry.COLUMN_WINE_STORE,
WineContract.WineEntry.COLUMN_WINE_IMAGE,
WineContract.WineEntry.COLUMN_WINE_THUMBNAIL};
//I want to return the row where the name is equal to newText (which is what the user types into the SearchView
String selection = WineContract.WineEntry.COLUMN_WINE_NAME + " = ?";
String[] selectionArgs = {newText};
Cursor cursor = db.query(WineContract.WineEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
mCursorAdapter = new WineCursorAdapter(getActivity(), cursor);
wineListView.setAdapter(mCursorAdapter);
return false;
}
});
Could I get some help in understanding how this is supposed to work?
I looked at the video you linked and unfortunately, it looks like the video demonstrates how to achieve this search functionality in a pretty different approach. Namely, they use an ArrayAdapter<String> that has some built-in implementation of a Filter that allows them perform substring matching on a simple list of results.
Your case of using a CursorAdapter to search against a database unfortunately won't work in this manner. A CursorAdapter returns a Cursor object which is really just an "facade" for retrieving the row data/results returned by a database query. In other words, the CursorAdapter doesn't know how to "filter" anything, you have to specify what to do when a filter is applied. For instance, you would need to implement something like this:
adapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence query) {
// Run some database query, given this "query" String and return a Cursor
return searchDatabase(query);
}
});
You sort of had the right idea your second snippet of code to implement a search query. However, a standard SQLite database table is only going to let you retrieve rows that match an exact criteria (basically what you've already coded above) and not a substring match like what you probably want.
Fortunately, there is a way to get full-text search in an SQLite database so you can search and match queries to substrings and partial queries, probably what you actually want. You can use something called an SQLite virtual table that implements a scheme like FTS3 to support searching. There is a great tutorial on the official Android docs linked below that will show you exactly how to achieve this:
https://developer.android.com/training/search/search.html
I've used this method in the past several times to implement searching across a database. It's probably a bit more work than you expected to change out your current database helper but this is the way I know how to do it. Let me know if anything doesn't make sense!
Also I do you hope take into account my comments above about restructuring your code because I'm sure you want to write an app that considers good performance!
I'm not sure if this would suit be all I do for a similar is have an EditText with a textChangedListener that just drives a a query, gets an updated cursor and uses swapCursor on the ListView adapter. The query itself uses Like to get all occurences e.g. that have na.
This the Listener setup Code :-
/**************************************************************************
* addFilterListener - Add a Listener to filter the ListView
* i.e. as characters are typed then the ListView
* is filtered according to the characters input
* This is done by using LIKE '%<characters>%'
*
*/
public void addFilterListener() {
inputproductfilter.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
productfilter = DBProductsTableConstants.PRODUCTS_NAME_COL_FULL +
SQLLIKECHARSTART +
inputproductfilter.getText().toString() +
SQLLIKECHAREND;
plcsr = dbproductmethods.getExpandedProducts(productfilter,orderby);
productlistadapter.swapCursor(plcsr);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
It uses :-
public static final String SQLLIKECHARSTART = " LIKE '%";
public static final String SQLLIKECHAREND = "%' ";
and for below
public static final String SQLAS = " AS ";
Not that it's all that relevant here's getExpandedproducts :-
/**************************************************************************
*
* #param filter filter string less WHERE keyword
* #param order order String less ORDER and BY kewords
* #return Cursor containing Expanded products
*/
Cursor getExpandedProducts(String filter, String order) {
Cursor rv;
String[] columns = new String[] {
DBProductsTableConstants.PRODUCTS_ID_COL_FULL,
DBProductsTableConstants.PRODUCTS_NAME_COL_FULL,
DBProductsTableConstants.PRODUCTS_NOTES_COL_FULL,
DBProductsTableConstants.PRODUCTS_STORAGEORDER_COL_FULL,
DBProductsTableConstants.PRODUCTS_STORAGEREF_COL_FULL,
DBStorageTableConstants.STORAGE_ID_COL_FULL +
SQLAS + DBStorageTableConstants.STORAGE_ALTID_COL,
DBStorageTableConstants.STORAGE_NAME_COL_FULL,
DBStorageTableConstants.STORAGE_ORDER_COL_FULL
};
String table = DBProductsTableConstants.PRODUCTS_TABLE +
SQLLEFTJOIN +
DBStorageTableConstants.STORAGE_TABLE +
SQLON +
DBProductsTableConstants.PRODUCTS_STORAGEREF_COL_FULL +
" = " +
DBStorageTableConstants.STORAGE_ID_COL_FULL;
rv = db.query(table,columns,filter,null,null,null,order);
return rv;
}
e.g. full list :-
and then with na entered in the filter :-

Error while fetching data from a db

I have a table, c_question in which I stored some questions with this structure
autoincrement column _id,
question,
option1,
option2,
option3,
correct_answer
Now I want to retrieve the question in a TextView and the answers in a RadioGroup.
If the user selects the correct answer, then the question and options will change
in the same page.
Logcat: fatal exception at main ..... cursorIndexOutOfBoundException
The output shows the last data (question with answers) I entered in the db and if I click any answer, the app crashes.
String row="SELECT* FROM c_question";
final Cursor c=db.rawQuery(row, null);
c.moveToFirst();
if(c.moveToFirst())
{
do
{
tv1.setText(c.getString(1));
r0=(RadioButton)findViewById(R.id.radio0);
r0.setText(c.getString(2));
r1=(RadioButton)findViewById(R.id.radio1);
r1.setText(c.getString(3));
r2=(RadioButton)findViewById(R.id.radio2);
r2.setText(c.getString(4));
k.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
int idd=r.getCheckedRadioButtonId();
r0=(RadioButton)findViewById(idd);
String r=r0.getText().toString();
if(r.equals(c.getString(5)))
{
Toast.makeText(QuestionsOn.this, "correct!!!", 123).show();
;
} else
Toast.makeText(QuestionsOn.this, "Incorrect!!!", 123).show();
}
});
} while(c.moveToNext());
}
Output showing the last data(Question with options) I entered in DB
That's what you get when you update the save views in a loop; only the last "row" will get shown.
If you want to show a list of data from the database, you need some Adapter class in a ListView / ViewPager
and if I click any option, the app crashes...
According to the error, c.getString(5) doesn't exist, so seems like you didn't create your database with the correct number of columns.

SQLite database insert is somehow vanishing?

I'm having a very strange issue on my Android app wherein when I am inserting a value to a DB table, the first entry is disappearing somehow. However, any subsequent entries are appearing fine.
To be a little more specific, part of my application allows users to create a simple log where they enter some text and when they save it, it shows up on a list of log entries. However, when I try to insert the very first entry to an empty table, that entry is not being displayed, nor does the database indicate there is any data when I query for a count.
Interestingly enough, when I look at the return of the database insert call (SQLiteDatabase.insert()) I see a valid row number returned. In fact, when I look at any log entry I've saved to the database, the row number is correctly incrementing. As per the docs, my understanding is that if a non-negative number is returned, the insert was successful.
Here is the code that takes the result of the EditText from my AlertDialog, creates a new log entry, and calls the insert method:
newPainLogEntryDialog.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//make new pain log entry
PainLog painLog = new PainLog();
painLog.setPainEntry(input.getText().toString());
painLog.setPainDateTime(Calendar.getInstance());
Database.init(PainLogTab.this.getActivity());
Database.createPainLog(painLog);
updatePainLogList();
//display success to user
Toast.makeText(PainLogTab.this.getActivity(),
"Log entry saved", Toast.LENGTH_SHORT).show();
}
});
The code for Database.createPainLog():
public static long createPainLog(PainLog painLog) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_PAINLOG_ENTRY, painLog.getPainEntry());
cv.put(COLUMN_PAINLOG_DATETIME, painLog.getPainDateTimeString());
return getDatabase().insert(PAINLOG_TABLE, null, cv);
}
And the last call before the Toast message is updatePainLogList(), which gets all the DB entries:
public void updatePainLogList(){
Database.init(PainLogTab.this.getActivity());
final List<PainLog> painLogs = Database.getAllPainLogs();
painLogListAdapter.setPainLogs(painLogs);
Log.d(getClass().getSimpleName(), "number of painLogs found: " + painLogs.size());
getActivity().runOnUiThread(new Runnable() {
public void run() {
// reload content
PainLogTab.this.painLogListAdapter.notifyDataSetChanged();
if(painLogs.size() > 0){
getView().findViewById(android.R.id.empty).setVisibility(View.INVISIBLE);
}else{
getView().findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
}
}
});
}
And for completion sake, the body of the getAll() and its accompanying method getCursor():
public static Cursor getPainLogCursor() {
String[] columns = new String[] {
COLUMN_PAINLOG_ID,
COLUMN_PAINLOG_ENTRY,
COLUMN_PAINLOG_DATETIME
};
return getDatabase().query(PAINLOG_TABLE, columns, null, null, null, null,
null);
}
public static List<PainLog> getAllPainLogs() {
List<PainLog> painLogs = new ArrayList<PainLog>();
Cursor cursor = Database.getPainLogCursor();
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
PainLog painLog = new PainLog();
painLog.setId(cursor.getInt(IDX_PAINLOG_ID));
painLog.setPainEntry(cursor.getString(IDX_PAINLOG_ENTRY));
painLog.setPainDateTime(cursor.getString(IDX_PAINLOG_DATETIME));
painLogs.add(painLog);
}
}
cursor.close();
return painLogs;
}
Now with some code I can explain what debugging steps I have taken thus far. As mentioned above, when I look at the return of the DB insert, I get a positive, non-zero number. However, when I try to print the number of logs in the immediately following update method (no deletes or anything get called en route), it displays 0, and indeed if I follow the Cursor I find that it never enters the loop which adds logs to the list which is displayed, also indicating it is not picking up the entry.
I have tried to set the DB insert in a transaction so that I can manually commit, but this does not help either. What makes this more interesting to me is that I have similar functionality elsewhere in my app where I save user preferences and display them in a list, and this does not suffer from the same problem...I have compared against this code and couldn't find any differences that would cause it.
To sum it up, my question is two-fold: why is only my first insert on an empty table showing up as not there, while all following ones are fine?; why am I getting a valid return from the database insert and yet immediately following the insert when I query for that data it is missing?
Thanks in advance for any help you can provide :)
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This skips the first row in cursor. moveToFirst() moves to the first row and moveToNext() moves to the next one, skipping the first one.
You can replace this with just while (cursor.moveToNext()). When you get your cursor from a query, it is placed at index -1 first i.e. at the row before the first one.
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This would be the best solution for it....

changing text into database values

when button is pressed i want to the text to change to the database collumn values, i know its wrong but here is the code:
private void MostraDados() {
// TODO Auto-generated method stub
final TextView text = (TextView) findViewById(R.id.tvUSUARIO);
Button mostrar = (Button) findViewById(R.id.bMostrar);
mostrar.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
db = openOrCreateDatabase("dbtest.db", Context.MODE_PRIVATE, null);
String q = "SELECT * FROM dbtest.db WHERE usuarioorigem='";
text.setText(q);
//text.execSQL("DROP COLUMN IF EXISTS usuarioorigem");
}
});
}
Your code is missing some critical parts for example a DatabaseClass that manages the cursor and database.
private void MostraDados() {
final TextView text = (TextView) findViewById(R.id.tvUSUARIO);
Button mostrar = (Button) findViewById(R.id.bMostrar);
mostrar.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// our missing a database helper
MyDatabaseClass dbhelper = new MyDatabaseClass();
dbhelper.open();
Cursor result = dbhelper.doMyQuery();
String mystring = result.getString(0);
text.setText(mystring);
dbhelper.close();
}
});
....
public class WorkoutDbAdapter {
....
public Cursor doMyQuery()
{
return this.mDb.query( yourQuery );
}
}
This is the minimum you'd need and even with the above i'm missing a lot of the smaller detail. Search for some tutorials on creating and using Databases.
Essentially however you need to get the cursor back, set the position of the cursor, or cursor.moveNext() and then get the value that you can assign to the textField.
Your source code lacks a correct call to a database and access to the cursor. Hopefully you'll find some decent tutorials that will flesh the rest out for you.
The SQL is not written correctly. You must SELECT from a column. And you're passing the query string the the text view. You should first review how to query the database with the cursor, and how to retrieve what you want from the cursor.
So I would look into how to use the curosr, all of that's available in the Android docs, and you might want to try the API demos in the emulator I'm sure you can learn how to work with the cursor there as well. So look here, http://developer.android.com/reference/android/database/Cursor.html.
And here, Is Android Cursor.moveToNext() Documentation Correct?.
After getting the cursor, you could do something like this:
while(c.moveToNext(){
text.setText(c.getString(0))
}

Categories

Resources