gpt4 book ai didi

android - 完全限定的数据库路径名的 SQLiteOpenHelper 问题

转载 作者:IT老高 更新时间:2023-10-28 22:23:46 26 4
gpt4 key购买 nike

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

myFilesDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/Android/data/" + packageName + "/files");
myFilesDir.mkdirs();

这很好,结果路径是......

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

我需要一个 SQLite DB,我想将它存储在 SD 卡上,所以我扩展 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() 填充它。

所以问题来了 - 该应用正在进行 Beta 测试,可能有 5 或 6 人参与,并且和我一样,他们运行的是 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() 为此返回的路径设备。

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

  1. 虽然在 v2.2 上可接受,但不建议为 DB 名称指定完全限定路径,并且在早期版本中会失败
  2. SD 卡存储可接受完全限定路径,但“/nand”路径被解释为“内部”,在这种情况下仅可接受相对路径
  3. 我完全错过的其他东西

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

谢谢。

最佳答案

如果您提供 custom ContextClass 并且您在目标目录中具有写入权限,则可以将 SQLiteOpenHelper 与自定义路径一起使用。

public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 3;
.....

DatabaseHelper(final Context context, String databaseName) {
super(new DatabaseContext(context), databaseName, null, DATABASE_VERSION);
}
}

下面是自定义 DatabaseContext 类,它可以发挥所有作用:

class DatabaseContext extends ContextWrapper {

private static final String DEBUG_CONTEXT = "DatabaseContext";

public DatabaseContext(Context base) {
super(base);
}

@Override
public File getDatabasePath(String name) {
File sdcard = Environment.getExternalStorageDirectory();
String dbfile = sdcard.getAbsolutePath() + File.separator+ "databases" + File.separator + name;
if (!dbfile.endsWith(".db")) {
dbfile += ".db" ;
}

File result = new File(dbfile);

if (!result.getParentFile().exists()) {
result.getParentFile().mkdirs();
}

if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
Log.w(DEBUG_CONTEXT, "getDatabasePath(" + name + ") = " + result.getAbsolutePath());
}

return result;
}

/* this version is called for android devices >= api-11. thank to @damccull for fixing this. */
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
return openOrCreateDatabase(name,mode, factory);
}

/* this version is called for android devices < api-11 */
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
// SQLiteDatabase result = super.openOrCreateDatabase(name, mode, factory);
if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
Log.w(DEBUG_CONTEXT, "openOrCreateDatabase(" + name + ",,) = " + result.getPath());
}
return result;
}
}

2012 年 6 月更新:
这是如何工作的(@barry 问题):

普通的 android 应用程序具有相对于应用程序文件夹的本地数据库文件。通过使用覆盖 getDatabasePath() 的客户上下文,数据库现在相对于 sd 卡上的不同目录。

2015 年 2 月更新:
用新的 android-4.4 设备替换旧的 android-2.2 设备后,我发现我的解决方案不再有效。感谢@damccull-s 的回答,我能够修复它。我已经更新了这个答案,所以这应该是一个工作示例。

2017 年 5 月更新:

统计:此方法用于more than 200 github projects

关于android - 完全限定的数据库路径名的 SQLiteOpenHelper 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5332328/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com