Android SQLiteCantOpenDatabaseExeption由于未知错误

时间:2016-07-30 20:32:06

标签: android android-studio android-sqlite

我正在尝试编写一个扩展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)

我试过了:

  1. 清算申请数据
  2. 卸载
  3. 在模拟器而不是我的设备上运行测试
  4. 重命名数据库文件
  5. 向Android Manifest添加READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。
  6. 但无论我做什么,抛出异常并且永远不会创建数据库(永远不会调用onCreate())。我该怎么办?任何帮助表示赞赏。

2 个答案:

答案 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