简体   繁体   English

SQLiteOpenHelper:未在物理设备上调用onCreate()方法

[英]SQLiteOpenHelper: onCreate() method not called on physical device

I have done many tests on an android emulator running in version 4.4. 我在4.4版本中运行的android模拟器上做了很多测试。 On my app I create a sqlite database with one table using SQLiteOpenHelper: 在我的应用程序上,我使用SQLiteOpenHelper创建一个带有一个表的sqlite数据库:

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). 它在模拟器上运行良好,因此调用SQLiteOpenHelper类的onCreate()方法并创建数据库,但不在我的手机上调用(Google Nexus 5)。

My phone is not rooted so I can't access the folder /data/data/com.myapp/databases . 我的手机没有root权限,因此我无法访问文件夹/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. 提前感谢任何可以帮助我的人。

The onCreate method is called only for the first time - when the DB is actually created. onCreate方法仅在第一次调用时 - 实际创建数据库时。 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) 因此,如果您卸载应用程序然后重新安装它 - 它将被调用,但如果您安装在现有副本之上onCreate将不会被调用(因为数据库已经存在)

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 . 1) 没有数据库 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. 2) 数据库存在 ,但其版本已过时。 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 . 3) 有一个数据库及其实际版本 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. 要处理上述情况,我们需要创建一个继承SQLiteOpenHelper的类。 Call it DBHelper. 称之为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) onCreate - 如果我们要连接的数据库不存在将被调用的方法(这是你的情况)

As @Asahi said, Database is only created only if you reinstall the app. 正如@Asahi所说,只有在重新安装应用程序时才会创建数据库。 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. 但既然你说我的手机没有root,所以我无法访问文件夹/data/data/com.myapp/databases ,我想指出你可以将你的手机连接到电脑,安装正确的USB驱动程序和使用DDMS查看手机的文件结构。 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 . PS: -要在ddms上查看真实设备的所有文件夹,您需要root访问权限 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. 如果您的设备没有root,并且您不想将其设置为root,那么您可以在模拟器上安装该设备,该模拟器显示DDMS中的所有文件夹。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM