1

我正在将我的资产文件夹中的数据库文件复制到安装时的数据库文件夹中。我有一个名为 firstRun 的共享首选项,默认值为 true。如果这是真的,那么我复制数据库文件并将 firstRun 值设置为假。在此过程之后,我立即在数据库表中查询一些数据。在较旧的 Android 版本 (2.1) 上,会发生 SQLite 异常(没有这样的表)并且应用程序崩溃,在 Android 4.2.1 上,dbHelper 会记录相同的消息,但会继续运行并从它未能找到的表中返回值。使用较早的 Android 版本,如果我再次启动该应用程序,则会找到数据库表,并且所有操作都会正常进行。应用程序崩溃后,我可以检查复制的数据库以及表和行是否存在。这似乎与其他真正不存在表的问题不同,因为我可以看到它们确实存在。我想知道这是否是某种同步问题,在复制过程之后表不立即存在,但在进程完成后的某个时刻存在。据我所知,这不是异步完成的,所以我不确定为什么。

这是一些显示问题的代码:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean firstRun = prefs.getBoolean(getString(R.string.first_time_run), true);

if (firstRun) {
    SharedPreferences.Editor edit = prefs.edit();
    edit.putBoolean(getString(R.string.first_time_run), Boolean.FALSE);
    edit.commit();

    try {
        dbHelper.createDatabase();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}
// This method will fire an exception the first time the app is run - no such table
Bundle metaData = dbHelper.fetchAppMetaData();
this.appTitle = metaData.getString("app_title");
this.normalId = Integer.parseInt(metaData.getString("normal_id"));

fetchAppMetaData 方法是一个基本的 sqlite.query:

Bundle metaData = new Bundle();
Cursor dbCursor = null;
SQLiteDatabase database = getReadableDatabase();
String[] cols = new String[] {"app_title", "normal_id"};
dbCursor = database.query(true, TBL_METADATA, cols, null, null, null, null, null, null);  

if (dbCursor != null) {  
        dbCursor.moveToFirst();

最终会返回一个包。

数据库创建方法为:

//Open the local db as the input stream
InputStream dbFromAssets = myContext.getAssets().open(DB_NAME);

// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;

// Check that the directory now exists
File f = new File(DB_PATH);

if (!f.exists()) {
    f.mkdir();
}

// Open the empty db as the output stream
OutputStream appDatabase = new FileOutputStream(outFileName);

// Transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = dbFromAssets.read(buffer)) > 0){
    appDatabase.write(buffer, 0, length);
}

// Close the streams - don't cross them!
appDatabase.flush();
appDatabase.close();
dbFromAssets.close();

如有任何想法,将不胜感激。

4

2 回答 2

1

下面是工作代码的剪切和粘贴。每次应用程序加载时,我都会在 MainActivity 启动时使用它。测试和使用版本 2.3 - 4.2:

这是我正在使用的检查代码:

try 
    {           
        String destPath = "/data/data/" + getPackageName() + "/databases/(...your db...)";

        File f = new File(destPath);  
        File c = new File("/data/data/" + getPackageName() + "/databases/");

        // ---if directory doesn't exist then create it---
        if (!c.exists()) 
        { 
            c.mkdir();
        }

        // ---if db file doesn't exist then create it---
        if (!f.exists()) 
        { 
            CopyDB(getBaseContext().getAssets().open("...name of db from assets foleder..."), new FileOutputStream(destPath));
        }
    } 
    catch (FileNotFoundException e) 
    {           
        e.printStackTrace();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }

这是我正在使用的代码,如果找不到则进行复制:

public void CopyDB(InputStream inputStream, OutputStream outputStream) throws IOException 
{
    //---copy 1K bytes at a time---
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inputStream.read(buffer)) > 0) 
    {
        outputStream.write(buffer, 0, length);
    }

    inputStream.close();
    outputStream.close();
}

希望这是有希望的...

于 2013-02-13T12:36:32.690 回答
1

我的解决方案是在创建数据库后关闭 dbHelper,然后再尝试再次使用它。

例如:

try {
    dbHelper.createDatabase();
} catch (Exception e) {
}
dbHelper.close();
dbHelper.fetchAppMetaData();

希望这对其他人有帮助。

于 2013-02-13T13:06:34.273 回答