SQLiteOpenHelper: onCreate() method not called on physical device

余生长醉 提交于 2019-12-12 20:18:21

问题


I have done many tests on an android emulator running in version 4.4. On my app I create a sqlite database with one table using SQLiteOpenHelper:

package com.findwords.modeles;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import com.findwords.MainActivity;
import com.findwords.controleurs.MenuController;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by louk on 02/01/14.
 */
public class DictionaryDbHelper extends SQLiteOpenHelper{

    // declare constants fields
    private static final String DB_PATH = "/data/data/com.findwords/databases/";
    private static final String DB_NAME = "dictionary_db";
    private static final int DB_VERSION = 1;

    // declared constant SQL Expression
    private static final String DB_CREATE =
            "CREATE TABLE dictionary ( " +
                    "_id integer PRIMARY KEY AUTOINCREMENT, " +
                    "word text NOT NULL, " +
                    "definition text NOT NULL, " +
                    "length integer NOT NULL " +
                    ");";

    private static final String DB_DESTROY =
            "DROP TABLE IF EXISTS dictionnary";

    /*
     * constructor
     */
    public DictionaryDbHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    /**
     * 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 = MenuController.getInstance().getMainActivity().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();

    }

    /*
     * (non-Javadoc)
     * @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DB_CREATE);

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

    /*
     * (non-Javadoc)
     * @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DB_DESTROY);
        onCreate(db);
    }
}

Moreover I have written an adapter with a method open:

/*
 * open database connection
 */
public DictionaryDbAdapter open() throws SQLException {
    mDbHelper = new DictionaryDbHelper(mContext);
    mDb = mDbHelper.getWritableDatabase();
    return this;
}

It's working well on the emulator so the onCreate() method of the SQLiteOpenHelper class is called and create the database, but is not called on my phone (Google Nexus 5).

My phone is not rooted so I can't access the folder /data/data/com.myapp/databases .

However I want this application to work on any phone so I don't want to root my phone.

Thanks in advance to anyone who could help me.


回答1:


Let i try to explain you some things.

In an application to connect to the database , we specify the name and version of the database . In this situation, the following may occur :

1) There is no database . This may be for example in the case of initial setting program. In this case, the application itself must create the database and all the tables in it. And further, it is already working with the newly created database.

2) Database exists, but its version is outdated. It may be the case update. For example a new version of the program need additional fields in the old tables or new tables . In this case, the application must update existing tables and create new ones if necessary.

3) There is a database and its actual version . In this case, the application successfully connects to the database and running.

As you know , the phrase " application must " tantamount to the phrase " the developer must ", ie it is our task . To handle the situations described above , we need to create a class that inherits for SQLiteOpenHelper. Call it DBHelper. This class will provide us with methods to create or update the database in case of their absence or obsolescence.

onCreate - a method that will be called if the database to which we want to connect - does not exist(it's your case)




回答2:


The onCreate method is called only for the first time - when the DB is actually created. So if you uninstall your app and then install it again - it will get called, but if you install on top of the existing copy onCreate will not be called (since the DB already exists)




回答3:


As @Asahi said, Database is only created only if you reinstall the app. But since you said that My phone is not rooted so I can't access the folder /data/data/com.myapp/databases, I want to point out that you can connect your mobile to the computer, install the correct USB drivers and use DDMS to see the file structure of your mobile phone. There you can see the database of your app along with the Shared Preferences and other files.

PS :- To see all the folder of real device on ddms you need root access. If your device is not rooted and you don't want to root your one then you can install the device on emulator which shows all folders in DDMS.



来源:https://stackoverflow.com/questions/20936272/sqliteopenhelper-oncreate-method-not-called-on-physical-device

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!