attempt to reopen an already-closed object: sqlitequery - android

So essentially I am querying the DB twice. I don't understand where this error is really coming from because I am not closing the DB anywhere. The code that returns the error runs like this. I've checked around and I just having seen a case like mine.
BeaconHandler pullAllDB = new BeaconHandler(this);
try {
List<Beacon> beaconsShown = pullAllDB.getAllBeacons();
for (final Beacon bn : beaconsShown) {
try {
int messageCount = pullAllDB.getMessageCount();
Log.d("Message", messageCount + " Messages Found");
if (messageCount > 0) {
//Do Something
} else {
// Do Nothing
}
}
catch (Exception e) {
e.getStackTrace();
Log.e("Message", e.getMessage());
}
}
}
And the code doing the queries...
public int getBeaconsCount() {
String countQuery = "SELECT * FROM " + TABLE_BASIC_BEACON;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
cursor.close();
// return count
return cursor.getCount();
}
public int getMessageCount() {
String mcountQuery = "SELECT * FROM " + MESSAGE_BEACON;
SQLiteDatabase mdb = this.getReadableDatabase();
Cursor mcursor = mdb.rawQuery(mcountQuery, null);
mcursor.close();
// return count
return mcursor.getCount();
}

You should post a logcat if you are getting an error. It helps to see which line is causing your problem.
From the Android docs.
close()
Closes the Cursor, releasing all of its resources and making
it completely invalid.
Your call to mcursor.getCount() after you have closed it is likely causing the error
Maybe try something like this.
int count = mcursor.getCount();
mcursor.close();
// return count
return count ;

I'm assuming here that pullAllDB is your database object which contains the code doing the queries. In that case, before the line, List<Beacon> beaconsShown = pullAllDB.getAllBeacons();, you should do something like pullAllDB.open(); and do pullAllDB.close(); after you are done running queries.
So all in all, your function would look like..
try {
//open the database class here
pullAllDB.open();
List<Beacon> beaconsShown = pullAllDB.getAllBeacons();
for (final Beacon bn : beaconsShown) {
try {
int messageCount = pullAllDB.getMessageCount();
Log.d("Message", messageCount + " Messages Found");
if (messageCount > 0) {
//Do Something
} else {
// Do Nothing
}
}
catch (Exception e) {
e.getStackTrace();
Log.e("Message", e.getMessage());
}
//close the database here
pullAllDB.close();
}
}

Related

Android cursor.getColumnNames() doesn't contain the new added column

