简体   繁体   中英

net.sqlcipher.database.SQLiteException: error code 14: Could not open database

I am attempting to create a local SQLite database with SQLCipher

Here is my method for creating/writing to the database:

class DatabaseUtils {

val storagePath = Environment.getExternalStorageDirectory()


fun storeTransaction(context: Context, password: String, transaction: Transaction) {
    SQLiteDatabase.loadLibs(context)


    val databaseFile: File = context.getDatabasePath("$storagePath/Test.db")

    if (!databaseFile.exists()) {
        databaseFile.mkdirs()
    }



        val database: SQLiteDatabase = SQLiteDatabase.openOrCreateDatabase(databaseFile, password, null)

        database.execSQL("CREATE TABLE IF NOT EXISTS Transactions(cardNumber INTEGER)")

        database.execSQL("INSERT INTO Transactions(cardNumber) VALUES(${transaction.cardNumber})")

        database.close()

    }
}

I have declared

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

in my manifest, and requested permission when I called the function like so:

override fun onStart() {
    super.onStart()

    initUI()



    if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(activity!!,
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
            1)

    }
    if (ContextCompat.checkSelfPermission(context!!, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(activity!!,
            arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
            2)

    }

    val databaseUtils = DatabaseUtils()

    databaseUtils.storeTransaction(context!!,getString(R.string.app_version), Transaction("12345678"))


}

The directory gets created, but I am still getting the above error when I call openOrCreateDatabase. What am I missing?

Problem #1: SQLiteDatabase needs a file, but you made it a directory:

if (!databaseFile.exists()) {
    databaseFile.mkdirs()
}

Delete those three lines, and delete the directory on your device. Or, do not pass databaseFile to SQLiteDatabase.openOrCreateDatabase() , but instead pass a File object pointing to a file inside of your directory.

Problem #2: You are trying to write to external storage, yet you do not hold the permissions. ActivityCompat.requestPermissions() is not a blocking call. When it returns, you do not yet hold the permissions . Yet, in your code, you are rolling right along attempting to use the permissions that you do not yet hold.

Beyond that:

  • Do not use string concatenation to assemble SQL statements, as you are in the second execSQL() call. Use ? as a placeholder and pass your arguments as the second parameter to execSQL() . This is especially important for strings, as SQLCipher+SQLite will properly escape special characters and stuff for you.

  • You are doing disk I/O on the main application thread, which will cause your app's UI to freeze while that I/O is occurring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM