Android SQLiteCantOpenDatabaseExeption由于未知错误
我正在尝试编写一个扩展SQLiteOpenHelper类的android应用程序。不幸的是,由于SQLiteCantOpenDatabaseException,我有一个android测试失败。Android SQLiteCantOpenDatabaseExeption由于未知错误
这里是一个扩展了SQLiteOpenHelper数据库辅助类:
public class ToDoDbHelper extends SQLiteOpenHelper {
// must be incremented upon schema change
private static final int DATABASE_VERSION = 1;
static final String DATABASE_NAME = "todo.db";
private final Context mContext;
public ToDoDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
File dbFile = mContext.getDatabasePath(DATABASE_NAME);
// database already exists
if(dbFile.exists()) {
return;
}
// Create a table to hold our labels
final String SQL_CREATE_LABEL_TABLE = "CREATE TABLE" + TaskLabel.TABLE_NAME + " (" +
TaskLabel._ID + " INTEGER PRIMARY KEY," +
TaskLabel.COLUMN_LABEL + " TEXT NOT NULL " +
");";
// Create a table to hold our priorities
final String SQL_CREATE_PRIORITY_TABLE = "CREATE TABLE" + TaskPriority.TABLE_NAME + " (" +
TaskPriority._ID + " INTEGER PRIMARY KEY," +
TaskPriority.COLUMN_PRIORITY + " TEXT NOT NULL " +
");";
final String SQL_INSERT_PRIORITY_TABLE = "INSERT INTO " + TaskLabel.TABLE_NAME +
" VALUES (" + Resources.getSystem().getString(R.string.priority_none) + ")," +
" (" + Resources.getSystem().getString(R.string.priority_low) + ")," +
" (" + Resources.getSystem().getString(R.string.priority_med) + ")," +
" (" + Resources.getSystem().getString(R.string.priority_high) +
");";
// Create a table to hold our tasks
final String SQL_CREATE_TASK_TABLE = "CREATE TABLE " + TaskEntry.TABLE_NAME + " (" +
TaskEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
TaskEntry.COLUMN_CREATE_DATE + " INTEGER NOT NULL," +
TaskEntry.COLUMN_DUE_DATE + " INTEGER," +
TaskEntry.COLUMN_TITLE + " TEXT NOT NULL," +
TaskEntry.COLUMN_DETAIL + " TEXT," +
TaskEntry.COLUMN_IS_COMPLETED + " INTEGER NOT NULL," +
TaskEntry.COLUMN_IS_DELETED + " INTEGER NOT NULL," +
TaskEntry.COLUMN_REMINDER_ADDED + " INTEGER NOT NULL," +
TaskEntry.COLUMN_LABEL_ID + " INTEGER NOT NULL," +
TaskEntry.COLUMN_PRIORITY_ID + " INTEGER NOT NULL," +
TaskEntry.COLUMN_PARENT_TASK_ID + " INTEGER," +
// Set up the priority column as a foreign key to the priority table
" FOREIGN KEY (" + TaskEntry.COLUMN_PRIORITY_ID + ") REFERENCES " +
TaskPriority.TABLE_NAME + "(" + TaskPriority._ID + "), " +
// Set up label column as a foreign key to the label table
" FOREIGN KEY (" + TaskEntry.COLUMN_LABEL_ID + ") REFERENCES " +
TaskLabel.TABLE_NAME + "(" + TaskLabel._ID + "));";
sqLiteDatabase.execSQL(SQL_CREATE_LABEL_TABLE);
sqLiteDatabase.execSQL(SQL_CREATE_PRIORITY_TABLE);
sqLiteDatabase.execSQL(SQL_INSERT_PRIORITY_TABLE);
sqLiteDatabase.execSQL(SQL_CREATE_TASK_TABLE);
}
// this function to be implemented if DATABASE_VERSION is incremented (i.e. if schema changes)
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
下面是调用类的测试:
@Test
public void testCreateDb() throws Throwable {
mContext.deleteDatabase(ToDoDbHelper.DATABASE_NAME);
SQLiteDatabase db = new ToDoDbHelper(
mContext).getWritableDatabase();
// make sure the database is open
assertEquals(true, db.isOpen());
在这条线发生异常:
SQLiteDatabase db = new ToDoDbHelper(
mContext).getWritableDatabase();
这里是堆栈跟踪:
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error
(code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:571)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at com.todo.group1.todo.data.TestDb.testCreateDb(TestDb.java:47)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1879)
我曾尝试:
- 清除应用数据
- 卸载
- 模拟器上进行的,而不是我的设备
- 重命名数据库文件
- 添加READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限运行测试到Android Manifest。
但无论我做什么,抛出异常并且永远不会创建数据库(onCreate()永远不会被调用)。我该怎么办?任何帮助表示赞赏。
决定把我的评论作为一个答案在这里,因为它解决了这个问题,甚至能够帮助别人的未来:
在Android 6+(M)上,您应该在运行时请求权限以访问数据库。 Android开发者指南:https://developer.android.com/training/permissions/requesting.html
我发现你在两次SQL创建查询中缺少白色空白。
例:
final String SQL_CREATE_LABEL_TABLE = "CREATE TABLE" // you missing a blank after TABLE
请再次仔细检查所有的语句:)
虽然这只会在CRUD操作中出现问题。它不应该阻止数据库文件被打开 –
谢谢,这是测试在启动时显示的问题之一。 – jwb1092
如果您使用的是Android 6+(M),那么您可能应该尝试在运行时请求权限。 –
您确定要使用Junit来做到这一点吗?通常你只是模拟一个数据库。 –
@DmytroKarataiev就是这样。我在运行时请求中使用了android开发人员文档来修复它。谢谢! – jwb1092