具有完全限定的数据库路径名的SQLiteOpenHelper问题

在我的应用中,我使用...


myFilesDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()

                      + "/Android/data/" + packageName + "/files");

myFilesDir.mkdirs();

很好,最终的路径是...


/mnt/sdcard/Android/data/com.mycompany.myApp/files

我需要一个要存储在SD卡上的SQLite数据库,因此我按如下方式扩展了SQLiteOpenHelper ...


public class myDbHelper extends SQLiteOpenHelper {


    public myDbHelper(Context context, String name, CursorFactory factory, int version) {

        // NOTE I prefix the full path of my files directory to 'name'

        super(context, myFilesDir + "/" + name, factory, version);

    }


    @Override

    public void onCreate(SQLiteDatabase db) {

        // Create tables and populate with default data...

    }

}

到目前为止一切顺利-我第一次打电话getReadableDatabase()或getWriteableDatabase()在SD卡上创建了一个空DB并将其onCreate()填充。


所以这就是问题所在-该应用程序可能需要5到6个人进行Beta测试,并且像我一样,他们正在运行Android v2.2,并且一切正常。我有一个测试器,但是正在运行v2.1,并且myDbHelper在首次使用时尝试创建数据库时,它因以下原因而崩溃...


E/AndroidRuntime( 3941): Caused by: java.lang.IllegalArgumentException: File /nand/Android/data/com.mycompany.myApp/files/myApp-DB.db3 contains a path separator

E/AndroidRuntime( 3941): at android.app.ApplicationContext.makeFilename(ApplicationContext.java:1445)

E/AndroidRuntime( 3941): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:473)

E/AndroidRuntime( 3941): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)

E/AndroidRuntime( 3941): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)

E/AndroidRuntime( 3941): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)

文件目录的路径是一个奇数(“ / nand”),因为它是内部存储器,尽管不是手机自己的内部存储器-但这是getExternalStorageDirectory()此设备返回的路径。


我可以看到三个可能的答案...


尽管在v2.2上可以接受,但是不建议为数据库名称指定完全限定的路径,并且在早期版本中会失败

SD卡存储可接受完全限定的路径,但是“ / nand”路径被解释为“内部”路径,在这种情况下,仅相对路径可接受

我完全想不到的其他东西

如果上述任何一项或全部适用,那么如果有人可以帮助我解决这个问题,我将不胜感激。


谢谢。


梵蒂冈之花
浏览 677回答 3
3回答

撒科打诨

从历史上看,您无法通过使用路径SQLiteOpenHelper。它仅适用于简单的文件名。我没有意识到他们放宽了Android 2.2中的限制。如果您希望使用SD卡上的数据库,并且希望支持Android 2.1及更低版本,则不能使用SQLiteOpenHelper。

拉莫斯之舞

k3b的答案很棒。它使我工作。但是,在使用API级别11或更高版本的设备上,您可能会看到它停止工作。这是因为添加了新版本的openOrCreateDatabase()方法。现在,它包含以下签名:openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags, DatabaseErrorHandler errorHandler)在某些具有此方法的设备上,这似乎是默认调用的方法。为了使此方法在这些设备上起作用,您需要进行以下更改:首先,编辑您现有的方法,使其仅将调用结果返回给新方法。@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode,        CursorFactory factory) {    return openOrCreateDatabase(name, mode, factory, null);}其次,使用以下代码添加新的替代。@Overridepublic SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler) {    SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(),null,errorHandler);    return result;}该代码与k3b的代码非常相似,但是请注意,SQLiteDatabase.openOrCreateDatabase采用String而不是File,并且我使用了允许DatabaseErrorHandler对象的版本。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Android