I have packaged a database with my application, and I can see in my File Explorer that the databases folder along with the workoutsDatabase.sqlite file is being created. When I look at the contents of the database, though, the only table in there is the android_metadata table. I have been searching for hours and have seen many people with similar problems, however, I cannot seem to figure out the correct solution.
Can anyone spot why the tables dont seem to copy over? I have validated the workoutsDatabase.sqlite in my assets folder DOES contain the table "workout" and it does have data in it.
WorkoutsDatabaseHelper
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class WorkoutsDatabaseHelper extends SQLiteOpenHelper {
private String DATABASE_PATH = "/data/data/com.rcd.myworkouts/databases/";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "workoutsDatabase.sqlite";
private static final String TABLE_WORKOUTS = "workouts";
private static final String KEY_ID = "_id";
private static final String KEY_WORKOUT_NAME = "workout_name";
private static final String KEY_LAST_NAME = "last_name";
private static final String KEY_FIRST_NAME = "first_name";
private static final String KEY_MIDDLE_NAME = "middle_name";
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_DATE_ADDED = "date_added";
private static final String KEY_WORKOUT = "workout";
private static final String KEY_MEASUREMENT = "measurement";
private static final String KEY_PHOTO = "photo";
private SQLiteDatabase myDatabase;
private final Context myContext;
public WorkoutsDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
}
// Creates a empty database on the system and rewrites it with your own database.
public void createDatabase() throws IOException {
boolean dbExist = checkDatabase();
SQLiteDatabase db_Read = null;
if(dbExist) {
// Do nothing - database already exist
} else {
//By calling this method an empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
db_Read = getReadableDatabase();
db_Read.close();
try {
copyDatabase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
//Check if the database already exist to avoid re-copying the file each time you open the application.
//#return true if it exists, false if it doesn't
private boolean checkDatabase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DATABASE_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch(SQLiteException e) {
// Database doesn't exist yet
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDatabase() throws IOException {
getWritableDatabase();
Log.d("Database", "New database is being copied to device!");
try
{
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
// transfer bytes from the inputfile to the
// Path to the just created empty db
String outFileName = DATABASE_PATH + DATABASE_NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// Transfer bytes form the inputfile to the output file
byte[] buffer = new byte[1024];
int length;
while((length = myInput.read(buffer)) > 0)
{
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
Log.i("Database", "New database has been copied to device!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
protected Boolean openDatabase() {
if(checkDatabase())
{
// Open the database
String myPath = DATABASE_PATH + DATABASE_NAME;
try
{
Log.i("Database", "Trying to Open Database!");
if(myDatabase != null)
{
if(!myDatabase.isOpen())
{
Log.i("Database", "Database is closed now opening it!");
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
else
{
Log.i("Database", "Database is already Open!");
}
Log.i("Database", "Database is Opened successfully in OPEN_READWRITE Mode !");
return true;
}
else
{
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
Log.i("Database", "Database is Opened successfully in OPEN_READWRITE Mode !");
return true;
}
}
catch(Exception e)
{
Log.e("Database", "Some error occured while opening Database Error:" + e.getMessage());
myDatabase = null;
return false;
}
}
else
try {
copyDatabase();
Log.d("WorkoutsDatabaseHelper.java", "Copy Database..");
} catch (IOException e) {
throw new Error("Error copying database");
}
return false;
}
#Override
public synchronized void close() {
if(myDatabase != null)
myDatabase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Related
I'm working with a prepopulated database. Using SQLite Manager in Mozilla, right now I have a dummy database and just wanted to test out the onUpgrade method, so I altered a string in one of the columns, exported it as a new database and as you'll see in my code, tried to open the newly updated version. Also important note, I'm updating the version number by one manually in the code
private static final int DB_VERSION = 3;
and in the onUpgrade
if (newVersion == 3) {
Log.e("WORKED!!", "onUpgrade executed");
so next time I would update these two numbers to 4. Not sure if I'm doing this right or what's wrong but I'm getting the log message, just not seeing the data updated in the app.
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class DataBaseHelper extends SQLiteOpenHelper {
private static String DB_PATH;
private static final String DB_NAME = "DummyTestOne.sqlite";
private static final int DB_VERSION = 3;
private static final String DB_NAME2 = "DummyTestFive.sqlite";
private SQLiteDatabase mDataBase;
private final Context mContext;
public static final String DBTABLENAME = "questiontable";
public static final String DBATABLENAME = "answertable";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "question";
public static final String COLUMN_CATEGORY = "category";
public static final String COLUMN_FID = "fid";
public static final String COLUMN_ANSWER = "answer";
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.mContext = context;
DB_PATH = context.getDatabasePath(DB_NAME).getPath();
}
public void createDataBase() {
boolean dbExist = checkDataBase();
if (dbExist) {
} else {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
Log.e(this.getClass().toString(), "Error while checking db");
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException {
InputStream externalDbStream = mContext.getAssets().open(DB_NAME);
OutputStream localDbStream = new FileOutputStream(DB_PATH);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
localDbStream.write(buffer, 0, bytesRead);
}
localDbStream.flush();
localDbStream.close();
externalDbStream.close();
}
public void openDataBase() throws SQLException {
mDataBase = this.getWritableDatabase();
}
#Override
public synchronized void close() {
if (mDataBase != null) {
mDataBase.close();
}
super.close();
}
public Cursor getCursorForAllQs() {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DBTABLENAME);
String[] asColumnsToReturn = new String[]{COLUMN_ID, COLUMN_NAME, COLUMN_CATEGORY, COLUMN_FID};
Cursor mCursor = queryBuilder.query(mDataBase, asColumnsToReturn, null,
null, null, null, "_id");
return mCursor;
}
public List<String> getAnswersForQ(int questionFid) {
List<String> answers = new ArrayList<>();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DBATABLENAME);
String[] tableColumns = new String[]{DataBaseHelper.COLUMN_ANSWER};
String where = "fid = ?";
String[] selectionArgs = new String[]{String.valueOf(questionFid)};
String orderBy = DataBaseHelper.COLUMN_ID;
Cursor c = queryBuilder.query(mDataBase, tableColumns, where, selectionArgs, null, null, orderBy);
if (c.moveToFirst()) {
do {
try{
answers.add(c.getString(c.getColumnIndex(DataBaseHelper.COLUMN_ANSWER)));
} catch (Exception e) {
Log.e("FAILED", c.getString((c.getColumnIndex(DataBaseHelper.COLUMN_ANSWER))));
}
} while (c.moveToNext());
}
Log.d("getAnswersForQ", answers.toString());
return answers;
}
public String getName(Cursor c) {
return (c.getString(1));
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion == 3) {
Log.e("WORKED!!", "onUpgrade executed");
}
if (newVersion > oldVersion) {
InputStream inputStream = null;
OutputStream outputStream = null;
String dbFilePath = DB_PATH + DB_NAME;
try {
inputStream = mContext.getAssets().open(DB_NAME2);
outputStream = new FileOutputStream(dbFilePath);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException e) {
throw new Error("Problem copying database from resource file.");
}
}
}
}
Upgrading a database means changing it in place while keeping the old data intact as much as possible.
So if you want to add or rename a column, you have to execute the proper SQL command to do this in the onUpgrade callback.
(Note: SQLiteAssetHelper makes using a prepopulated database easier, and you should use it, but upgrading still needs a separate SQL script.)
If you do not care about the contents of the old database, then you should not upgrade it. Just give your new database version a new file name, so that it is simply copied over, and delete the old file.
I am trying to create a new version of database in my android app. But although I change the version of database from previous version (2) to a new version (3) it doesn't invoke onUpgrade() and onCreate() . It just invoke three times the constructor. I do not understand why constructor invoked three times and also why onUpgrade() and onCreate() did not invoke?
I also tried with new database version code but result is same.
Here is my code.
public class DatabaseHelper extends SQLiteOpenHelper {
private static String PACKAGE_NAME;
private static String DB_PATH;
private static String DB_NAME = "mydata.db";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 3);
this.myContext = context;
Log.e("UPDATED3", "CONSTRUCTOR");
PACKAGE_NAME = myContext.getPackageName();
DB_PATH = "/data/data/" + PACKAGE_NAME + "/databases/";
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
// do nothing - database already exist
} else {
// By calling this method and empty database will be created into
// the default system path
// of your application so we are gonna be able to overwrite that
// database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException {
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
// Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
}
#Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.e("UPDATED3", "ONCREATE");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e("UPDATED3", "UPDATED THE DATABASE");
}
}
I use my database this(showing below) way in any activity.
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext());
try {
databaseHelper.createDataBase();
databaseHelper.openDataBase();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Error: " + e.getMessage(),
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
This is my DataBaseHelper.java
package com.example.abc2;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.example.abc2/databases/";
private static String DB_NAME = "DB_BusData";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* #param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exist
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
}
MainActivity.java
public void DatabaseConn(){
DataBaseHelper myDbHelper = new DataBaseHelper(this.getApplicationContext());
myDbHelper = new DataBaseHelper(this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
SQLiteDatabase db = myDbHelper.getReadableDatabase();
//SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.example.abc2/databases/DB_BusData", null, 0);
Cursor c = db.rawQuery("SELECT * FROM Tbl_Driver", null);
if(c.moveToFirst()) {
String username = c.getString(c.getColumnIndex("Driver_Code")).trim();
String password = c.getString(c.getColumnIndex("Driver_Name")).trim();
Log.d(null, username);
}
db.close();
}
Any Idea to make my myDbHelper as global variable, otherwise every function i want to call the database i need to declare it, it is inconvenience.
Just add this
DataBaseHelper myDbHelper = new DataBaseHelper(this.getApplicationContext());
Over onCreate in your MainActivity, and remove it from public void DatabaseConn(){.
Create a Singleton Database class:
public class Database extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "yourDatabaseName";
//Declare a String for each Table name
public static final String TABLE_NAME1 = "tableName1";
public static final String TABLE_NAME2 = "tableName2";
//Declare a SQL string for create each table
private static final String CREATE_TABLE1 =
"CREATE TABLE if not exists " + TABLE_NAME1 ..............";
private static final String CREATE_TABLE2 =
"CREATE TABLE if not exists " + TABLE_NAME2 .................";
private static Database Singleton = null;
private Context context;
private static SQLiteDatabase Db;
private Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
public static synchronized Database getInstance(Context c){
if(Singleton == null) {
Singleton = new Database(c.getApplicationContext());
Db = Singleton.getWritableDatabase();
}
return Singleton;
}
public SQLiteDatabase getDatabase() {
return Db;
}
public synchronized void close() {
if (Singleton != null && Db.isOpen()) Db.close();
}
#Override
protected void finalize() throws Throwable {
try{
close();
}
finally{
super.finalize();
}
#Override
public void onCreate(SQLiteDatabase db) {
//Create Tables
db.execSQL(CREATE_TABLE1);
db.execSQL(CREATE_TABLE2);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
When you need a database object:
SQLiteDatabase Db = Database.getInstance(context).getDatabase();
I have 100 images in my Assets folder. I would like to set an image to the imageview, and below four buttons with 4 possible answers to connect with the image (one correct, of course). What I was thinking, I have a similar quiz game already done, I'm using SQLite database for question and answers. So, is there a way I could use sqlite database for this, but only where my question is in database I would place some term or an integer, for example 1 for image_1.png, 2 for image_2.png and so on.
Or another scenario is to prepopulate database with images, but I don't know if that's even possible or how to do it.
Is there a way to rewrite my db helper to use it with this? Here's my db helper and testAdapter:
public class DataBaseHelper extends SQLiteOpenHelper
{
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
//destination path (location) of our database on device
private static String DB_PATH = "/data/data/rs.androidaplikacijekvizopstekulture/databases/";
private static String DB_NAME ="pitanja.sqlite";// Database name
private static SQLiteDatabase mDataBase;
private final Context mContext;
private static final String KEY_ID = "_ID";
private static final String TABLE_NAME = "tblPitanja";
public DataBaseHelper(Context mojContext)
{
super(mojContext, DB_NAME, null, 1);// 1? its Database Version
DB_PATH = mojContext.getApplicationInfo().dataDir + "/databases/";
this.mContext = mojContext;
}
public void createDataBase() throws IOException
{
//If database not exists copy it from the assets
this.getReadableDatabase();
this.close();
try
{
//Copy the database from assests
copyDataBase();
Log.e(TAG, "createDatabase database created");
}
catch (IOException mIOException)
{
throw new Error("ErrorCopyingDataBase");
}
}
/*Check that the database exists here: /data/data/your package/databases/Da Name
private boolean checkDataBase()
{
File dbFile = new File(DB_PATH + DB_NAME);
//Log.v("dbFile", dbFile + " "+ dbFile.exists());
return dbFile.exists();
}
*/
//Copy the database from assets
private void copyDataBase() throws IOException
{
InputStream mInput = mContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream mOutput = new FileOutputStream(outFileName);
byte[] mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer))>0)
{
mOutput.write(mBuffer, 0, mLength);
}
mOutput.flush();
mOutput.close();
mInput.close();
}
//Open the database, so we can query it
public boolean openDataBase() throws SQLException
{
String mPath = DB_PATH + DB_NAME;
//Log.v("mPath", mPath);
mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY);
//mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDataBase != null;
}
#Override
public void close()
{
if(mDataBase != null)
mDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase arg0) {
}
#Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
Log.w("DataBaseHelper", "Upgrading database!!!!!");
onCreate(arg0);
}
}
And here's testAdaper:
public class TestAdapter
{
protected static final String TAG = "DataAdapter";
private final Context mContext;
private SQLiteDatabase mDb;
private DataBaseHelper mDbHelper;
public TestAdapter(Context context)
{
this.mContext = context;
mDbHelper = new DataBaseHelper(mContext);
}
public TestAdapter createDatabase() throws SQLException
{
try
{
mDbHelper.createDataBase();
}
catch (IOException mIOException)
{
Log.e(TAG, mIOException.toString() + " UnableToCreateDatabase");
throw new Error("UnableToCreateDatabase");
}
return this;
}
public TestAdapter open() throws SQLException
{
try
{
mDbHelper.openDataBase();
mDbHelper.close();
mDb = mDbHelper.getReadableDatabase();
}
catch (SQLException mSQLException)
{
Log.e(TAG, "open >>"+ mSQLException.toString());
throw mSQLException;
}
return this;
}
public void close()
{
mDbHelper.close();
}
public Cursor getTestData(String whereClause)
{;
try
{
String sql ="SELECT * FROM tblPitanja WHERE 1 = 1 " + whereClause + " ORDER BY RANDOM() LIMIT 1";
Cursor mCur = mDb.rawQuery(sql, null);
if (mCur!=null)
{
mCur.moveToNext();
}
return mCur;
}
catch (SQLException mSQLException)
{
Log.e(TAG, "getTestData >>"+ mSQLException.toString());
throw mSQLException;
}
}
}
You can save the images in sqlite by using blob datatype. Use SQLite manager (firefox plugin) to pre-populate your database on a computer. Then you just need the db file in assets folder, and not those 100 images!
Check this:
how to store Image as blob in Sqlite & how to retrieve it?
Another way (faster) is to store images in an external folder and then enter its URL in the database.
Since you have images in assets already I would suggest you to save only the names of the associated image in the sqlite. I prefer always to avoid saving blob in sqlite. You can always get the correct name and load it into the imageview directly from the database.
EDIT :
your code can be as simple as this.
Cursor getname = db.rawQuery("Select * from table_name where QuestionID = ...");
if(getname.movetofirst())
{
String drawablename = getname.getString(getname.getColumnIndex("PicName"));
ImageView iw= (ImageView)findViewById(R.id.imageView1);
int resID = getResources().getIdentifier(drawableName, "drawable", getPackageName());
iw.setImageResource(resID);
}
I have a big problem in my android application. I'm develop for the first time an android application with a sqlite database but i have problems that i cant solve.
I have my sqlite database on assets folder of eclipse project with name saldb.sqlite
I have the following class to manage Database with Singletone pattern:
package sal.app.logic;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseManager extends SQLiteOpenHelper{
private static DataBaseManager dbManagerInstance = null;
private Context salContext;
private SQLiteDatabase salDatabase;
private static String DB_PATH = "/data/data/sal.app/databases/";
private static String DB_NAME = "saldb.sqlite";
private DataBaseManager(Context c)
{
super(c, DB_NAME, null, 1);
//this.salContext = c;
}
public static DataBaseManager getSalDatabase(Context c)
{
if (dbManagerInstance == null)
{
dbManagerInstance = new DataBaseManager(c);
}
return dbManagerInstance;
}
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exist
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase()
{
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = salContext.getAssets().open(DB_NAME);
// Path to the just created empty db
//String outFileName = DB_PATH + DB_NAME;
String outFileName = "/data/data/sal.app/databases/saldb.sqlite";
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
salDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
#Override
public synchronized void close() {
if(salDatabase != null)
salDatabase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
//db.execSQL("Insert Into Question(_id,level,text,idTopic) Values (1,1,'asa',0)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
public Question getOneQuestion()
{
//list of Versioni, search result with query text
Question quest = new Question();
try
{
//open database to query
openDataBase();
//salDatabase.execSQL("Insert Into Question(_id,level,text,idTopic) Values (1,1,'asa',0)");
//Cursor cursor = salDatabase.rawQuery("SELECT text, idTopic, level from Question WHERE level=2", null);
Cursor cursor = salDatabase.rawQuery("SELECT * from Question", null);
/*Cursor cursor = salDatabase.query("Question",
new String[] { "text","idTopic","level"},
"level=2",
null ,
null,
null,
"RANDOM() LIMIT 1");*/
//Cursor c = db.rawQuery(select, null); */
//mapped all rows to data object
if (cursor.moveToFirst())
{
System.out.println(cursor.getString(2));
do
{
Cursor cursor2 = salDatabase.rawQuery("SELECT * from Topic WHERE _id=0", null);
cursor2.moveToFirst();
Topic t = new Topic(cursor2.getString(1));
quest = new Question(cursor.getString(2),t,(int)cursor.getShort(1));
break;
} while (cursor.moveToNext());
}
//close cursor
cursor.close();
}
catch(Exception ex)
{
System.out.println("DatabaseHelper.search()- : ex " + ex.getClass() +", "+ ex.getMessage());
}
//
return quest;
}
/*public ArrayList<Answer> getAnswersOfQuestion(Questin q)
{
}*/
}
But in first time that i run my application i have de following erros:
05-29 23:55:45.684: D/ddm-heap(221): Got feature list request
05-29 23:55:46.295: D/dalvikvm(221): GC freed 519 objects / 45792 bytes in 109ms
05-29 23:55:46.544: E/Database(221): sqlite3_open_v2("/data/data/sal.app/databases/saldb.sqlite", &handle, 1, NULL) failed
05-29 23:55:46.594: D/AndroidRuntime(221): Shutting down VM
05-29 23:55:46.604: W/dalvikvm(221): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
05-29 23:55:46.604: E/AndroidRuntime(221): Uncaught handler: thread main exiting due to uncaught exception
in my main Activity im doing this:
public class SALActivity extends Activity {
Button back;
Button choiceA;
static int choice = 0;
DataBaseManager db;
//Button choiceB;
//Button choiceC;
//Button choiceD;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.gamemenu);
//db= new DataBaseManager(this);
db=DataBaseManager.getSalDatabase(this);
try {
db.createDataBase();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//db=DataBaseManager.getSalDatabase(this);
Question q = db.getOneQuestion();
//back = (Button) findViewById(R.id.gaveup_button);
choiceA = (Button) findViewById(R.id.choice_a_button);
choiceA.setTextColor(0xffffffff);
//choiceA.setText("A: Académica");
choiceA.setText(q.getQuestionText());
choiceA.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
//choiceA.setText(10);
//choiceB = (Button) findViewById(R.id.choice_b_button);
//choiceC = (Button) findViewById(R.id.choice_c_button);
//choiceD = (Button) findViewById(R.id.choice_d_button);
//Intent v = new Intent(this, SALActivity.class);
//this.startActivity(v);
}
}
In the second time that i run app, error dont occur, database are in the correct path but only have the table android_metadata
I also could say that if i put the correct dataBase on /data/data/sal.app/databases/ the entire program just works...
The error is in the copyDatabase.
This is my working code to copy database.
private static String DB_PATH = "/data/data/com.demo.databaseDemo/databases/";
private static String DB_NAME = "myDatabase.db";
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = _myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}//end of copyDataBase() method
You need to create the folder for you database and copy into the folder the first time your app runs. Here is what I do:
// Check to see if database exists, otherwise copy from assets
boolean dbExist = db.databaseExist();
if (!dbExist) {
try {
// See if there is a data directory, otherwise create it
String destPath = "/data/data/" + getActivity().getPackageName() +
"/databases/";
File f = new File(destPath);
if (!f.exists()) {
f.mkdirs();
f.createNewFile();
// Copy from assets to data directory
CopyDB(getActivity().getBaseContext().getAssets().open("myData.sqlite"),
new FileOutputStream(destPath + "/myData.sqlite"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}