Method does not search in database? - android

Since morning, I've been trying to figure it out a problem that occured me today, and now, close to midnight I found out the problem.. I have 2 methods in a database, one for registering new users and one for login management purposes. Both use the same parameters:
1- user class, 2- var for user class.
The login management gets text from 2 edittexts and compare their values with database ( something like username/password ) and the other have the basic variables.getVariables() -> insert(table,null,variables).
When I call registra_usuario method, translated for register_user it proceeds like it inserted the info into database. But, when I use the second method busca_acesso (search_access) it gives me an OutofBounds error
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
Does this mean that the database has nothing inside TABLE_USER? Because cursor has a size of 0?
These are my two methods:
public boolean registra_usuario(user user){ <- ***THIS ONE SAYS IT'S NEVER USED***
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
try{
values.put(COLUMN_USER_ENTRY_ID, user.getId());
values.put(COLUMN_USER_USERNAME, user.getUsername());
values.put(COLUMN_USER_PASSWORD, user.getPassword());
values.put(KEY_CREATED_AT , user.getCreated_at());
db.insert(TABLE_USER, null, values);
CharSequence text = "Usuário Cadastrado!!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(null, text, duration);
toast.show();
return true;
}catch (Exception e){
db.close();
return false;
}
}
UPDATED METHOD
public boolean busca_acesso(user user){
SQLiteDatabase db = this.getReadableDatabase();
String [] tabela_user = new String[]{"usuaid","username","password"};
String [] whereargs = new String[]{user.getUsername()};
String compare_user = projeto_db.COLUMN_USER_PASSWORD + " = ?";
Cursor cursor = db.query(TABLE_USER, tabela_user, compare_user, whereargs, null, null, null );
int index = cursor.getColumnIndex(COLUMN_USER_PASSWORD);
cursor.moveToFirst();
while(!cursor.getString(index).equals(user.getPassword())){
cursor.moveToNext();
}
if(cursor.getString(index).equals(user.getPassword())) {
return true;
}else{
return false;
}}
final projeto_db db = new projeto_db(this);
user user = new user(); ***MAIN_ACTIVITY
user.setUsername(username_login);
user.setPassword(password_login);
db.busca_acesso(user);
user user = new user(); ***DIFFERENT ACTIVITY
user.setId();
user.setUsername(editText_username.getText().toString());
user.setPassword(editText_password.getText().toString());
user.setCreated_at(getDateTime());
db.registra_usuario(user);
Both are being called inside onCreate from class and from onClick of Button.
Thanks in advance!

Related

Get User By User Email From SQLite

