the table ( i.e. vaccines) structure is :
id- auto increment primary key
dose1_date - string
dose2_date - string
The DatabaseAccessor class is as follows. The initDB() and setVaccineDates methods are called from another activity. But the database is not updated. The logged message is found in the logcat however. The DatabaseHelper class is not shown here.
public class DatabaseAccessor {
public static DataBaseHelper myDbHelper = null;
public static SQLiteDatabase rdb = null;
public static SQLiteDatabase wdb = null;
public static synchronized final void initDB(Context context) throws Exception {
if (myDbHelper == null) {
myDbHelper = new DataBaseHelper(context);
myDbHelper.openDataBase();
rdb = myDbHelper.getReadableDatabase();
wdb = myDbHelper.getWritableDatabase();
}
}
public static void setVaccineDates(String birthDate) throws SQLException{
try {
String[] selections = null;
String qry = null;
qry = "select * from vaccines order by id";
Cursor cursor = wdb.rawQuery(qry, selections);
Log.d("update qry===== ", qry);
while (cursor.moveToNext()) {
int rowID = Integer.parseInt(cursor.getString(0));
ContentValues values = new ContentValues();
values.put("dose1_date","66666");
values.put("dose2_date","7777");
wdb.update("vaccines", values, "id=?", new String[] {String.valueOf(rowID)});
//wdb.close();
}
cursor.close();
} catch (Exception e) {
e.printStackTrace();
}
}// end of method setVaccineDates
}
What to do ?
Edit : If I uncomment the wdb.close() line , I see in logcat
'06-09 04:21:05.387: W/System.err(4144): java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.cloudsoft.vaccine/databases/vaccines2.db
'
As a newbie in android it was just a mistake out of ignorance that this situation took place: after update operation I tried to find the changes in the database file (i.e. file with .db extension sitting inside assets folder in Eclipse) through sqlite browser . But what actually happens is the app running in the device (real one or emulator) has its own database which is created from the .db extension file inside assets folder and consequent database operations only affect the app's own database leaving no touch on the database inside the mentioned folder in Eclipse. And there is the way to watch the app's very own database in the running device in Eclipse's 'File Explorer' (in DDMS mode) with the help of Questoid SQlite Manager
Related
This question already has answers here:
When does SQLiteOpenHelper onCreate() / onUpgrade() run?
(15 answers)
Closed 4 years ago.
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
Here is my code for sqlite in android studio
public class Database extends SQLiteAssetHelper{
private static final String DB_NAME="Jerson.db";
private static final int DB_VER=1;
public Database(Context context)
{
super(context, DB_NAME,null,DB_VER);
}
public List<Orders> getCarts()
{
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String[] sqlSelect={"MenuId","Name","Quantity","Price"};
String sqlTable="OrderDetails";
qb.setTables(sqlTable);
Cursor c = qb.query(db,sqlSelect,null,null,null,null,null);
final List<Orders> result = new ArrayList<>();
if (c.moveToFirst())
{
do {
result.add(new Orders(c.getString(c.getColumnIndex("MenuId")),
c.getString(c.getColumnIndex("Name")),
c.getString(c.getColumnIndex("Quantity")),
c.getInt(c.getColumnIndex("Price"))
));
}while (c.moveToNext());
}
return result;
}
public void addToCart(Order order)
{
SQLiteDatabase db = getReadableDatabase();
String query = String.format("INSERT INTO OrderDetails(MenuId,Name,Quantity,Price)VALUES('%s','%s','%s','%s');",
order.getMenuId(),
order.getName(),
order.getQuantity(),
order.getPrice());
db.execSQL(query);
}
public void cleanCart()
{
SQLiteDatabase db = getReadableDatabase();
String query = String.format("DELETE FROM OrderDetails");
db.execSQL(query);
}
}
I am sure I have a table in sqlite I dont know why its returning me no such table
here is a snippet of code on where I use the database
btnCart.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
new Database(getBaseContext()).addToCart(new Order(
foodId,
currentFood.getName(),
numberButton.getNumber(),
currentFood.getPrice()
));
Toast.makeText(FoodDetail.this, "Added To Cart", Toast.LENGTH_SHORT).show();
}
});
The most common cause for table not found is that it hasn't been created when the database is created. This may be due to an SQL error in the tale create statement or issues encountered when copying a packaged database from the assets folder.
The latter can be a badly written copy process, hence why SQLiteAssetHelper is frequently recommended as it's tried and tested. However, even with SQliteAssetHelper a bad file can result in such an error, such a database saved before the table is created as some SQLite Tools can allow.
When using SQLiteAssethelper, as per this question. The fix should be to :-
Delete the App's Data or Uninstall the App (both will delete the existing database allow it be copied (SQLiteAssethelper checks to see if the Database exists, if so then it doesn't attempt to copy the asset)).
Check that Database is sound using an SQlite tool and save it.
Copy the saved file (best done outside of Android Studio) to the App's assets/database folder (creating the assets folder and databases folder if need be).
Rerun the App.
I am working on pre-installed database and using SqliteAssetHelper library for that.
This is my db code
public class DBController extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "user.db";
private static final int DATABASE_VERSION = 1;
private final String TABLE_NAME = "User";
public DBController(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public ArrayList<UserData> getAllUserData() {
ArrayList<UserData> data_list = new ArrayList<>();
try {
// open database to query
SQLiteDatabase mySqliteDb = getWritableDatabase();
} catch (Exception e) {
Log.e("exception", "" + e);
}
close();
return data_list;
}
}
Error: Missing databases/user.db file (or .zip, .gz archive) in assets, or target folder not writable
and when I change my code to SQLiteDatabase mySqliteDb = getReadableDatabase(); I am getting android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database error.
I search for the problem and mostly everyon saying check your db present inside databases folder or not.
I tried using zip also still no luck. I guess I am missing something.
Your assets/ directory belongs inside main/, not inside app/.
I've used the GUI to create a DB which has 1650 records in it.
I'm trying to query this DB but it's always returning nothing. I've tried writing a simple getrowcount() method to see if I'm getting anything at all, but it always returns zero. I must be missing something obvious here, if someone can help point out what's going on.
In my main app.java:
db = new DbHandler(this);
String sIcao1 = "ROW COUNT = " + String.valueOf(db.getRowCount());
In my dbhandler.java:
package com.jammo.mywidget4;
<snip - standard includes>
public class DbHandler extends SQLiteOpenHelper {
private static SQLiteDatabase db;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "airports";
private static final String TABLE_AIRPORTS = "airports";
public DbHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
db = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
db = this.getWritableDatabase();
}
int getRowCount() {
int nCount = -1;
//SQLiteDatabase db = this.getReadableDatabase();
Cursor cur = db.rawQuery("SELECT * FROM airports", null);
nCount = cur.getCount();
if (cur != null) {
//cur.moveToFirst();
//nCount = cur.getInt(0);
//if (cur.getInt (0) == 0) {
//}
}
return nCount;
}
}
In the GUI (SQLite DB Browser) I'm doing a simple
select * from airports
... and I'm getting back the full number of rows. When I debug the Java, cursor returns nothing.
Also, the DB created by the GUI is located in myapp/assets/airports.db.
Any ideas?
I think you need to include the .db in the DATABASE_NAME.
Try changing this:
private static final String DATABASE_NAME = "airports";
to this:
private static final String DATABASE_NAME = "airports.db";
Edit:
Actually I think even with this change it is not going to work for you. SQLiteOpenHelper is expecting your db file to be inside of /data/data/your.package/databases/ So I think you'll need to copy it from assets to there if you want it to work with an unmodified SQLiteOpenHelper.
See here to learn how to copy it over: Android: Accessing assets folder sqlite database file with .sqlite extension
I have my code below. It correctly reads my sqlite database file(that i have already created using the SQLite Database Browser) in my assets folder - moves it to the /data/data/packagename/databases/ path on my device then i am able to use a query and cursor to get my information and it works great. Code here:
public class DatabaseHelper extends SQLiteOpenHelper {
private Context myDbContext;
private static String dbName = "restaurant.db";
private static String outfilePath = "/data/data/dev.mypackage.com/databases/";
private static String path = outfilePath + dbName;
private static SQLiteDatabase db;
public DatabaseHelper(Context context){
super(context, dbName, null, 2);
this.myDbContext = context;
db = openDb();
String s = "select * from menu";
Cursor c = db.rawQuery(s, null);
Log.e("DB Constructor Row count", String.valueOf(c.getCount()).toString());
while(c.moveToNext()){
Log.e("DB Constructor", c.getString(c.getColumnIndex("category")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("menuItem_id")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("title")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("desc")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("price")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("icon")));
}
c.deactivate();
c.close();
}
private void copyDataBase(File dbFile) throws IOException {
try{
InputStream dbStream = myDbContext.getAssets().open(dbName);
OutputStream newDbFile = new FileOutputStream(outfilePath + dbName);
byte[] buffer = new byte[1024];
int length;
while((length = dbStream.read(buffer)) > 0){
newDbFile.write(buffer);
}
newDbFile.flush();
newDbFile.close();
dbStream.close();
}
catch(IOException e){
throw new IOException("trying to copy the database - ERROR: " + e.getMessage());
}
}
private SQLiteDatabase openDb() throws SQLiteException{
File dbFile = myDbContext.getDatabasePath(dbName);
if(!dbFile.exists()){
Log.e("openDb", "file does not exist");
try {
copyDataBase(dbFile);
} catch (IOException e) {
throw new RuntimeException("Error creating source database", e);
}
}
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
}
public void loadRestaurantInfo(){
}
#Override
public void onCreate(SQLiteDatabase db){
// TODO Auto-generated method stub
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
Now i had to go back and add a row of information to one of the tables(in the database in the assets folder), using the SQLite Brower, - but that is not being reflected in my cursor output - I understand why this is happening - because if(!dbFile.exists()) fails so there is no copying to be done. So my question is - is what code do i need to add to make this work? I never created the tables with code so i dont see how useful the onUpgrade method is going to be for me.
You have three options:
Use onUpgrade() (preferred)
Delete the existing database and copy the new one (not a good idea)
Copy the data in the existing database, delete the existing database, copy the new database, insert data from old database into new database (too much work when the new database schema can be upgraded in onUpgrade).
So, to answer your question, you upgrade your database in onUpgrade() without having to recreate any tables.
On the other hand, if you just added a new row to a particular table, the database schema has not changed and you can just insert the new row at runtime... of course, not knowing what your application's purpose is this may not be a good idea as you can easily lose track of changes to your "static" database.
The "right" way to do things is quite different from how you've set out. Rather than go there, I'll assume you want to keep your current method of creating your database and I'll offer a suggestion to work with it. Add a table to your database which has a single row of meta data, which will include the database version (as well as anything else you like). If the database file already exists, open it and check the version. If the version is old, close it and replace it.
I am trying to figure out what order I need to do everything to have my program flow well and not crash. I want the player of my game to have a team of three people each as their own class with stats such as attack, health, etc.
When the game is first installed and run, I want to have a sqlite db made and filled with the 3 starter characters.
When they start it any other time, I want to have the three stored characters in the DB to be assigned to 3 local character objects.
I have a SQLite Adapter class handling the Db but I'm not sure how to order everything so that I check first to see if there is a Db in the programs Db path and open it if there is. Otherwise just create a new one and populate it with the initial characters.
I currently have:
DbAdapter = new PlayerDbAdapter(this);
DbAdapter.open();
DbAdapter.setInitialPlayers(); // inserts my initial player object info into the Db
which calls
public PlayerDbAdapter open() throws SQLException {
dbHelper = new SummonSQLiteHelper(context);
String s = DbPath + DB_NAME;
database = SQLiteDatabase.openOrCreateDatabase(s, null);
return this;
}
And now I'm a little lost as to what I need to make sure that I don't overwrite any saved info in the Db with the initial values everytime I start the program. Any suggestions?
Try like this
public PlayerDbAdapter open() throws SQLException {
dbHelper = new SummonSQLiteHelper(context);
String s = DbPath + DB_NAME;
bool b=checkDataBase(s);
if(b==false)
{
database = SQLiteDatabase.openOrCreateDatabase(s, null);
setInitialPlayers(); <---- set initial values here
}
else
{
database = SQLiteDatabase.openOrCreateDatabase(s, null);
}
return this;
}
private boolean checkDataBase(String str) {
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(str, null,
SQLiteDatabase.OPEN_READONLY);
checkDB.close();
} catch (SQLiteException e) {
// database doesn't exist yet.
}
return checkDB != null ? true : false;
}