1

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?

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your comprehensive answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.