Here's my getUser mothod :
public User getUser(String Email) {
SQLiteDatabase db = this.getReadableDatabase();
String sql = "SELECT * FROM " + DBContract.Users.TABLE_NAME
+ " WHERE " + DBContract.Users.COL_EMAIL + " = " + Email;
try {
Cursor cursor = db.rawQuery(sql, null);
User user = new User();
// Read data, I simplify cursor in one line
if (cursor != null) {
cursor.moveToFirst();
// Get imageData in byte[]. Easy, right?
user.setUserID(Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBContract.Users._ID))));
user.setUserName(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_NAME)));
user.setUserImage(cursor.getBlob(cursor.getColumnIndex(DBContract.Users.COL_IMAGE)));
user.setUserPassword(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_PASSWORD)));
user.setUserEmail(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_EMAIL)));
user.setUserLocation(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_LOCATION)));
}
cursor.close();
db.close();
return user;
} catch (SQLException e) {
}
return null;
}
User Profile Fragment where i call the getUser:
public class UserHomeFragment extends Fragment {
DBHelper dbHelper;
User user;
ImageView userImageView;
TextView userNameTexView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.user_profile_home_fragment, container, false);
dbHelper = new DBHelper(v.getContext());
user = new User();
userImageView = (ImageView) v.findViewById(R.id.userimg);
userNameTexView = (TextView) v.findViewById(R.id.user_name);
Bundle extras = getActivity().getIntent().getExtras();
assert extras != null;
String userEmail = extras.getString("userEmail");
user = dbHelper.getUser(userEmail);
// Bitmap bitmap = BitmapFactory.decodeByteArray(userImage, 0, userImage.length);
// userImageView.setImageBitmap(bitmap);
userNameTexView.setText(user.getUserName());
return v;
}}
Why the getUser return null ? I've checked there are users at the user's table .
Error Massage:Attempt to invoke virtual method 'java.lang.String com.arfni.ayafinal.model.User.getUserName()' on a null object reference
The issue you are encountering is two-fold.
The prime error is that you need to enclose a string value in quotes otherwise it may be considered as a keyword or an entity (e.g. a table or a column name) or it may cause a syntax error. In short the SQL will not execute and result in an exception.
The compounding error is that the exception is caught and thus the exception is ignored result in no Cursor being created and returned and hence the Cursor variable is never set, so it will be null and then when you then try to close the Cursor it will be null as it outside the scope of the null check.
Furthermore, you also have a potential issue in that if the cursor is not null but is empty, then the moveToFirst will not move to the first row as there isn't a first row to move to. This is indicated by the moveToFirst method returning false. The returned value isn't checked in your code so when you attempt to get the data an exception will occur (along the lines of try to read Index 0 when there are 0 rows) this too being trapped and perhaps leading to confusion.
I'd suggest replacing the getUser method with the following :-
public User getUser(String Email) {
SQLiteDatabase db = this.getReadableDatabase();
String sql = "SELECT * FROM " + DBContract.Users.TABLE_NAME
+ " WHERE " + DBContract.Users.COL_EMAIL + " = " + Email;
Cursor cursor = db.rawQuery(sql, null);
User user = new User();
// Read data, I simplify cursor in one line
if (cursor.moveToFirst()) {
// Get imageData in byte[]. Easy, right?
user.setUserID(Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBContract.Users._ID))));
user.setUserName(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_NAME)));
user.setUserImage(cursor.getBlob(cursor.getColumnIndex(DBContract.Users.COL_IMAGE)));
user.setUserPassword(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_PASSWORD)));
user.setUserEmail(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_EMAIL)));
user.setUserLocation(cursor.getString(cursor.getColumnIndex(DBContract.Users.COL_LOCATION)));
}
cursor.close();
db.close();
return user;
}
Notes
If the SQL fails then the exception stop the App. (i.e try/catch has bee removed).
Should the SQL result in nothing being extracted then an empty cursor is returned (you do not get a null Cursor except if you force it), as such the check for a null Cursor has been removed, rather than moving it so that it will not result in an exception.
user will either be null (no rows in the Cursor) or the user will be populated so there is no need to return null.

retrieve data from database what next?

