You can see my database helper class below. I use prepopulated sqlite database imported in assets folder. Whenever I add a table to my existing database, I get no such table error if my app is already installed on my phone. I guess my onUpgrade() method is now so good. It works, don't get me wrong, when I change some data to existing tables, I increase db version and it gets updated. But if I add a table I get error.
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.androidaplikacije.themostcompleteiqtest/databases/";
private static String DB_NAME ="pitanja.sqlite";// Database name
private static SQLiteDatabase mDataBase;
private final Context mContext;
private static final int DATABASE_VERSION = 3;
public DataBaseHelper(Context mojContext)
{
super(mojContext, DB_NAME, null, 3);// 1 it's 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 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
*/
public 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;
}
/*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) {
try {
// delete existing?
// Copy the db from assests
copyDataBase();
Log.e(TAG, "database updated");
} catch (IOException mIOException) {
Log.e(TAG, mIOException.toString());
try {
throw mIOException;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
There's 2 ways to do onUpgrade, depending on your app.
1)Drop all your old tables, then run onCreate. THis basically wipes out all your old data and starts over. Its a good technique if you can regenerate the old data somehow, or just don't care about it.
2)Carefully maintain a diff of your schema between each released version, and write SQL statements to make the proper changes between them- add new tables, alter existing tables to add/remove columns, etc. This is time consuming and fragile, so use this only if you need to keep data between those versions.
Related
My app is a quiz that has 33 stages and 25 categories, quiz data are in a LOCAL sqlite database that has three tables (Stages + Categories + Questions), users scores are saved to the Stage/Category tables in the database upon successful completion of each level.
I need from time to time to revise the data OR add new stages, categories and questions; I do so in the sqlite database itself, then I copy the database and paste it the Asset folder thus replacing old one, and the incitement version number.
These changes appear to new users after first installation BUT DO NOT appear to existing users after update.
I would like to reflect all changes and STILL PRESERVE user data (scores) that are already stored in the database.
I have tried the following:
1- copyDataBase onUpgrade - RESULT: changes and not reflected and user data is preserved.
2- Create a new_sqlite_database, copyDataBase onUpgrade using the new_sqlite_database - RESULT: changes are reflected, app crashes onclicklistner of a stage only once and works thereafter, user data is not preserved.
3- Alter Table with temp names, Drop old tables, create new tables with same old names, copyDataBase, update new tables records using temp tables - RESULT: Blank screens.
QuizDbHelper
class QuizDbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "qa_sqlite.db";
private static String DATABASE_LOCATION = "/data/data/packagename/databases/";
private static final int DATABSE_VERSION = 12;
private final Context mContext;
private SQLiteDatabase mDatabase;
private final Handler handler = new Handler();
public QuizDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABSE_VERSION);
if (android.os.Build.VERSION.SDK_INT >= 17)
DATABASE_LOCATION = context.getApplicationInfo().dataDir + "/databases/";
else
DATABASE_LOCATION = "/data/data/" + context.getPackageName() + "/databases/";
this.mContext = context;
copyDataBase();
this.getReadableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
copyDataBase();
Log.w("POSITIVE ... ","onCreate Called - Database Copied");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
copyDataBase();
Log.w("POSITIVE ... ", "onUpgrade Called - Database Copied");
}
}
private boolean checkDataBase() {
File dbFile = new File(DATABASE_LOCATION + DATABASE_NAME);
return dbFile.exists();
}
private void copyDataBase() {
if (!checkDataBase()) {
this.getReadableDatabase();
this.close();
try {
copyDBFile();
} catch (IOException mIOException) {
throw new Error("ُCopy Database Failed");
}
}
}
private void copyDBFile() throws IOException {
InputStream mInput = mContext.getAssets().open(DATABASE_NAME);
OutputStream mOutput = new FileOutputStream(DATABASE_LOCATION + DATABASE_NAME);
byte[] mBuffer = new byte[1024];
int mLength;
while ((mLength = mInput.read(mBuffer)) > 0)
mOutput.write(mBuffer, 0, mLength);
mOutput.flush();
mOutput.close();
mInput.close();
}
private void openDatabase() {
String dbPath = mContext.getDatabasePath(DATABASE_NAME).getPath();
if (mDatabase != null && mDatabase.isOpen()) {
return;
}
mDatabase = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE);
}
private void closeDatabase() {
if (mDatabase != null) {
mDatabase.close();
}
}
}
Database should be created or updated using onCreate or onUpgrade in QuizDbHelper after calling mDBHelper.getReadableDatabase(); onCreate in Mainavtivity.java ... example:
Mainavtivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
QuizDbHelper mDBHelper = new QuizDbHelper(this);
mDBHelper.getReadableDatabase();
SOME OTHER CODE
}
I NEED Two thing::
1. Reflect all changes after users update the app
2. PRESERVE user's data (scores) that are already stored in the database.
I haven't ever had to do this for one of my apps, but if I did, I would have a method to merge the new version of the database with the old one. The basic flow would be to see if the local database were present, if not, copy the new database to the local folder. If it does exist, check the db version. If the db version is less than the new database version, then copy the new database to the local folder with a temp name, then call doMerge().
doMerge would open the new database and select all rows from one of the tables into a cursor. Then, it would iterate through the cursor and do a select query on the old database to see if that record already exists in the old database, if so, skip it. Say, the new database has a cursor of all of the Stages records, you take each record's Name or Description value and "SELECT * FROM old.stages WHERE Name = '" + newName + "'"
If not found, insert the values from the new database into the old database. Repeat this for all three tables.
The trick will be managing the primary keys in each table. What if the user has inserted 50 records in one of the tables, and those keys match the primary keys in the new rows in the new database? If you have primary/foreign keys in your other tables, you would have to sync them, which would get hairy.
I managed to achieve the first objective
reflecting all changes after app upgrade ... here is what I have done:
**// 1. Check database version:**
private Boolean checkDataBaseVersion() {
Boolean Upgrade = false;
SQLiteDatabase db = mContext.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
Integer CurrentdbVersion = db.getVersion();
if (CurrentdbVersion < DATABSE_VERSION) {
Upgrade = true;
} else {
Upgrade = false;
}
Log.w("POSITIVE ...", "checkDataBase - Database Upgrade = " + Upgrade + " ... CurrentdbVersion: "
+ CurrentdbVersion + " DATABSE_VERSION: " + DATABSE_VERSION);
db.close();
return Upgrade;
}
**// 2. change copy database code:**
public void copyDataBase() {
if (!checkDataBase()) {
this.getReadableDatabase();
this.close();
try {
copyDBFile();
Log.w("POSITIVE ...", "copyDataBase - Database does not exists ... db copied");
} catch (IOException mIOException) {
throw new Error("حدث خطأ في نسخ قاعدة البانات من الملف");
}
} else if (checkDataBaseVersion()) {
//this.getReadableDatabase();
//this.close();
try {
copyDBFile();
Log.w("POSITIVE ...", "copyDataBase - Database exists - new version exists ... db copied ");
} catch (IOException mIOException) {
throw new Error("حدث خطأ في نسخ قاعدة البانات من الملف");
}
} else {
Log.w("POSITIVE ...", "copyDataBase - Database exists - no new version ... nothing done ");
}
}
private boolean checkDataBase() {
File dbFile = new File(DATABASE_LOCATION + DATABASE_NAME);
Log.w("POSITIVE ...", "checkDataBase - Database exists = " + dbFile.exists());
close(); /// NEW
return dbFile.exists();
}
**// 3. remove copy database code from public QuizDbHelper(Context context) and place it where it is needed:**
public QuizDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABSE_VERSION);
if (android.os.Build.VERSION.SDK_INT >= 17)
DATABASE_LOCATION = context.getApplicationInfo().dataDir + "/databases/";
else
DATABASE_LOCATION = "/data/data/" + context.getPackageName() + "/databases/";
this.mContext = context;
}
I am using an SQLite db in my android application and I setup helper classes for each table in the db. There are many tables and these classes just handle all the crud methods for each table. I followed example #6 here
I'm having an issue when there are multiple instances of the helper classes instantiated. The database is only available when one helper class is instantiated at a time.
public class ProjectsHelper {
SQLiteDatabase db;
DataBaseHelper dbHelper;
private String TABLE_NAME = "Projects";
public ProjectsHelper(Context context){
if(dbHelper == null){
dbHelper = new DataBaseHelper(context);
}
}
public void open() throws SQLException {
try {
if(!isOpen()){
db = dbHelper.getWritableDatabase();
}
} catch (Exception e){
e.printStackTrace();
}
}
private boolean isOpen(){
return db != null && db.isOpen();
}
public void close() {
if(isOpen()){
dbHelper.close();
db.close();
dbHelper = null;
db = null;
}
}
public long insert(Project obj){
ContentValues values = new ContentValues();
values.put("ProjName", obj.getProjName().trim());
if(!Utilities.empty(obj.getProjDesc())){
values.put("ProjDesc", obj.getProjDesc().trim());
}
if(!Utilities.empty(obj.getProjNumber())){
values.put("ProjNum", obj.getProjNumber().trim());
}
values.put("ServerID", obj.getServerID());
values.put("GUID", obj.getGUID());
values.put("ModDate", obj.getModDate());
long id = db.insert(TABLE_NAME, null, values);
return id;
}
}
public class DataBaseHelper extends SQLiteOpenHelper {
//The Android's default system path of your application database.
public static String DB_PATH = "/data/data/com.siscoders.arscompnentinspector/databases/";
public static String DB_NAME = "ARSInspection.db";
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;
try {
createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
//openDataBase();
}catch(SQLException sqle){
throw sqle;
}
}
/**
* 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);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
#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) {
}
}
my app experiences a crash when the sqlite database is updated the first time. Reloading the app, it works fine from then on. I'm guessing this has to do with the onUpgrade function then. I can't seem to locate where the problem is, any advice very appreciated. Thanks in advance.
DatabaseHelper:
public class DatabaseHelper extends SQLiteOpenHelper {
private static String DB_PATH = "/data/data/jp.atomicideas.ne/databases/";
private static String DB_NAME = "dataset";
public static final int DB_VERSION = 2;
private SQLiteDatabase myDataBase;
private final Context myContext;
public static final String EXPRESSION_TABLE = "expression";
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access
* the assets and resources.
*
* #param context
*/
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.myContext = context;
}
/**
* Creates an empty database on the system and rewrites with database from app
* #throws IOException
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
// if the database already exists, do nothing
if(dbExist){
Log.v("DB Exists", "db exists");
// by calling this method here, onUpgrade will be called on a writeable db, if version number is bumped
this.getWritableDatabase();
}
dbExist = checkDataBase();
// if the database doesn't exist, copy the application's database to be used
if(!dbExist) {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exists to avoid re-copying the file
* #return true only if it exists, falls if it doesnt
*/
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 not exist yet
}
if(checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
/**
* Copies database from the local assets folder to the system folder
* #throws IOException
*/
private void copyDataBase() throws IOException {
// Open the app database file as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the empty temporary database to be replaced
String outFileName = DB_PATH + DB_NAME;
// Open the empty database file as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// Transfer bytes from the input file 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();
}
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) {
Toast.makeText(myContext, "onUpgrade called!", Toast.LENGTH_LONG).show();
if (oldVersion < newVersion) {
Log.v("Database Upgrade", "Database version higher, upgrading");
myContext.deleteDatabase(DB_NAME);
}
}
}
And here is the LogCat output:
06-28 20:52:07.638: V/DB Exists(26580): db exists
06-28 20:52:07.658: V/Database Upgrade(26580): Database version higher, upgrading
06-28 20:52:07.658: I/Database(26580): sqlite returned: error code = 1802, msg = statement aborts at 3: [PRAGMA user_version = 2]
06-28 20:52:07.658: E/Database(26580): Failure 10 (disk I/O error) on 0x33a3f0 when executing 'PRAGMA user_version = 2'
06-28 20:52:07.658: I/Database(26580): sqlite returned: error code = 1, msg = statement aborts at 2: [ROLLBACK;] cannot rollback - no transaction is active
06-28 20:52:07.658: E/Database(26580): Failure 1 (cannot rollback - no transaction is active) on 0x33a3f0 when executing 'ROLLBACK;'
06-28 20:52:07.658: D/Database(26580): exception during rollback, maybe the DB previously performed an auto-rollback
06-28 20:52:07.668: D/AndroidRuntime(26580): Shutting down VM
06-28 20:52:07.668: W/dalvikvm(26580): threadid=1: thread exiting with uncaught exception (group=0x2aac8578)
AND
06-28 20:52:07.678: E/AndroidRuntime(26580): Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error: PRAGMA user_version = 2
You don't need to delete the database, just copy over it using the method you've alady defined (copyDataBase), like this:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Toast.makeText(myContext, "onUpgrade called!", Toast.LENGTH_LONG).show();
if (oldVersion < newVersion) {
Log.v("Database Upgrade", "Database version higher, upgrading");
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error upgrading database");
}
}
}
i'm a beginner in java and android. now i want to work with external database (cancer.db).
i created "DataBaseHelper" class.
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/YOUR_PACKAGE/databases/";
private static String DB_NAME = "myDBName";
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;
}
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.}
then i use codes below in "on create" method to create or open database:
private static String DB_PATH = "/data/data/info.myprogram/databases/";
private static String DB_NAME = "cancer.db";
DataBaseHelper myDbHelper = new DataBaseHelper();
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;
}
i use these codes to get query. my table name is "shb":
SQLiteDatabase db;
Cursor cc= db.rawQuery("SELECT Name FROM shb WHERE _id=1",null);
cc.moveToFirst();
String sss=cc.getString(1);
now when i start debugging i get errors. what's the wrong code? whats my mistake? how should i get query?
and excuse me for my weak English, because it's not my mother tongue .
First create a sqlite database and create table inside it, put it in assets folder of your app.use that database by using following code. please make changes in code for your datbaseName, tableName, fieldsName and path of database etc. i have also write the code of getting list of data by passing paerticuler value.
public class MySQLiteHelper extends SQLiteOpenHelper {
public static final String TABLE_CARS = "Cars";
public static final String COL_ENAME = "ename";
public static final String COL_MODAL = "modal";
public static final String COL_ANAME = "aname";
public static final String COL_TYPES = "types";
private static final String TAG = "MSSS : DatabaseHelper";
// Your Database Name
private static final String DATABASE_NAME = "4saleCars.sqlite";
// Your Your Database Version
private static final int DATABASE_VERSION = 1;
private final Context myContext;
private SQLiteDatabase myDataBase;
// The Android's default system path of your application database. DB_PATH =
// "/data/data/YOUR_PACKAGE/databases/"
private String DB_PATH = "/data/data/net.forsalemall.android/databases/";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
try {
createDataBase();
} catch (Exception e) {
Log.e(TAG,
"DatabaseHelper_constuctor createDataBase :"
+ e.fillInStackTrace());
}
}
#Override
public void onCreate(SQLiteDatabase database) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// ***************************** My DB Handler Methods
// *****************************
/**
* Creates a empty database on the system and rewrites it with your own
* database.
**/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
// Database already exist
openDataBase();
} 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.
myDataBase = getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error createDataBase().");
}
}
}
/**
* 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 + DATABASE_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;
}
/*
* public boolean isDataBaseExist() { File dbFile = new File(DB_PATH +
* DATABASE_NAME); return dbFile.exists(); }
*/
/**
* 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 transferring bytestream.
**/
private void copyDataBase() throws IOException {
try {
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DATABASE_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();
} catch (IOException e) {
throw new Error("Error copyDataBase().");
}
}
public void openDataBase() throws SQLException, IOException {
try {
// Open the database
String myPath = DB_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
throw new Error("Error openDataBase().");
}
}
// ***************************** My DML Methods
// *****************************
public List<String> getModalList(String aname, Context context) {
List<String> list = new ArrayList<String>();
list.add(context.getResources().getString(R.string.all));
Cursor cursor;
String query;
query = "SELECT modal FROM Cars WHERE aname = '" + aname + "';";
try {
cursor = myDataBase.rawQuery(query, null);
if (cursor != null) {
while (cursor.moveToNext())
list.add(Utils.getDecodedString(cursor.getString(0)));
}
cursor.deactivate();
} catch (Exception e) {
Log.e(TAG, "getModalList Error : " + e.fillInStackTrace());
}
return list;
}
}
use this getModalList in your activity just like below
MySQLiteHelper dbHelper = new MySQLiteHelper(
AdvanceSearchActivity.this);
String aname = Utils.getEncodedString(catName);
car_modal = dbHelper.getModalList(aname,AdvanceSearchActivity.this);
i am newbie with android sqlite database. now i just try to create my custom database manager and i got the error at oncreate() function. I already spent 3 days to figure it out but unfortunately i am still stuck in it. Any brilliant idea would be appreciate.
public class DBManager extends SQLiteOpenHelper {
private SQLiteDatabase db;
private static Context myContext;
public static final String DB_NAME = "goldenland.db";
public static final String TB_CAT = "tbl_categories";
public static final String TB_ARTICLE = "tbl_articles";
public static final String TB_SUBCAT = "tbl_subcategories";
public static final String TB_SCHEDULE = "tbl_schedule";
public static final String TB_CONTENT = "tbl_contents";
public static final String TB_CITY = "tbl_cities";
public static final String name = "name";
public static String DB_PATH = "/data/data/com.gokiri.goldenland/databases/";
public DBManager(Context context) {
super(context, DB_NAME, null, 1);
DBManager.myContext = context;
}
public void createDataBase() throws IOException {
boolean dbExit = checkDataBase();
if (dbExit) {
System.out.println("Testing");
} else {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDb = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDb = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
} catch (SQLException e) {
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null ? true : false;
}
public void copyDataBase() throws IOException {
InputStream myInput = myContext.getAssets().open("goldenland_2.sqlite");
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDatabase() throws SQLiteException {
String myPath = DB_PATH + DB_NAME;
db = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
}
A few things might be wrong. Does your database really exist in res/assets? Are you writing to the correct directory? Stepping through with the debugger would go a long way toward diagnosing the problem.
You might get a sanity check by having copyDatabase take a String argument, which would be this.getReadableDatabase().getPath(). You might even try writing that out to the log to see if you're writing to the correct database directory.
Few things to check.
1. in method checkDataBase open the database in OPEN_READONLY mode.
2. this is very important check that the size of the database is less than 1 mb. Android version previous to 3.0 don't allow file copy of more than 1 mb.
Update:
You will need to split the database file into parts of 1Mb each, copy all parts one by one and join them together again. refer to following link
unless you didnt put up all your code, it seems to me that you are missing somethings. I used this tutorial and had no problems
http://www.devx.com/wireless/Article/40842/1954
hope that helps