3

Newbie here. I received some good info in a previous post I made, and I'm hoping I can get a bit more help :) Thanks for looking.

I am shipping a prepopulated sqlite database with an application. I've gone through the process of copying the database from my assets folder within the source code to the /database/ folder through a routine I found online, that I'm sure you all are familiar with (http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/). This appears to be working correctly. Using DDMS I am able to see the database being copied over and showing up in the proper directory.

Now however, I am getting no results. When I examine logcat, I see the following errors when I attempt to open the DB:

02-19 14:59:40.490: I/Database(4071): sqlite returned: error code = 14, msg = cannot open file at source line 25467
02-19 14:59:40.490: E/Database(4071): sqlite3_open_v2("/data/data/com.testapp.test/databases/pbaMainDb.sqlite", &handle, 2, NULL) failed

EDIT: Here is the ListScreen class I am using to open the database after installation and do a simple query from:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lists);

   DbHelper db = new DbHelper(this);
    db = new DbHelper(this);



    try {
        db.createDatabase();
    } catch (IOException ioe) {
        throw new Error ("Unable to create database");
    }



    try {
    myDbHelper.close();
    db.openDataBase(); 
    } catch(SQLException sqle){
        throw sqle;
  }




}


public Cursor fetchAllTables() {

    return myDbHelper.rawQuery("SELECT name FROM sqlite_master WHERE type='table'",
            new String[]{});

}

private void fillData() {

    //Cursor c = fetchAllTables();
    //startManagingCursor(c);

    String[] from = new String[] {"name"};
    int[] to = new int[] {R.id.listview};


    SimpleCursorAdapter notes = 
            new SimpleCursorAdapter (this, R.layout.list_view, cursor, from, to);
    setListAdapter(notes);

            }

    }

EDIT: Also, from my DbHelper class (where the code is to copy my existing Db), here is the code where I do that (I apologize, it's a bit of a dump):

    public class DbHelper extends SQLiteOpenHelper {
// the default android path of the database files it creates
private static String DB_PATH = "/data/data/com.testdata.test/databases/";
private static String DB_NAME = "pbaMainDb.sqlite";
private SQLiteDatabase myDataBase;
private final Context myContext;

// constructor to keep a reference of the passed context in order to access the 

public DbHelper (Context context) {
    super(context, DB_NAME, null, 1);
    this.myContext = context;
}

// Create an empty database and then rewrite with original

public void createDatabase() throws IOException {
    boolean dbExist = CheckDataBase();
    if (dbExist) {
        // if exists, do nothing
    }else {
        //when we call this method the empty database will be created into 
        this.getReadableDatabase();
        try {
                copyDataBase();
        }
        catch (IOException e) {
                throw new Error("Error copying database");
        }
}
    this.close();
}

        // Check if the database already exists to avoid re-copy
private boolean CheckDataBase() {
    SQLiteDatabase checkDB = null;

    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null                 SQLiteDatabase.OPEN_READWRITE);
        //File dbfile = new File(myPath);
        //return dbfile.exists();
    } catch (SQLiteException e) {
            //database doesn't exist yet
    }
    if (checkDB != null) {
            checkDB.close();
    }
    return checkDB != null ? true : false;
}   
  // Copies database from assets folder to new empty folder

    private void copyDataBase() throws IOException {
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        //path to just created DB

        String outFileName = DB_PATH + DB_NAME;

        OutputStream myOutput = new FileOutputStream (outFileName);

        //transfer bytes from input file to output file

        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 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) {
    }

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

}
ADK
  • 139
  • 2
  • 12

2 Answers2

1

This might seem simple, but try taking off the extension from the database name. i.e., make the path "/data/data/com.testapp.test/databases/pbaMainDb" and take the extension off the file when you put it in your assets folder as well.

Also, I think there might be a size limitation on the database file size. How big is your file?

And one final possibility: right after the app crashes, open it up again (not compile and install but just open it up again on the device) and see if it works. Sometimes the databases folder is not created on the first time around so you might have to go in and create it with some thing like