ok I just followed an instruction that I should do this to retrieve sql data from database but it just cuts to there so far I have this inside my databasehelper class.
public void getIconResource(String tblName)
{
SQLiteDatabase db = this.getReadableDatabase();
String getresource = "Select * from " + tblName;
Cursor cursor = db.rawQuery(getresource,null); //null for conditions
if(cursor.moveToFirst())
{
do
{
int resource = cursor.getInt(3);
}
while (cursor.moveToNext());
}
db.close();
}
So somehow this does is it get all the values of my tables 4th column which contains an int... how do I retrieve the value in my MainActivity and save it in an array of integers?
just add everything in a ArrayList and return the arraylist
simply call the method in your main activty
public ArrayList<Integer> getIconResource(String tblName)
{
SQLiteDatabase db = this.getReadableDatabase();
String getresource = "Select * from " + tblName;
Cursor cursor = db.rawQuery(getresource,null); //null for conditions
ArrayList data= new ArrayList<>();
if(cursor.moveToFirst())
{
do
{
int resource = cursor.getInt(3);
data.add(resource);
}
while (cursor.moveToNext());
}
db.close();
}
return data;
}
Well, as you have it, the variable resource is scoped only to the while loop. Even if it wasn't it would constantly get overwritten on each loop iteration.
Instead, you should declare a collection higher up and Add each value to it during your while loop. You could also redefine your function to return the collection if integers.
public List<int> getIconResource(String tblName)
{
SQLiteDatabase db = this.getReadableDatabase();
List<int> myVals = new List<int>();
String getresource = "Select * from " + tblName;
Cursor cursor = db.rawQuery(getresource, null); //null for conditions
if (cursor.moveToFirst())
{
do
{
myVals.Add(cursor.getInt(3));
}
while (cursor.moveToNext());
}
db.close();
return myVals;
}
Also, as a note... string concatenation of a SQL query is a recipe for disaster. Look up SQL Injection and best practices to avoid it before continuing further. It is worth the time to get into good habits early on.
EDIT / ADDENDUM
Unless you also limit your result set returned from your table query, you will be getting every record. The function you have here really has no practical use and would likely cause more problems than any benefits it may have. I would suggest, as an example of a more usable function that returns a specific IconResource based on the IconId:
public int getIconResource(int iconId)
{
SQLiteDatabase db = this.getReadableDatabase();
String getresource = "select IconResource from IconTable where IconId = ?";
PreparedStatement pstmnt = db.prepareStatement(getresource);
pstrmnt.setString(1, iconId);
ResultSet rset = db.executeQuery();
int iconResource;
if (rset.next())
iconResource = rset.getInt("IconResource");
db.close();
return iconResource;
}
Of course, the above is making assumptions of your table structure.
Using the above, in your code elsewhere, you would simply call this function with the IconId and use the output however needed:
int iconResource = getIconResource(5); // returns the IconResource for IconId = 5
The above prevents any possible SQL Injection attacks by using a parameterized query and avoiding the use of dynamic concatenated strings sent to your SQL server.
You may try out the following code:
public List<Integer> getIconResource(String tblName)
{
List<Integer> list = new ArrayList<Integer>();
list.clear();
SQLiteDatabase db = this.getReadableDatabase();
String getresource = "Select * from " + tblName;
Cursor cursor = db.rawQuery(getresource,null); //null for conditions
if(cursor.moveToFirst())
{
do
{
int resource = cursor.getInt(3);
list.add(resource);
}
while (cursor.moveToNext());
}
db.close();
return list;
}
Then call this method in MainActivity and store the List in another Integer type list.
databasehelper dbhelper;
List<Integer> newList = dbhelper.getIconResource("Your tablename");
fot(int i = 0 ; i< newList.size() ; i++){
int yourValue = newList(i);
}

my sqlite cursor returns empty result for a query

I have a small function for checking to see if a records already exists in my sqlite database. There is data in the database that should match the query, i have verified this by opening up the database.But i get an empty result.
Below is the function, it takes in a parameter and uses that as the search parameter. i have also verified that the parameter is correct.
public boolean checkParent(String email)
{
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = null;
try
{
res = db.rawQuery("SELECT * FROM parents WHERE email = ' " + email + " ' ",null);
res.close();
}
catch (Exception ex)
{
Log.e("Error checking parent", ex.toString());
}
if(res == null)
{
return true;
}
else
{
return false;
}
}
Right way to pass argument in rawQuery method.
db.rawQuery("SELECT * FROM parents WHERE email = ?",new String[]{email});
You are checking whether the cursor object res is null. This will never happen; rawQuery() always returns a cursor object.
You have to check whether the cursor is empty, i.e., whether the cursor actually contains any rows. To do this, call a method like moveToFirst() and check if it succeeds.
Or even better, use a helper function that does handle the cursor for you:
public boolean checkParent(String email)
{
SQLiteDatabase db = this.getReadableDatabase();
long count = DatabaseUtils.queryNumEntries(db,
"parents", "email = ?", new String[]{ email });
return count > 0;
}

How to check the value already excists or not in sqlite db in android?