I use code below to test if a column exists:
public static boolean isColumnExists(String tableName, String columnName) {
Cursor cursor = null;
try {
SQLiteDatabase db = getDatabase();
cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null);
String[] cloNames = cursor.getColumnNames();
if (cloNames != null) {
for (String temp : cloNames) {
if (columnName.equalsIgnoreCase(temp)) {
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor && !cursor.isClosed()) {
cursor.close();
}
}
return false;
}
The column hello2 doesn't exist in initial state, after adding column to database, the following test still tells that the column doesn't exist, and the second try will cause an error about duplicate column, which is not correct.
if (!isColumnExists("PositionCache", "hello2")) {
// First try will insert column to database
getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
}
if (!isColumnExists("PositionCache", "hello2")) {
// Second try will give and error about duplicate column of hello2
getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
}
I need to know the reason about such an abnormal phenomenon.
If I change SELECT * FROM to select * from in method isColumnExists then everything become normal.
I believe the reason is that SQLite (I strongly suspect the Cursor, so more correctly the Android SQLite aspect of the SDK) is cacheing data (perhaps because the underlying data is never retrieved from the Database as there is no need to get the data (as far as the Cursor is concerned)).
I've tried various checks including putting breakpoints in, checking the result of getColumnnames, and making the method non-static.
As soon as I add an alternative check using the PRAGMA table_info(*table_name*); then the column exists.
As such I'd suggest using the following :-
public static boolean isColumnExistsOld(String tableName, String columnName) {
Cursor csr = getDatabase().rawQuery("PRAGMA table_info(" + tableName + ")",null);
while(csr.moveToNext()) {
if (csr.getString(csr.getColumnIndex("name")).equalsIgnoreCase(columnName)) {
return true;
}
}
return false;
/*
Cursor cursor = null;
try {
SQLiteDatabase db = getDatabase();
cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
cursor.moveToFirst();
String[] cloNames = cursor.getColumnNames();
if (cloNames != null) {
for (String temp : cloNames) {
if (columnName.equalsIgnoreCase(temp)) {
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor && !cursor.isClosed()) {
cursor.close();
}
}
boolean rv = colfound;
return false;
*/
}
Note your code has been left in but commented out.
I believe that evaluating forces the cache to be refreshed (i.e. I tried this an yep it does dynamically change to include the column).

Running a raw sqlite query

I am trying to run this query but it just isn't working and i can't seem to find what is wrong with it.
public boolean verifyUser(String name , String pword){
boolean result = false;
SQLiteDatabase db = this.getReadableDatabase();
try {
Cursor res = db.rawQuery( "select * from user where username="+name+" and password="+pword+"", null );
int count = res.getCount();
res.moveToFirst();
if (count == 0)
{
result = false;
}
else{
result = true;
}
}
catch (SQLiteException se ) {
Log.e(getClass().getSimpleName(), "Could not log in");
}
return result;
//return true;
}
In SQL, you need to put your string literals in 'single quotes'. Better yet, use parameters:
Cursor res = db.rawQuery( "select * from user where username=? and password=?",
new String[] { name, pword } );
Checked this, it's edited of your code.
public boolean verifyUser(String name , String pword){
boolean result = false;
SQLiteDatabase db = this.getReadableDatabase();
try {
Cursor res = db.rawQuery( "select * from user where username='"+name+"' and password='"+pword+"'", null );
int count = res.getCount();
//res.moveToFirst(); //Remove this line (It may be crashing because of this line.)
if (count == 0)
{
result = false;
}
else{
res.moveToFirst();
result = true;
}
}
catch (SQLiteException se ) {
Log.e(getClass().getSimpleName(), "Could not log in");
}
return result;
//return true;
}
Copy and paste the following query
select * from user where username='"+name+"' and password='"+pword+"'"
actually you are missing the Single Quotes

get and set boolean type from database android sqlite

I'm new to android development so I don't have much idea to how can handle this problem.
I have a problem with extract part in my codes, I want to get all rows of my table but here is some problem with boolean type
public ArrayList<UserMealUnit> getUserMealUnit() {
ArrayList<UserMealUnit> result = null;
SQLiteDatabase myDataBase = null;
Cursor cursor = null;
try {
myDataBase = openHelper.getWritableDatabase();
cursor = myDataBase.query(TABLE_USERMEALUNIT, new String[] { "*" }, null, null,
null, null, null);
if (cursor.moveToFirst()) {
result = new ArrayList<UserMealUnit>();
do {
result.add(extractUserMealUnit(cursor));
} while (cursor.moveToNext());
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
finally {
if (cursor != null) {
cursor.close();
}
myDataBase.close();
}
return result;
}
//extract
private UserMealUnit extractUserMealUnit(Cursor cursor) {
UserMealUnit usermealunit = new UserMealUnit();
boolean value1;
usermealunit.setMealid(cursor.getInt(cursor.getColumnIndex(TABLE_USERMEALUNIT_ID)));
usermealunit.setBreakfast(cursor.getInt(cursor.getColumnIndex(TABLE_USERMEALUNIT_BREAKFAST)));
return usermealunit;
}
breakfast type is boolean but cursor.getInt(cursor.getColumnIndex(TABLE_USERMEALUNIT_BREAKFAST) return int and here is the problem. I search about this problem but cant find anything useful. can any one help me?
There is no boolean type in SQLite database. Instead, you must save 0 as false and 1 as true. Thus to read your value
final boolean breakfast = cursor.getInt(cursor.getColumnIndex(TABLE_USERMEALUNIT_BREAKFAST) != 0;
When using the ContentValues the system will convert the Boolean into int for you automatically when saving.
contentValues.put(TABLE_USERMEALUNIT_BREAKFAST, booleanValue);

Method calls a function to return a value and then the rest of the first function is skipped

I have a function which is supposed to add a new record to the SQLite database. This function will then call a function to return an int to a variable, then the rest of the code is skipped and it goes straight into the finally statement.
Below is the method.
SQLiteDatabase myDb = null;
if (type.equals("Website"))
{
details = formatUrl(details);
}
try
{
myDb = context.openOrCreateDatabase("PasswordManager", Context.MODE_PRIVATE, null);
int rowId = common.getNextID("password");
//ALL OF THIS CODE IS SKIPPED
ContentValues cv = new ContentValues();
cv.put("id", rowId);
cv.put("category", category);
cv.put("company", Encryption.encrypt(company));
cv.put("loginAction", Encryption.encrypt(details));
cv.put("username", Encryption.encrypt(username));
cv.put("password", Encryption.encrypt(password));
cv.put("type", type);
cv.put("appName", "N/A");
myDb.insert("password", null, cv);
}
catch (SQLiteException ex)
{
common.showBasicAlertDialog("Something has gone wrong.\n\nWe will fix this as soon as we can", false);
Log.e("Database Errror", ex.toString());
return false;
}
catch (SQLException ex)
{
common.showBasicAlertDialog("Something has gone wrong.\n\nWe will fix this as soon as we can", false);
Log.e("SQL Error", ex.toString());
return false;
}
finally
{
//IT GOES STRAIGHT INTO THIS CODE AFTER THE GETNEXTID METHOD RETURNS
if (myDb.isOpen())
{
myDb.close();
return true;
}
}
return false;
Below is the code for the getNextId() function
public int getNextID(String table)
{
int nextID = 1;
Cursor cursor = null;
SQLiteDatabase myDB = null;
try
{
myDB = context.openOrCreateDatabase("PasswordManager", Context.MODE_PRIVATE, null);
cursor = myDB.rawQuery("SELECT id FROM "+table+" ORDER BY id DESC LIMIT 1", null);
if (cursor != null)
{
cursor.moveToFirst();
nextID = cursor.getInt(0) + 1;
}
}
catch (SQLiteException ex)
{
Log.d("GetNextID", ex.toString());
nextID = -1;
}
finally
{
if (myDB.isOpen())
{
myDB.close();
}
if (!cursor.isClosed())
{
cursor.close();
}
}
return nextID;
}
I don't understand the content values have been skipped and it goes straight into the finally.
Perhaps some exception other than SQLException and SQLiteException have been thrown? If you put catch(Exception x) {...} you will probably see.
First try moving the line.
myDb = context.openOrCreateDatabase("PasswordManager", Context.MODE_PRIVATE, null);
below the line
int rowId = common.getNextID("password");
in your method. Or even better would be to add myDb as a parameter into your getNextID function so you are using the same DB reference and then don't close the DB in that function.
Add in the catch(Exception x) to your exceptions.
And then finally put a breakpoint inside your getNextID method and find out exactly which line it is breaking on.
Cheers

Handling Invalid SQLite Queries in Android

I have a simple code that manages to successfully query an SQLite Database and convert that result from cursor to string in order to display it on screen.
My problem now would be invalid queries that make the App Crash. Would there be a way to successfully handle invalid queries? Preferably something that would keep my app from crashing and would just redirect the user to the home page and display a toast of warning.
So far my method for searching looks like this:
public String search(DataBaseHelper myDB){
SQLiteDatabase db = myDB.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT BuildingColor, Room FROM LSBuildingsDB WHERE _id =" + newString, null);
cursor.moveToFirst();
String data = cursor.getString(cursor.getColumnIndexOrThrow("BuildingColor")) + " " +
cursor.getString(cursor.getColumnIndex("Room"));
//Toast msg = Toast.makeText(getBaseContext(),data, Toast.LENGTH_SHORT);
//msg.show();
cursor.close();
return data;
}
Cursor cursor = NULL ;
try
{
cursor = db.rawQuery("SELECT BuildingColor, Room FROM LSBuildingsDB WHERE _id =" + newString, null);
if(cursor != NULL)
{
try {
if (cursor.moveToNext()) {
String data = cursor.getString(cursor.getColumnIndexOrThrow("BuildingColor")) +
" " + cursor.getString(cursor.getColumnIndex("Room"));
} else {
// Query result was empty, deal with it here.
}
} finally {
// Cursors should be closed
cursor.close();
}
}
}
catch (SQLiteException e) // (Exception e) catch-all:s are bad mmkay.
{
//print exception
}
Cursor cursor = null;
String data = "";
try
{
cursor = db.rawQuery("SELECT BuildingColor, Room FROM LSBuildingsDB WHERE _id =" + newString, null);
}catch (Exception e) {
// TODO: handle exception
}

Categories

Resources