File f = new File(DB_PATH);
if (!f.exists()) {
    f.mkdir();
}

EDIT: A couple more question. After looking over the tutorial you used, did you also use the createDataBase() method as he shows at the very end?

Also, before you perform your query try calling myDbHelper.close(); and then call the open method again. It is possible that the empty version that he creates in the tutorial is still open and needs to be closed on the first time around

Let me know how these go and I will try to keep helping you if necessary.

EDIT: Replace your onCreate and fetchAllTables with my edits below. For some reason, you had created two instances of the DbHelper class so I removed that. Also, I can't see where you declared myDbHelper that you used on onCreate, but get rid of all references to that. We will only use one instance of DbHelper to interact with the database, and that is db. As you can see, I create this as a class variable that we will use throughout the entire class and instantiate and open once in onCreate. Also pay attention if the error changes, because I am only focusing right now on getting the opening of the database to work.

DbHelper db;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lists);

    db = new DbHelper(this);

    try {
        db.createDatabase();
    }
    catch (IOException ioe) {
        throw new Error ("Unable to create database");
    }

    try {
        db.close();
        db.openDataBase(); 
    } catch(SQLException sqle){
        throw sqle;
    }
}

public Cursor fetchAllTables() {
    return db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
}
koopaking3
  • 3,375
  • 2
  • 25
  • 36
  • Much appreciated on your taking a look at this. I've tried it with/without the extension, and I still get the same results. The DB size shouldn't be an issue, it's very small (4 tables with limited data...I want to get it working before I add more). I also tried to rerun the app (not compile) and I still get the same issue - however I'm certain the "databases" folder IS getting created on the first instance, I'm tracking it in DDMS and seeing the folder/file being created and successfully being copied. I also am calling the createDataBase() method (it was just in the Main class). – ADK Feb 20 '12 at 05:02
  • Also, I just moved it (and included the myDbHelper.close() into the same class as I attempted to open it from above, and am getting the same results. I appreciate any extra assistance you can lend :) – ADK Feb 20 '12 at 05:02
  • Ok, for now let's assume your implementation of the code from the tutorial is good. Could you post the whole code from your main class so I can see how you are opening the DB? – koopaking3 Feb 20 '12 at 05:20
  • Will do, I will change my edits above to the ListScreen.class file, which I am using to open the DB. – ADK Feb 20 '12 at 05:41
  • I updated two pieces of code above. The first is the ListScreen where I try to query and then populate the DB. The second is the DbHelper dump where I copy my database from. Thanks again. – ADK Feb 20 '12 at 05:46
  • Also, since you are new here: at Stack Overflow when someone answers your question, you accept it by clicking the check mark next to their answer so that they get credit. Also, you can "upvote" with the arrows if you think the answer might help others who see the post. Just wanted to let you know in case we can figure this out! – koopaking3 Feb 20 '12 at 06:18
  • Thanks for the Stack Overflow tip! I updated the ListScreen class, and am still getting a number of errors through logcat (I will paste them above in edits.) Also, I had myDbHelper here: "private SQLiteDatabase myDbHelper;" in the ListScreen class in order to use it to execute the RawQuery command. When I use "db" in your code above, it gives me an error on that line in eclipse. – ADK Feb 20 '12 at 06:32
  • Ignore the part about pasting a new error, it's the same one (unable to open file). – ADK Feb 20 '12 at 06:34
  • Try completely uninstalling your app from the device/emulator and reinstalling with Eclipse. – koopaking3 Feb 20 '12 at 07:07
  • Dang, well I'm at my wits end. I'll let you know if I have anything come to me. Good luck! – koopaking3 Feb 20 '12 at 07:16
0

I had same problem, but as one of comments in "http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications" said, I just did this:

replace this line

String myPath = DB_PATH + DB_NAME;

in checkDataBase() method with this:

String myPath = Environment.getExternalStorageDirectory() + "/" + DB_NAME;

It worked well for me.

Mehrdad Salimi
  • 1,400
  • 4
  • 16
  • 31