android - 数据库文件未从 Assets 复制到 data/data/<package name>/databases

标签 android mysql database sqlite assets

与此问题相关的问题很多,但没有一个对我有帮助。如果我看到我的代码的逻辑,它应该可以工作,但仍然根本无法工作。我在之前的项目中做到了这一点,当时效果很好,但现在不行了。

安装应用程序时,数据库文件位于/data/data//databases/路径中。但说错误:(1)没有这样的表:表名。然后我使用SQLite浏览器打开数据库文件,可以看到只有一张表android_metadata。其他表丢失。它清楚地表明数据库尚未从 Assets 文件夹中复制。相反,它在给定路径中创建新数据库。如果给定的路径在 SDCard 中,那么我的手机上没有 SD 卡,并且我的手机已 root。每次第一次安装应用程序时,我都需要更改data/data//databases/目录的权限才能查看数据库的数据。

但是当我将数据库文件从 Assets 文件夹动态拉到/data/data//databases/时,我的应用程序不会崩溃。当然,我不希望这样做。请您查看我的代码并找出可以更改的内容。谢谢!!

public DatabaseHelper() throws IOException {
    super(Attendance.getContext(), DB_NAME, null, DB_VERSION);
    /*try {
        createDataBase();
        openDataBase();
    } catch (IOException e) {
        e.printStackTrace();
    }*/
    boolean dbexist = checkDataBase();
    if(dbexist){
        openDataBase();
    }else{
        createDataBase();
    }
}

/**
 * Database maintains global state in application
 * 
 * @return singleton instance
 */
public static DatabaseHelper getInstance() {

    if (mInstance == null) {
        try {
            mInstance = new DatabaseHelper();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return mInstance;
}

/**
 * Creates a empty database on the system and rewrites it with your own
 * database.
 * 
 * @throws IOException
 */
public void createDataBase() throws IOException {

    boolean dbexist = checkDataBase();
    if (dbexist) {

    }else{
        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 checkDataBase = null;
    boolean checkDataBase =true;
    try {
        String Path = DB_PATH + DB_NAME;
        File dbFile = new File(Path);
        /*
         * checkDataBase = SQLiteDatabase.openDatabase(Path, null,
         * SQLiteDatabase.OPEN_READONLY);
         */
        checkDataBase = dbFile.exists();
    } catch (SQLiteException e) {
        Log.e("CheckDb", "DB not found");
        // database does't exist yet.
    }
    return checkDataBase;
}

/**
 * Copies your database from 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.
 * 
 * @throws IOException
 */

private void copyDataBase() throws IOException {

    // Open your local database as the input stream
    InputStream myInput = context.getAssets().open(DB_NAME);

    // Open the empty db as the output stream.
    OutputStream myOutput = new FileOutputStream(DB_PATH + DB_NAME);

    // 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 stream.
    myOutput.close();
    myOutput.flush();
    myInput.close();
    Log.i("Database", "New database has been copied to device!");

}

/**
 * Open the database
 * 
 * @throws SQLException
 */
public boolean openDataBase() throws SQLException {
    String path = DB_PATH + DB_NAME;
    db = SQLiteDatabase.openDatabase(path, null,
            SQLiteDatabase.OPEN_READWRITE);
    Log.i("DB....", "database opened....");
    return db != null;
}

public synchronized void close() {
    if (mInstance != null)
        db.close();
    super.close();
}

日志猫:

02-27 13:30:26.509: D/AndroidRuntime(20480): Shutting down VM
02-27 13:30:26.509: W/dalvikvm(20480): threadid=1: thread exiting with uncaught  exception (group=0x4188eba8)
02-27 13:30:26.509: E/AndroidRuntime(20480): FATAL EXCEPTION: main
02-27 13:30:26.509: E/AndroidRuntime(20480): Process: <package-name>, PID: 20480
02-27 13:30:26.509: E/AndroidRuntime(20480): java.lang.RuntimeException: Unable to start activity ComponentInfo{<package-name>/<package-name>.MainActivity}: java.lang.NullPointerException
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.ActivityThread.access$800(ActivityThread.java:135)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.os.Handler.dispatchMessage(Handler.java:102)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.os.Looper.loop(Looper.java:136)
 02-27 13:30:26.509: E/AndroidRuntime(20480):   at android.app.ActivityThread.main(ActivityThread.java:5017)
 02-27 13:30:26.509: E/AndroidRuntime(20480):   at java.lang.reflect.Method.invokeNative(Native Method)
 02-27 13:30:26.509: E/AndroidRuntime(20480):   at java.lang.reflect.Method.invoke(Method.java:515)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at dalvik.system.NativeStart.main(Native Method)
02-27 13:30:26.509: E/AndroidRuntime(20480): Caused by: java.lang.NullPointerException
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.Areva.areva_attendance.helper.DatabaseHelper.copyDataBase(DatabaseHelper.java:172)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.Areva.areva_attendance.helper.DatabaseHelper.createDataBase(DatabaseHelper.java:130)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.Areva.areva_attendance.helper.DatabaseHelper.<init>(DatabaseHelper.java:94)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.Areva.areva_attendance.helper.DatabaseHelper.getInstance(DatabaseHelper.java:107)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com.Areva.areva_attendance.model.Portfolio.<init>(Portfolio.java:25)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at com .Areva.areva_attendance.MainActivity.onCreate(MainActivity.java:43)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.Activity.performCreate(Activity.java:5231)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
02-27 13:30:26.509: E/AndroidRuntime(20480):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
02-27 13:30:26.509: E/AndroidRuntime(20480):    ... 11 more

最佳答案

我想你的 DB_PATH 是硬编码的。

您应该使用 Environment.getDataDirectory() 来获取内部存储路径,因为 Android 可能会根据设备/操作系统版本将其定位在不同的位置。

关于android - 数据库文件未从 Assets 复制到 data/data/<package name>/databases,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22062622/

相关文章:

android - 通知未取消操作点击 android

android - Gradle 异常 : "There must be one branch ID(.bid) file in the root dir of the project"

php - 使用PHP连接MySQL数据库的连接类,插入、更新、删除

mysql - 在 phpmyadmin 中启用关系 View 时出现问题

php - codeigniter transact 将数据添加到两个表中

java - 恢复 ArrayList 中的 CheckBox 状态永远不会将 CheckBox 设置为已选中

c# - 插入多行的最快方法

sql - 过程数据库代码与多个数据库调用

java - H2 DB - 列必须在 Group By 列表中

java - 精确计算两个 double 值之间的差异