1
votes

I am loading a database file in assets called mydb. I then use the code below to load the database file onto the emulator. This works sometimes but not always. I reset eclipse and the database file loads up correctly. I cannot get it to work at all on the real device. I have tried this with other experiemental files project. I think there is a setting I have not configured correctly but I am not not sure. Any help would be greatly appreciated.

methods tried

  1. I tried to use the android_meta table as this was suggest to fix issues of databases not being loaded.

  2. I can also had records using this sort of syntax. This will even work on the lives device long id = db.insertContact("Wei-Meng Lee", "[email protected]"); This code snipet is taken from the book android development

  3. I am making the code alterations that where specified in the example

entire fault log

06-21 15:17:56.792: E/AndroidRuntime(556): FATAL EXCEPTION: main 06-21 15:17:56.792: E/AndroidRuntime(556): java.lang.RuntimeException: Unable to start activity ComponentInfo{alex.android.test.db/alex.android.test.db.AndroidtestdbActivity}: android.database.sqlite.SQLiteException: no such table: contacts: , while compiling: SELECT DISTINCT _id, name, email FROM contacts WHERE _id=2 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread.access$600(ActivityThread.java:123) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.os.Handler.dispatchMessage(Handler.java:99) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.os.Looper.loop(Looper.java:137) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread.main(ActivityThread.java:4424) 06-21 15:17:56.792: E/AndroidRuntime(556): at java.lang.reflect.Method.invokeNative(Native Method) 06-21 15:17:56.792: E/AndroidRuntime(556): at java.lang.reflect.Method.invoke(Method.java:511) 06-21 15:17:56.792: E/AndroidRuntime(556): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 06-21 15:17:56.792: E/AndroidRuntime(556): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 06-21 15:17:56.792: E/AndroidRuntime(556): at dalvik.system.NativeStart.main(Native Method) 06-21 15:17:56.792: E/AndroidRuntime(556): Caused by: android.database.sqlite.SQLiteException: no such table: contacts: , while compiling: SELECT DISTINCT _id, name, email FROM contacts WHERE _id=2 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteCompiledSql.(SQLiteCompiledSql.java:68) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteProgram.compileSql(SQLiteProgram.java:143) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteProgram.compileAndbindAllArgs(SQLiteProgram.java:361) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:127) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:94) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteQuery.(SQLiteQuery.java:53) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:47) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1564) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1449) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1405) 06-21 15:17:56.792: E/AndroidRuntime(556): at alex.android.test.db.DBAdapter.getContact(DBAdapter.java:163) 06-21 15:17:56.792: E/AndroidRuntime(556): at alex.android.test.db.AndroidtestdbActivity.onCreate(AndroidtestdbActivity.java:32) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.Activity.performCreate(Activity.java:4465) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) 06-21 15:17:56.792: E/AndroidRuntime(556): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)

public class DBAdapter {

 private static final String DB_NAME = "MyDB";
private static final int DB_VERSION = 1;
 public static final String KEY_ROWID = "_id";
    public static final String KEY_NAME = "name";
    public static final String KEY_EMAIL = "email";
    private static final String TAG = "DBAdapter";
    private static final String DATABASE_TABLE = "contacts";

private static Context c;
private SQLiteDatabase db;
private SQLiteOpenHelper sqlDBHelp;

/**
 * Constructor for the SQL DB Adapter, copy DB from assets if not exists in /data/data/<package-name>/databases
 * 
 * @param c
 */
public DBAdapter(Context c) {
    super();
    DBAdapter.c = c;
    sqlDBHelp = new SqlDBHelper();
}

/**
 * Open the SQL DB as Writable
 */
public void openDB() {
    try {
        db = sqlDBHelp.getWritableDatabase();
    } catch (SQLiteException ex) {
        Toast.makeText(c, "DB with filename " + DB_NAME + "coudn't be opend!", Toast.LENGTH_SHORT);
    }
}

/**
 * Close the SQL DB
 */
public void closeDB() {
    db.close();
}

/**
 * Helper class for the SQL DB Adapter
 */
static class SqlDBHelper extends SQLiteOpenHelper {

    private static final String DB_PATH = "/data/data/" + c.getPackageName() + "/databases/" + DB_NAME;

    public SqlDBHelper() {
        super(c, DB_NAME, null, DB_VERSION);
        createDB();     
    }

    private void createDB() {

        SharedPreferences prefs = c.getSharedPreferences("sharedPrefs", 0);
        boolean dbExists = prefs.getBoolean("dbExists", false);
        Log.d("PM.ADA.SDA", "DB Exists : " + dbExists);
        if (!dbExists) {
            this.getReadableDatabase();
            copyDB();
            prefs.edit().putBoolean("dbExists", true).commit();
        }
    }


