【问题标题】:net.sqlcipher.database.SQLiteException: error code 14: Could not open databasenet.sqlcipher.database.SQLiteException:错误代码 14:无法打开数据库
【发布时间】:2019-07-16 18:48:49
【问题描述】:

我正在尝试使用 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"/>

&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;

在我的清单中,并在我这样调用函数时请求许可:

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 时仍然出现上述错误。我错过了什么?

【问题讨论】:

    标签: android sqlite sqlcipher


    【解决方案1】:

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

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

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

    问题 #2:您正在尝试写入外部存储,但您没有权限。 ActivityCompat.requestPermissions() 不是阻塞调用。当它返回时,您还没有拥有权限。然而,在您的代码中,您正在尝试使用您尚未拥有的权限。

    除此之外:

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

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

    【讨论】:

    • 非常感谢您的全面回答。
    猜你喜欢
    • 2020-03-10
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    相关资源
    最近更新 更多