In my application I am saving a bill number in SQLite database. Before I add a new bill number how to check if the bill number exists in the DB.
My main class code is,
String bill_no_excist_or_not = db.billno_exist_or_not(""+et_bill_number.getText().toString());
Log.v("Bill No", ""+bill_no_excist_or_not);
My DB Code,
String billno_exist_or_not(String bill_number){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_BILL_DETAILS, new String[] { KEY_BILL_NUMBER }, KEY_BILL_NUMBER + "=?"
+ new String[] { bill_number }, null, null, null, null);
//after this i don't know how to return the values
return bill_number;
}
I don't know how to check the values which is already available or not in DB. Can any one know please help me to solve this problem.
Here is the function that helps you to find whether the value is available in database or not.
Here please replace your query with my query..
public int isUserAvailable(int userId)
{
int number = 0;
Cursor c = null;
try
{
c = db.rawQuery("select user_id from user_table where user_id = ?", new String[] {String.valueOf(userId)});
if(c.getCount() != 0)
number = c.getCount();
}
catch(Exception e) {
e.printStackTrace();
} finally {
if(c!=null) c.close();
}
return number;
}
Make your KEY_BILL_NUMBER column in your table UNIQUE and you can just insert using insertWithOnConflict with the flag SQLiteDatabase.CONFLICT_IGNORE

SQLite Android Delete database row

I want to delete a row in the sqlite data base. Please refer to the sql datastructure and my current delete method which is not working.
private static final String[] TABLE_MESSAGE_FIELDS = {
FIELD_USERNAME, "CHAR(32) NOT NULL",
FIELD_READED, "INTEGER(1) NOT NULL",
FIELD_SEND, "INTEGER(1) NOT NULL",
FIELD_TIMESTAMP, "INTEGER(64) NOT NULL",
FIELD_CONTENT, "TEXT NOT NULL",
};
//more tables
private static final String[] TABLE_MESSAGE_INDEXS = {
FIELD_USERNAME, FIELD_READED,
};
This is the structure, basically it is an instant messenger (IM) android app, so the user can send and receive message. While the operations like receiving message etc are working, the option to delete is not.
I am looking to delete the whole conversation between a user, in other words not the individual message in a conversation, but the whole conversation itself. I guess the right way is to find out the user name, and delete the entire row. The table TABLE_MESSAGE_FIELDS is contains the 5 columns indicating the message, I want to delete that entire conversation.
This is how I go about it
public boolean deleteMessage(String userName)
{
SQLiteDatabase database = mLocalDatabase.getWritableDatabase();
final String[] COLUMNS = { FIELD_TIMESTAMP, FIELD_CONTENT };
final String SELECTION = FIELD_USERNAME + "=?" ;
//database.beginTransaction();//do i need this?
boolean result= database.delete(TABLE_MESSAGE,SELECTION,new String[]{userName})>=0;
//database.endTransaction();//??
database.close();
return result;
}
Assuming you have correctly declared create query and everything works, your code looks correct so reason why your row(s) are not deleted from database may be that you provided wrong username i.e. each row in database not equal with given userName. Try to print your variable before perform delete action.
Then, you mentioned transaction. If you used it, you need to call
setTransactionSuccessful()
or your changes will be rolled back and database will be back to state before transaction.
boolean result = false;
db.beginTransaction();
result = db.delete(TABLE_MESSAGE, SELECTION, new String[] {userName}) > 0;
db.setTransactionSuccessful();
db.endTransaction();
public boolean deleteMessage(String userName) {
boolean result = false;
if (userName != null && !userName.equals("")) {
userName = userName.trim();
SQLiteDatabase database = mLocalDatabase.getWritableDatabase();
// final String[] COLUMNS = { FIELD_TIMESTAMP, FIELD_CONTENT };
// final String SELECTION = FIELD_USERNAME + "=?" ;
// database.beginTransaction();//do i need this?
String whereCondition = FIELD_USERNAME + "=" + userName;
result = database.delete(TABLE_MESSAGE, whereCondition, null);
// database.endTransaction();//??
database.close();
}
return result;
}

Categories

Resources