    public void onCreate(SQLiteDatabase db) {
        /*
        try {
            db.execSQL(DATABASE_TABLE); 
        } catch (SQLException e) {
            e.printStackTrace();
        }   
        */

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

         Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS contacts");
            onCreate(db);


    }

    public void copyDB() {
        try {               
            InputStream is = c.getAssets().open(DB_NAME);
            BufferedInputStream bis = new BufferedInputStream(is);
            OutputStream os = new FileOutputStream(DB_PATH);
            BufferedOutputStream bos = new BufferedOutputStream(os);

            byte[] buffer = new byte[64];
            int length;

            while ((length = bis.read(buffer)) > 0) {
                bos.write(buffer, 0, length);
            }

            bos.flush();
            bos.close();
            bis.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

public long insertContact(String name, String email) 
{
    ContentValues initialValues = new ContentValues();
    initialValues.put(KEY_NAME, name);
    initialValues.put(KEY_EMAIL, email);
    return db.insert(DATABASE_TABLE, null, initialValues);
}

//---deletes a particular contact---
public boolean deleteContact(long rowId) 
{
    return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

//---retrieves all the contacts---
public Cursor getAllContacts() 
{
    return db.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
            KEY_EMAIL}, null, null, null, null, null);
}

//---retrieves a particular contact---
public Cursor getContact(long rowId) throws SQLException 
{
    Cursor mCursor =
            db.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
            KEY_NAME, KEY_EMAIL}, KEY_ROWID + "=" + rowId, null,
            null, null, null, null);
    if (mCursor != null) {
        mCursor.moveToFirst();
    }
    return mCursor;
}

//---updates a contact---
public boolean updateContact(long rowId, String name, String email) 
{
    ContentValues args = new ContentValues();
    args.put(KEY_NAME, name);
    args.put(KEY_EMAIL, email);
    return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}

}

other activity TextView name;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    DBAdapter db = new DBAdapter(this); 
    name = (TextView)findViewById(R.id.name);



    //---get a contact---
    db.openDB();
    Cursor c = db.getContact(2);
    if (c.moveToFirst())  
    {
        DisplayContact(c);
    name.setText(String.valueOf(c.getString(1)));
    }
    else
        name.setText("not found");
        Toast.makeText(this, "No contact found", Toast.LENGTH_LONG).show();
    db.closeDB();

}

public void DisplayContact(Cursor c)
{
    Toast.makeText(this, 
            "id: " + c.getString(0) + "\n" +
            "Name: " + c.getString(1) + "\n" +
            "Email:  " + c.getString(2),
            Toast.LENGTH_LONG).show();  


}  

}

1
I'm confused... the error you posted has at alex.android.test.db.DBAdapter$DatabaseHelper.copyDataBase(DBAdapter.java:88), but I don't see that method anywhere in the code you posted.Barak
i have updated the code again and used another post i foundalex
It looks like your DB is being copied now... but I'm betting you deleted your contacts table... My guess would be that the database has a verion number of 1 coded into it, but your java code has a version of 2, so it called the onUpgrade method, which deleted the contacts table and then called your empty onCreateMethod, which did nothing. If that's the case, change your version number back to one, uninstall your app and reinstall and you might be in business.Barak
I made the change but still have the same error I tested it on the live device and deleted the app before up loading it againalex

1 Answers

1
votes

I see a few differences from how I do it... You are missing an outputStream.flush(), and I call this.getReadableDatabase(); before I start my copy process and this.close(); after.

For your reference, here is how I do it and it works fine:

private static class DatabaseHelper extends SQLiteOpenHelper {
    DatabaseHelper(Context context, String dbname, int dbversion) {
        super(context, dbname, null, dbversion);
        if (checkDataBase(dbname)) {
            openDataBase(dbname);
        } else {
            try {
                this.getReadableDatabase();
                copyDataBase(dbname);
                this.close();
                openDataBase(dbname);
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
            Toast.makeText(context,
                    "Initial " + dbname + " database has been created",
                    Toast.LENGTH_LONG).show();
        }
    }


public DBAdapter(Context ctx) {
    DBAdapter.mCtx = ctx;
}

private static boolean checkDataBase(String dbname) {
    SQLiteDatabase checkDB = null;
    boolean exist = false;
    try {
        String db = MAIN_DB_PATH + dbname;
        checkDB = SQLiteDatabase.openDatabase(db, null,
                SQLiteDatabase.OPEN_READONLY);
    } catch (SQLiteException e) {
        Log.v("db log", "database does't exist");
    }
    if (checkDB != null) {
        exist = true;
        checkDB.close();
    }
    return exist;
}

private static void copyDataBase(String dbname) throws IOException {
    InputStream myInput = mCtx.getAssets().open(dbname);
    String outFileName = MAIN_DB_PATH + dbname;
    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();
}