我正在尝试编写一个扩展SQLiteOpenHelper类的Android应用程序。不幸的是,由于SQLiteCantOpenDatabaseException,我有一个android测试失败。
这是扩展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)
我试过了:
但无论我做什么,抛出异常并且永远不会创建数据库(永远不会调用onCreate())。我该怎么办?任何帮助表示赞赏。
答案 0 :(得分:0)
我发现在两个SQL创建查询中缺少一个白色空白。
前:
final String SQL_CREATE_LABEL_TABLE = "CREATE TABLE" // you missing a blank after TABLE
请再次仔细检查所有声明:)
答案 1 :(得分:0)
决定将我的评论作为答案在这里,因为它解决了问题,并可能在将来帮助其他人:
在Android 6+(M)上,您应该在运行时请求权限以访问数据库。 Android开发者指南:https://developer.android.com/training/permissions/requesting.html