net.sqlcipher.database.SQLiteException:错误代码14:无法打开数据库

时间:2019-07-16 18:48:49

标签: android sqlite sqlcipher

我正在尝试使用SQLCipher创建本地SQLite数据库

这是我创建/写入数据库的方法:

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()

    }
}

我已经宣布

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

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

在清单中,并在我这样调用函数时请求权限:

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"))


}

已创建目录,但是当我调用openOrCreateDatabase时仍然出现上述错误。我想念什么?

1 个答案:

答案 0 :(得分:1)

问题1:SQLiteDatabase需要一个文件,但您将其设置为目录:

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

删除这三行,然后删除设备上的目录。或者,不要将databaseFile传递给SQLiteDatabase.openOrCreateDatabase(),而是传递指向目录内文件的File对象。

问题2:您正在尝试写入外部存储,但是您没有持有该权限。 ActivityCompat.requestPermissions()不是阻止呼叫。返回时,您尚未持有权限。但是,在您的代码中,您正在尝试使用尚未持有的权限。

除此之外:

  • 请勿使用字符串连接来组装SQL语句,就像在第二个execSQL()调用中一样。使用?作为占位符,并将您的参数作为第二个参数传递给execSQL()。这对于字符串尤其重要,因为SQLCipher + SQLite会为您正确地转义特殊字符和内容。

  • 您正在主应用程序线程上执行磁盘I / O,这将导致应用程序的UI在发生I / O时冻结。