diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 634799ada..8bdef4f27 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -3,7 +3,7 @@ name: Bug report
about: Create a report to help us improve
title: "BUG :
"
labels: bug, open source
-assignees: itsdebs
+assignees: "@rudderlabs/sdk-android"
---
**Describe the bug**
diff --git a/.github/workflows/draft_new_release-v2.yml b/.github/workflows/draft_new_release-v2.yml
index f78e671e6..60b8fbea7 100644
--- a/.github/workflows/draft_new_release-v2.yml
+++ b/.github/workflows/draft_new_release-v2.yml
@@ -90,4 +90,4 @@ jobs:
github_token: ${{ secrets.PAT }}
pr_title: 'chore(release): pulling ${{ steps.create-release.outputs.branch_name }} into master-v2'
pr_body: ':crown: *An automated PR*'
- pr_reviewer: 'itsdebs'
\ No newline at end of file
+ pr_reviewer: '@rudderlabs/sdk-android'
\ No newline at end of file
diff --git a/.github/workflows/draft_new_release.yml b/.github/workflows/draft_new_release.yml
index 9c3f93f75..5c5abd3e5 100644
--- a/.github/workflows/draft_new_release.yml
+++ b/.github/workflows/draft_new_release.yml
@@ -82,4 +82,4 @@ jobs:
github_token: ${{ secrets.PAT }}
pr_title: "chore(release): pulling ${{ steps.create-release.outputs.branch_name }} into ${{ steps.create-release.outputs.main_branch }}"
pr_body: ":crown: *An automated PR*"
- pr_reviewer: 'itsdebs'
+ pr_reviewer: '@rudderlabs/sdk-android'
diff --git a/.github/workflows/publish-new-github-release-v2.yml b/.github/workflows/publish-new-github-release-v2.yml
index 03672322c..22004a710 100644
--- a/.github/workflows/publish-new-github-release-v2.yml
+++ b/.github/workflows/publish-new-github-release-v2.yml
@@ -87,7 +87,7 @@ jobs:
github_token: ${{ secrets.PAT }}
pr_title: 'chore(release): pulling master-v2 into develop-v2 post release v${{ steps.extract-version.outputs.release_version }}'
pr_body: ':crown: *An automated PR*'
- pr_reviewer: 'itsdebs'
+ pr_reviewer: '@rudderlabs/sdk-android'
- name: Delete hotfix release branch v2
uses: koj-co/delete-merged-action@master
diff --git a/.github/workflows/publish-new-github-release.yml b/.github/workflows/publish-new-github-release.yml
index 5472ed312..cdfa83853 100644
--- a/.github/workflows/publish-new-github-release.yml
+++ b/.github/workflows/publish-new-github-release.yml
@@ -49,7 +49,7 @@ jobs:
github_token: ${{ secrets.PAT }}
pr_title: "chore(release): pulling main into develop post release v${{ steps.extract-version.outputs.release_version }}"
pr_body: ':crown: *An automated PR*'
- pr_reviewer: 'itsdebs'
+ pr_reviewer: '@rudderlabs/sdk-android'
- name: Create pull request into develop-mpx
uses: repo-sync/pull-request@v2
if: (startsWith(github.event.pull_request.head.ref, 'release-mpx/') || startsWith(github.event.pull_request.head.ref, 'hotfix-release-mpx/'))
@@ -59,7 +59,7 @@ jobs:
github_token: ${{ secrets.PAT }}
pr_title: "chore(release): pulling main into develop post release v${{ steps.extract-version.outputs.release_version }}"
pr_body: ':crown: *An automated PR*'
- pr_reviewer: 'itsdebs'
+ pr_reviewer: '@rudderlabs/sdk-android'
- name: Delete hotfix release branch
uses: koj-co/delete-merged-action@master
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3dfe51f4e..da123d073 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+### [1.23.2](https://github.com/rudderlabs/rudder-sdk-android/compare/v1.23.1...v1.23.2) (2024-06-25)
+
+
+### Bug Fixes
+
+* database crash issue ([#449](https://github.com/rudderlabs/rudder-sdk-android/issues/449)) ([9251b68](https://github.com/rudderlabs/rudder-sdk-android/commit/9251b6882162d61f6300f16d543bec9864a397cc))
+
### [1.23.1](https://github.com/rudderlabs/rudder-sdk-android/compare/v1.23.0...v1.23.1) (2024-05-28)
diff --git a/CODEOWNERS b/CODEOWNERS
index 394c12b4e..ce19134bc 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1 +1 @@
-* @pallabmaiti @itsdebs @bardisg @ChryssaAliferi
+* @rudderlabs/sdk-android
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6c3fefcab..3908fa013 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -40,5 +40,5 @@ For any questions, concerns, or queries, you can start by asking a question on o
[issue]: https://github.com/rudderlabs/rudder-sdk-android/issues/new
-[CLA]: https://rudderlabs.wufoo.com/forms/rudderlabs-contributor-license-agreement
+[CLA]: https://forms.gle/845JRGVZaC6kPZy68
[Slack]: https://rudderstack.com/join-rudderstack-slack-community/
diff --git a/README.md b/README.md
index a6eb2dd5b..0729ce4bc 100644
--- a/README.md
+++ b/README.md
@@ -117,60 +117,6 @@ The variable `it` contains the intialized nativeSDK object.
[**Registering Lotame's onSync callback**](https://github.com/rudderlabs/rudder-integration-lotame-android#register-your-onsync-callback) shows one more example of registering a callback using `onIntegrationReady`.
-#### Do I need to add anything to my ProGuard rules?
-
-If you are using Proguard full mode to optimize your app, add the following lines to your Android ProGuard rules:
-
-```java
-# Reporter Module
--keep class com.rudderstack.android.ruddermetricsreporterandroid.models.LabelEntity { *; }
--keep class com.rudderstack.android.ruddermetricsreporterandroid.models.MetricEntity { *; }
--keep class com.rudderstack.android.ruddermetricsreporterandroid.models.ErrorEntity { *; }
-
-# Required for the usage off TypeToken class in Utils.converToMap, Utils.convertToList
--keep class com.google.gson.reflect.TypeToken { *; }
--keep class * extends com.google.gson.reflect.TypeToken
-
-# Required for the serialization of SourceConfig once it is downloaded.
--keep class com.google.gson.internal.LinkedTreeMap { *; }
--keep class * implements java.io.Serializable { *; }
--keep class com.rudderstack.rudderjsonadapter.RudderTypeAdapter { *; }
--keep class * extends com.rudderstack.rudderjsonadapter.RudderTypeAdapter
-
-# Required to ensure the DefaultPersistenceProviderFactory is not removed by Proguard
-# and works as expected even when the customer is not using encryption feature.
--dontwarn net.sqlcipher.Cursor
--dontwarn net.sqlcipher.database.SQLiteDatabase$CursorFactory
--dontwarn net.sqlcipher.database.SQLiteDatabase
--dontwarn net.sqlcipher.database.SQLiteOpenHelper
--keep class com.rudderstack.android.sdk.core.persistence.DefaultPersistenceProviderFactory { *; }
-
-# Required for the usage of annotations across reporter and web modules
--dontwarn com.fasterxml.jackson.annotation.JsonIgnore
--dontwarn com.squareup.moshi.Json
--dontwarn com.fasterxml.jackson.annotation.JsonProperty
-
-# Required for Device Mode Transformations
--keep class com.rudderstack.android.sdk.core.TransformationResponse { *; }
--keep class com.rudderstack.android.sdk.core.TransformationResponseDeserializer { *; }
-
-# to make sure that serialized name annotations are not removed by the Proguard full mode.
--keepclassmembers,allowobfuscation class * {
- @com.google.gson.annotations.SerializedName ;
-}
-
-# Required for proper serialization of the custom traits and custom context
--keep class * implements com.google.gson.JsonSerializer { *; }
-
-# to make sure that the customContextMap, custom traits are sent in the proper format
--keepclassmembers class com.rudderstack.android.sdk.core.RudderContext { java.util.Map customContextMap; }
--keepclassmembers class com.rudderstack.android.sdk.core.RudderTraits { java.util.Map extras; }
-
-# Required for DBEncryption feature using SQLCipher
--keep class net.sqlcipher.** { *; }
--keep class net.sqlcipher.database.* { *; }
-```
-
## Contribute
We would love to see you contribute to this project. Get more information on how to contribute [**here**](./CONTRIBUTING.md).
diff --git a/core/src/main/java/com/rudderstack/android/sdk/core/DBPersistentManager.java b/core/src/main/java/com/rudderstack/android/sdk/core/DBPersistentManager.java
index 751b88c3f..98982e6d2 100644
--- a/core/src/main/java/com/rudderstack/android/sdk/core/DBPersistentManager.java
+++ b/core/src/main/java/com/rudderstack/android/sdk/core/DBPersistentManager.java
@@ -16,7 +16,6 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.rudderstack.android.ruddermetricsreporterandroid.RudderReporter;
import com.rudderstack.android.sdk.core.persistence.DefaultPersistenceProviderFactory;
import com.rudderstack.android.sdk.core.persistence.Persistence;
import com.rudderstack.android.sdk.core.persistence.PersistenceProvider;
@@ -26,11 +25,9 @@
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
@@ -43,7 +40,6 @@
class DBPersistentManager/* extends SQLiteOpenHelper*/ {
public static final String DBPERSISTENT_MANAGER_CHECK_FOR_MIGRATIONS_TAG = "DBPersistentManager: checkForMigrations: ";
- public static final Object QUEUE_LOCK = new Object();
public static final ExecutorService executor = Executors.newSingleThreadExecutor();
static final String EVENT = "EVENT";
@@ -100,8 +96,7 @@ class DBPersistentManager/* extends SQLiteOpenHelper*/ {
//synchronizing database access
private static final Object DB_LOCK = new Object();
private static DBPersistentManager instance;
- final Queue queue = new LinkedList<>();
- DBInsertionHandlerThread dbInsertionHandlerThread;
+ private DBInsertionHandlerThread dbInsertionHandlerThread;
private Persistence persistence;
private DBPersistentManager(Application application,
@@ -190,18 +185,18 @@ private void createSchema(String eventSchemaSQL) {
/*
- * Receives message from Repository, and passes it to the Handler thread if it exists, else adds it to a queue for replay
- * once Handler thread is initialized.
+ * Receives message from Repository, and passes it to the Handler thread if it exists else creates a new Handler thread.
+ * This method should be called in a synchronized way.
* */
void saveEvent(String messageJson, EventInsertionCallback callback) {
Message msg = createOsMessageFromJson(messageJson, callback);
- synchronized (DBPersistentManager.QUEUE_LOCK) {
- if (dbInsertionHandlerThread == null) {
- queue.add(msg);
- return;
- }
- addMessageToHandlerThread(msg);
+ if (dbInsertionHandlerThread == null) {
+ // Need to perform db operations on a separate thread to support strict mode.
+ // saveEvent method is already called on an executor thread, so we can directly call DBInsertionHandlerThread
+ dbInsertionHandlerThread = new DBInsertionHandlerThread("db_insertion_thread", persistence);
+ dbInsertionHandlerThread.start();
}
+ dbInsertionHandlerThread.addMessage(msg);
}
private Message createOsMessageFromJson(String messageJson, EventInsertionCallback callback) {
@@ -213,13 +208,6 @@ private Message createOsMessageFromJson(String messageJson, EventInsertionCallba
return msg;
}
- /*
- Passes the input message to the Handler thread.
- */
- void addMessageToHandlerThread(Message msg) {
- dbInsertionHandlerThread.addMessage(msg);
- }
-
@VisibleForTesting
void saveEventSync(String messageJson) {
ContentValues insertValues = new ContentValues();
@@ -456,32 +444,6 @@ private int getCountForCommand(String sql) {
return count;
}
- /*
- Starts the Handler thread, which is responsible for storing the messages in its internal queue, and
- save them to the sqlite db sequentially.
- */
- void startHandlerThread() {
- Runnable runnable = () -> {
- try {
- synchronized (DBPersistentManager.QUEUE_LOCK) {
- dbInsertionHandlerThread = new DBInsertionHandlerThread("db_insertion_thread", persistence);
- dbInsertionHandlerThread.start();
- for (Message msg : queue) {
- addMessageToHandlerThread(msg);
- }
- }
- } catch (SQLiteDatabaseCorruptException | ConcurrentModificationException |
- NullPointerException ex) {
- RudderLogger.logError(ex);
- ReportManager.reportError(ex);
-
- }
- };
- // Need to perform db operations on a separate thread to support strict mode.
- executor.execute(runnable);
- }
-
-
private boolean checkIfColumnExists(String newColumn) {
String checkIfStatusExistsSqlString = "PRAGMA table_info(events)";
if (!persistence.isAccessible()) {
diff --git a/core/src/main/java/com/rudderstack/android/sdk/core/EventRepository.java b/core/src/main/java/com/rudderstack/android/sdk/core/EventRepository.java
index 92a20fbd6..a3a4102f8 100644
--- a/core/src/main/java/com/rudderstack/android/sdk/core/EventRepository.java
+++ b/core/src/main/java/com/rudderstack/android/sdk/core/EventRepository.java
@@ -214,7 +214,6 @@ private void initializeDbManager(Application application) {
dbEncryption.getPersistenceProviderFactoryClassName(), dbEncryption.key);
this.dbManager = DBPersistentManager.getInstance(application, dbManagerParams);
dbManager.checkForMigrations();
- dbManager.startHandlerThread();
}
private void initiatePreferenceManager(Application application) {
diff --git a/core/src/test/java/com/rudderstack/android/sdk/core/DBPersistentManagerTest.java b/core/src/test/java/com/rudderstack/android/sdk/core/DBPersistentManagerTest.java
index ce9835f0f..f16fea439 100644
--- a/core/src/test/java/com/rudderstack/android/sdk/core/DBPersistentManagerTest.java
+++ b/core/src/test/java/com/rudderstack/android/sdk/core/DBPersistentManagerTest.java
@@ -6,46 +6,29 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
-import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
-import org.powermock.reflect.Whitebox;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
import android.os.Build;
-import android.os.Message;
-import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.hasEntry;
-import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasProperty;
-import static java.lang.Thread.sleep;
import android.app.Application;
import androidx.test.core.app.ApplicationProvider;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
import com.google.common.collect.ImmutableList;
import com.rudderstack.android.sdk.core.gson.RudderGson;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicInteger;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = Build.VERSION_CODES.O_MR1)
@@ -84,8 +67,6 @@ public void setUp() throws Exception {
dbPersistentManager = PowerMockito.mock(DBPersistentManager.class);
PowerMockito.when(dbPersistentManager, "saveEventSync", anyString()).thenCallRealMethod();
PowerMockito.when(dbPersistentManager, "saveEvent", anyString(), any()).thenCallRealMethod();
- PowerMockito.when(dbPersistentManager, "startHandlerThread").thenCallRealMethod();
- Whitebox.setInternalState(dbPersistentManager, "queue", new LinkedList());
deviceModeManager = Mockito.mock(RudderDeviceModeManager.class);
}
@@ -98,57 +79,6 @@ public void tearDown() {
private int addMessageCalled = 0;
- @Test
- public void testSynchronicity() throws Exception {
- final AtomicInteger messagesSaved = new AtomicInteger(0);
- // Mocking the addMessageToQueue, which is used by both the save-event-thread and Handler thread, to verify synchronization
- PowerMockito.when(dbPersistentManager, "addMessageToHandlerThread", any(Message.class))
- .thenAnswer((Answer) invocation -> {
- ++addMessageCalled;
- System.out.println("addMessageToQueue called by: " + Thread.currentThread().getName());
- //assert if called by multiple thread
- assertThat(addMessageCalled, Matchers.lessThan(2));
- sleep(500);
- --addMessageCalled;
- assertThat(addMessageCalled, Matchers.lessThan(1));
- System.out.println("return from addMessageToQueue by: " + Thread.currentThread().getName());
- messagesSaved.incrementAndGet();
- return null;
- }
- );
-
- // Triggering the saveEvent method of DBPersistentManager from save-event-thread, as this method adds messages to the queue.
- new Thread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < messages.size(); i++) {
- dbPersistentManager.saveEvent(messages.get(i),
- new EventInsertionCallback(new RudderMessageBuilder().build(),
- deviceModeManager));
- // Starting the Handler thread, only when some events are added to the queue, so that the replay happens, and handler
- // thread starts reading from the queue.
- if (i == messages.size() / 2) {
- dbPersistentManager.startHandlerThread();
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }, "save-event-thread") {
- }.start();
-
-
- //await until finished
- await().atMost(15, SECONDS).until(new Callable() {
- @Override
- public Boolean call() throws Exception {
- return messagesSaved.get() == messages.size();
- }
- });
- }
@Test
public void doneEventsTest() {
final DBPersistentManager dbPersistentManager = DBPersistentManager.getInstance(ApplicationProvider
@@ -216,4 +146,4 @@ private List parse(List messageJsons) {
}
return messages;
}
-}
\ No newline at end of file
+}
diff --git a/gradle.properties b/gradle.properties
index cf47e1be7..a6b4feadf 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -5,8 +5,8 @@ android.enableJetifier=true
android.enableR8.fullMode=true
kotlin.code.style=official
GROUP=com.rudderstack.android.sdk
-VERSION_CODE=28
-VERSION_NAME=1.23.1
+VERSION_CODE=29
+VERSION_NAME=1.23.2
POM_NAME=Rudderstack SDK for android
POM_DESCRIPTION=Rudderstack SDK for android
POM_ARTIFACT_ID=core
diff --git a/package.json b/package.json
index 6f69d4581..2dc854832 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "version": "1.23.1",
+ "version": "1.23.2",
"dependencies": {
"properties-reader": "^2.2.0"
}
diff --git a/settings.gradle b/settings.gradle
index 841f5ce3a..c2619a6a1 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,19 +1 @@
include ':sample-cdn', ':sample-kotlin', ':core', ':sample-segment-java', ':sample-kotlin-integration', ':dummy-impl', ':android-tv'
-//include(':web')
-//project(':web').projectDir = new File(rootDir, "../RudderAndroidLibs/web")
-////
-//include(':rudderjsonadapter')
-//project(':rudderjsonadapter').projectDir = new File(rootDir, "../RudderAndroidLibs/rudderjsonadapter")
-//include(':gsonrudderadapter')
-//project(':gsonrudderadapter').projectDir = new File(rootDir, "../RudderAndroidLibs/gsonrudderadapter")
-//include(':moshirudderadapter')
-//project(':moshirudderadapter').projectDir = new File(rootDir, "../RudderAndroidLibs/moshirudderadapter")
-//include(':jacksonrudderadapter')
-//project(':jacksonrudderadapter').projectDir = new File(rootDir, "../RudderAndroidLibs/jacksonrudderadapter")
-////
-//include(':repository')
-//project(':repository').projectDir = new File(rootDir, "../RudderAndroidLibs/repository")
-////
-//include(':rudderreporter')
-//project(':rudderreporter').projectDir = new File(rootDir, "../RudderAndroidLibs/rudderreporter")
-