开发者

How to use my own sqlite database?

I put my database field in "assets" folder. And use the code from this blog to copy the database to "/data/data/my_packname/databases/", (This copy code i run it in the onCreate() method when i run this app) then use select * from ... to get data. But it gives me the exception: no such table.

Someone told me that if i am attempting to copy the file in SQLiteOpenHelper's onCreate(), it's too late. So the copy file code can not copy the complete file.

So i need to use adb or ddms to pull the database first?

So, Any开发者_开发技巧one can teach me how to use my own databse? Can you tell me the setup?


I've used the instructions in that blog post and found them, while on the right track, to severely complicate the issue by unnecessarily extending SQLiteOpenHelper. I've had much better luck doing the following:

  1. Create a utility class that creates the static db by copying it into the correct directory from assets, but doesn't get itself so hung up on following the SQLiteOpenHelper format.

  2. Using the same utility class to open the db by using SQLiteDatabase.openDatabase()

Edit: Here is a version of this utility class I've created; it's not quite complete, but you'll get the drift.

public class DbUtils {
    private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/";
    private static final String DB_NAME = "my.db";

    public static void createDatabaseIfNotExists(Context context) throws IOException {
        boolean createDb = false;

        File dbDir = new File(DB_PATH);
        File dbFile = new File(DB_PATH + DB_NAME);
        if (!dbDir.exists()) {
            dbDir.mkdir();
            createDb = true;
        }
        else if (!dbFile.exists()) {
            createDb = true;
        }
        else {
            // Check that we have the latest version of the db
            boolean doUpgrade = false;

            // Insert your own logic here on whether to upgrade the db; I personally
            // just store the db version # in a text file, but you can do whatever
            // you want.  I've tried MD5 hashing the db before, but that takes a while.

            // If we are doing an upgrade, basically we just delete the db then
            // flip the switch to create a new one
            if (doUpgrade) {
                dbFile.delete();
                createDb = true;
            }
        }

        if (createDb) {
            // Open your local db as the input stream
            InputStream myInput = context.getAssets().open(DB_NAME);

            // Open the empty db as the output stream
            OutputStream myOutput = new FileOutputStream(dbFile);

            // 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 static SQLiteDatabase getStaticDb() {
        return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
    }
}


After you've copied the database, you should try closing and reopening the SQLiteDatabase object before executing any query on it. I had a similar problem with copying a db from an input stream and that's what solved it for me.


here is my Version from "Silvio Donnini" Code :), now you can update the Database easily.

private static final String DB_PATH = "/data/data/pakagename/databases/";
private static final String DB_NAME = "databaseName";     
private static SQLiteDatabase db;

public static void createDatabaseIfNotExists(Context context,int version) throws IOException {
    boolean createDb = false;

    File dbDir = new File(DB_PATH);
    File dbFile = new File(DB_PATH + DB_NAME);
    if (!dbDir.exists()) {
        dbDir.mkdir();
        createDb = true;
    }
    else if (!dbFile.exists()) {
        createDb = true;
    }
    else {
        // Check that we have the latest version of the db       
         db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);

        if (db.getVersion() != version) {
            dbFile.delete();
            createDb = true;
        }

    }

    if (createDb) {

        // Open your local db as the input stream
        InputStream myInput = context.getResources().openRawResource(R.raw.database);

        // Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(dbFile);

        // 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();
        SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
        dbwrite.setVersion(version);
        dbwrite.close();
        if (db != null)
            db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);

    }
}

public static SQLiteDatabase getStaticDb() {
     if (db != null)
         return db;

    return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}


I know this is an old question, but I lost a lot of time figuring it out, with the help of all the replies.


The issue is that a device stores a database in his data/data/.../databases folder. So, when you change sth about the database (name, add android metadata table, size..) it wont make any difference because of the stored database and the method that checked for existing database.


To get the newest database, after changing it, you must run the program without checking for existing databses (e.g. instead of dbExist = checkDataBase(); make it just false).

dbExist = checkDataBase();

Change to:

dbExists = false;

After you picked up the "new" databse you can return to checking the existing ones.

Hope it helps someone, dina


I know this is an old post, but for those who still get here after a Google or a Bing search, this is the solution to the stated problem:

in createDataBase() there is the following check;

this.getReadableDatabase();

This checks if there is already a database with the provided name and if not creates an empty database such that it can be overwritten with the one in the assets folder. On newer devices this works flawlessly but there are some devices on which this doesn't work. Mainly older devices. I do not know exactly why, but it seems like the getReadableDatabase() function not only gets the database but also opens it. If you then copy the database from the assets folder over it, it still has the pointer to an empty database and you will get table does not exist errors.

So in order to make it work on all devices you should modify it to the following lines:

SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
    db.close();
}

Even if the database is opened in the check, it is closed thereafter and it will not give you any more trouble.


Calm down guys,After long research finally found silly mistake for "no such table" error

Check name of database in Assets folder if it's like "DATABASE_NAME.EXTENSION" then put full name in Helper class with extension its solved my problem.

like say in Assets name of database is login.sqlite or login.db anything. put DB_NAME=login.sqlite fully with extention. this tutorial now works perfectly.


The way of creating database from article you've posted is slightly diffrent from that how it's done in android examples (I don't want to say if it's good or bad).

I've learned how to use databases from SDKs NotePad sample

It's good example to start from, becouse it covers both database creation topic and database access through ContentProvider (it's really the only good way to get data from db, otherwise you will have problems when trying to get data simultaneusly from many places of your code).

You should note that SQLiteOpenHelper is really powerful and "it will help you" if you will use it properly. For example it stores current database version (not sqlite version but number you assingn with database schema version) and when you create new application version with new database structure you can update current schema to the new version in onUpdate.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