diff --git a/README.md b/README.md
index 8adadd3..e3870ec 100644
--- a/README.md
+++ b/README.md
@@ -16,14 +16,14 @@ We welcome contributions, to contribute to SQLCipher for Android, a [contributor
Add a local reference to the local library and dependency:
```groovy
-implementation files('libs/sqlcipher-android-4.14.0-release.aar')
+implementation files('libs/sqlcipher-android-4.15.0-release.aar')
implementation 'androidx.sqlite:sqlite:2.6.2'
```
or source a Community edition build from Maven Central:
```groovy
-implementation 'net.zetetic:sqlcipher-android:4.14.0@aar'
+implementation 'net.zetetic:sqlcipher-android:4.15.0@aar'
implementation 'androidx.sqlite:sqlite:2.6.2'
```
diff --git a/build.gradle b/build.gradle
index a2dae67..1a94a03 100644
--- a/build.gradle
+++ b/build.gradle
@@ -33,7 +33,7 @@ project.ext {
if(project.hasProperty('sqlcipherAndroidVersion') && "${sqlcipherAndroidVersion}") {
libraryVersion = "${sqlcipherAndroidVersion}"
} else {
- libraryVersion = "4.14.1"
+ libraryVersion = "4.15.0"
}
minSdkVersion = 23
androidXSQLiteVersion = "2.6.2"
diff --git a/sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteDatabase.java b/sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteDatabase.java
index 1a26f71..2fba349 100644
--- a/sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteDatabase.java
+++ b/sqlcipher/src/main/java/net/zetetic/database/sqlcipher/SQLiteDatabase.java
@@ -401,6 +401,10 @@ private static boolean isMainThread() {
return looper != null && looper == Looper.getMainLooper();
}
+ public void beginTransactionReadOnly() {
+ beginTransaction();
+ }
+
/**
* Begins a transaction in EXCLUSIVE mode.
*
diff --git a/sqlcipher/src/main/jni/sqlcipher/android_database_CursorWindow.cpp b/sqlcipher/src/main/jni/sqlcipher/android_database_CursorWindow.cpp
index a835f6d..8ddce4e 100644
--- a/sqlcipher/src/main/jni/sqlcipher/android_database_CursorWindow.cpp
+++ b/sqlcipher/src/main/jni/sqlcipher/android_database_CursorWindow.cpp
@@ -275,9 +275,9 @@ namespace android {
jbyteArray valueObj, jint row, jint column) {
auto* window = reinterpret_cast(windowPtr);
jsize len = env->GetArrayLength(valueObj);
- void* value = env->GetPrimitiveArrayCritical(valueObj, NULL);
+ jbyte* value = static_cast(env->GetByteArrayElements(valueObj, NULL));
status_t status = window->putBlob(row, column, value, len);
- env->ReleasePrimitiveArrayCritical(valueObj, value, JNI_ABORT);
+ env->ReleaseByteArrayElements(valueObj, value, JNI_ABORT);
if (status) {
ALOGD("Failed to put blob. error=%d", status);
return false;
diff --git a/sqlcipher/src/main/jni/sqlcipher/android_database_SQLiteConnection.cpp b/sqlcipher/src/main/jni/sqlcipher/android_database_SQLiteConnection.cpp
index f0eab3c..dcb6a7a 100644
--- a/sqlcipher/src/main/jni/sqlcipher/android_database_SQLiteConnection.cpp
+++ b/sqlcipher/src/main/jni/sqlcipher/android_database_SQLiteConnection.cpp
@@ -354,11 +354,11 @@ static jlong nativePrepareStatement(JNIEnv* env, jclass clazz, jlong connectionP
auto* connection = reinterpret_cast(connectionPtr);
jsize sqlLength = env->GetStringLength(sqlString);
- const jchar* sql = env->GetStringCritical(sqlString, NULL);
+ const jchar* sql = env->GetStringChars(sqlString, NULL);
sqlite3_stmt* statement;
int err = sqlite3_prepare16_v2(connection->db,
sql, sqlLength * sizeof(jchar), &statement, NULL);
- env->ReleaseStringCritical(sqlString, sql);
+ env->ReleaseStringChars(sqlString, sql);
if (err != SQLITE_OK) {
// Error messages like 'near ")": syntax error' are not
@@ -459,10 +459,10 @@ static void nativeBindString(JNIEnv* env, jclass clazz, jlong connectionPtr,
auto* connection = reinterpret_cast(connectionPtr);
auto* statement = reinterpret_cast(statementPtr);
jsize valueLength = env->GetStringLength(valueString);
- const jchar* value = env->GetStringCritical(valueString, NULL);
+ const jchar* value = env->GetStringChars(valueString, NULL);
int err = sqlite3_bind_text16(statement, index, value, valueLength * sizeof(jchar),
SQLITE_TRANSIENT);
- env->ReleaseStringCritical(valueString, value);
+ env->ReleaseStringChars(valueString, value);
if (err != SQLITE_OK) {
throw_sqlite3_exception(env, connection->db, NULL);
}
@@ -473,9 +473,9 @@ static void nativeBindBlob(JNIEnv* env, jclass clazz, jlong connectionPtr,
auto* connection = reinterpret_cast(connectionPtr);
auto* statement = reinterpret_cast(statementPtr);
jsize valueLength = env->GetArrayLength(valueArray);
- auto* value = static_cast(env->GetPrimitiveArrayCritical(valueArray, NULL));
+ jbyte* value = static_cast(env->GetByteArrayElements(valueArray, NULL));
int err = sqlite3_bind_blob(statement, index, value, valueLength, SQLITE_TRANSIENT);
- env->ReleasePrimitiveArrayCritical(valueArray, value, JNI_ABORT);
+ env->ReleaseByteArrayElements(valueArray, value, JNI_ABORT);
if (err != SQLITE_OK) {
throw_sqlite3_exception(env, connection->db, NULL);
}
diff --git a/sqlcipher/src/main/jni/sqlcipher/src b/sqlcipher/src/main/jni/sqlcipher/src
index 778ab89..0b4d160 160000
--- a/sqlcipher/src/main/jni/sqlcipher/src
+++ b/sqlcipher/src/main/jni/sqlcipher/src
@@ -1 +1 @@
-Subproject commit 778ab890cfc30c3631212dcceb0295498abdcd3e
+Subproject commit 0b4d16090a71579c4c88220b7fb67bb7396f1434