Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cross-platform-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:

- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 29
force-avd-creation: false
Expand All @@ -53,7 +53,7 @@ jobs:
distribution: "zulu"
java-version: "17"
- name: "Run Crossplatform Tests"
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 29
force-avd-creation: false
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Checkout
uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 #v5.0.0
- name: Trunk Check
uses: trunk-io/trunk-action@75699af9e26881e564e9d832ef7dc3af25ec031b # v1.2.4
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # v1.3.1
with:
check-mode: pull_request
pr-check-hadcoded-secrets:
Expand Down Expand Up @@ -58,7 +58,7 @@ jobs:
key: avd-29
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 28
force-avd-creation: false
Expand All @@ -71,7 +71,7 @@ jobs:
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: "Run Instrumented Tests"
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 28
force-avd-creation: false
Expand Down Expand Up @@ -120,7 +120,7 @@ jobs:

- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 28
force-avd-creation: false
Expand All @@ -133,7 +133,7 @@ jobs:
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: "Run Instrumented Orchestrator Tests"
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b #v2.35.0
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a #v2.37.0
with:
api-level: 28
force-avd-creation: false
Expand Down
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
## [5.79.0](https://github.com/mParticle/mparticle-android-sdk/compare/v5.78.5...v5.79.0) (2026-05-14)


### Features

* add customBaseURL CNAME support to NetworkOptions ([#701](https://github.com/mParticle/mparticle-android-sdk/issues/701)) ([5285149](https://github.com/mParticle/mparticle-android-sdk/commit/5285149118b58cbd5cf4fb90cb58627deb7538b9)), closes [mparticle-apple-sdk#760](https://github.com/mParticle/mparticle-apple-sdk/issues/760)
* Add max persistence age override option [TRIAGE-608] ([#699](https://github.com/mParticle/mparticle-android-sdk/issues/699)) ([ca88322](https://github.com/mParticle/mparticle-android-sdk/commit/ca88322ac7ef8649ed111cf28afb81d99cdb271a))


### Bug Fixes

* increase MPLatch timeout from 5s to 30s ([#695](https://github.com/mParticle/mparticle-android-sdk/issues/695)) ([20f723f](https://github.com/mParticle/mparticle-android-sdk/commit/20f723f27cf296c879ceebc9d234edca039ab371))


### Updates & Maintenance

* Update submodules ([59a4a9a](https://github.com/mParticle/mparticle-android-sdk/commit/59a4a9a68e3addfaf5c4eea1afd396889721819d))

## [5.78.5](https://github.com/mParticle/mparticle-android-sdk/compare/v5.78.4...v5.78.5) (2026-03-25)


### Updates & Maintenance

* Update submodules ([86d8d97](https://github.com/mParticle/mparticle-android-sdk/commit/86d8d9748a0c7a796dd0b0be6722f92acef301ea))

## [5.78.4](https://github.com/mParticle/mparticle-android-sdk/compare/v5.78.3...v5.78.4) (2026-03-23)


### Updates & Maintenance

* Update submodules ([08dab75](https://github.com/mParticle/mparticle-android-sdk/commit/08dab75e3715733f6f5655fbf39fbce16a2e01a2))

## [5.78.3](https://github.com/mParticle/mparticle-android-sdk/compare/v5.78.2...v5.78.3) (2026-03-11)


### Updates & Maintenance

* bump actions/upload-artifact from 6 to 7 ([#649](https://github.com/mParticle/mparticle-android-sdk/issues/649)) ([0a188b1](https://github.com/mParticle/mparticle-android-sdk/commit/0a188b1f88efde471f8d6bff2aa8611b1b4bf956))
* Update submodules ([cbb17d7](https://github.com/mParticle/mparticle-android-sdk/commit/cbb17d7e359d41d8d7577a9516cf7788c7288442))

## [5.78.2](https://github.com/mParticle/mparticle-android-sdk/compare/v5.78.1...v5.78.2) (2026-02-27)


Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ You can grab the Core SDK via Maven Central. Please see the badge above and foll

```groovy
dependencies {
implementation 'com.mparticle:android-core:5.78.2'
implementation 'com.mparticle:android-core:5.79.0'
}
```

Expand All @@ -31,8 +31,8 @@ Several integrations require additional client-side add-on libraries called "kit
```groovy
dependencies {
implementation (
'com.mparticle:android-example-kit:5.78.2',
'com.mparticle:android-another-kit:5.78.2'
'com.mparticle:android-example-kit:5.79.0',
'com.mparticle:android-another-kit:5.79.0'
)
}
```
Expand Down
4 changes: 4 additions & 0 deletions android-core/proguard.pro
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@

-keep class com.mparticle.MPEvent$* { *; }
-keep class com.mparticle.MParticle { *; }
-keep class com.mparticle.MParticle$Internal { *; }
-keep class com.mparticle.internal.ConfigManager {
public com.mparticle.networking.NetworkOptions getNetworkOptions();
}
-keep class com.mparticle.MParticle$EventType { *; }
-keep class com.mparticle.MParticle$InstallType { *; }
-keep class com.mparticle.MParticle$IdentityType { *; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import com.mparticle.testutils.BaseCleanStartedEachTest;
import com.mparticle.testutils.BuildConfig;
import com.mparticle.testutils.MPLatch;

import java.util.concurrent.TimeUnit;
import com.mparticle.testutils.RandomUtils;

import org.json.JSONArray;
Expand Down Expand Up @@ -68,6 +70,7 @@ public class MParticleJSInterfaceITest extends BaseCleanStartedEachTest {
private static boolean sdkFetchedSuccessfully = false;
private static String bridgeToken = new RandomUtils().getAlphaString(5);
private static String bridgeVersion = "2";
private static final int WEBVIEW_TIMEOUT_SECONDS = 30;

private static final String jsStartupMParticle = "window.mParticle = {\n" +
" config: {\n" +
Expand Down Expand Up @@ -238,7 +241,7 @@ public void setUserAttribute(String json) {

}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -263,7 +266,7 @@ public void removeUserAttribute(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand Down Expand Up @@ -304,7 +307,7 @@ public void setUserAttribute(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand Down Expand Up @@ -361,7 +364,7 @@ public void logEvent(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand Down Expand Up @@ -443,7 +446,7 @@ public void logEvent(String json) {
}
});
assertNull(error.value);
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -470,7 +473,7 @@ public void logout(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -496,7 +499,7 @@ public void logout() {
latch.countDown();
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -522,7 +525,7 @@ public void login(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -548,7 +551,7 @@ public void login() {
latch.countDown();
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand All @@ -574,7 +577,7 @@ public void modify(String json) {
}
}
});
latch.await();
latch.await(WEBVIEW_TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(called.value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,46 @@ class MParticleOptionsTest : BaseAbstractTest() {
Assert.assertNull(options.configMaxAge)
}

@Test
fun testPersistenceMaxAgeSeconds() {
// nothing set, should return null (SDK will fall back to the 90-day default)
var options =
MParticleOptions
.builder(mContext)
.credentials("key", "secret")
.build()
Assert.assertNull(options.persistenceMaxAgeSeconds)

// positive number should be preserved
val testValue = Math.abs(ran.nextInt()) + 1
options =
MParticleOptions
.builder(mContext)
.credentials("key", "secret")
.persistenceMaxAgeSeconds(testValue)
.build()
Assert.assertEquals(testValue, options.persistenceMaxAgeSeconds)

// zero is non-positive and should be rejected (differs from configMaxAgeSeconds which
// accepts zero as "always stale") - mirrors iOS SDK behaviour
options =
MParticleOptions
.builder(mContext)
.credentials("key", "secret")
.persistenceMaxAgeSeconds(0)
.build()
Assert.assertNull(options.persistenceMaxAgeSeconds)

// negative numbers should be rejected
options =
MParticleOptions
.builder(mContext)
.credentials("key", "secret")
.persistenceMaxAgeSeconds(-5)
.build()
Assert.assertNull(options.persistenceMaxAgeSeconds)
}

@Test
fun testAndroidIdLogMessage() {
val infoLogs = ArrayList<String?>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,72 @@ class MessageServiceTest : BaseMPServiceTest() {
Assert.assertEquals(MessageService.getMessagesForUpload(database).size.toLong(), 20)
}

@Test
@Throws(JSONException::class)
fun testDeleteMessagesOlderThan() {
val sessionId = UUID.randomUUID().toString()
val now = System.currentTimeMillis()
val oneDayMillis = 24L * 60L * 60L * 1000L
// Insert 5 "old" messages dated 10 days ago and 5 "recent" messages dated 1 hour ago.
for (i in 0 until 5) {
val oldMessage =
BaseMPMessage
.Builder("custom_event")
.timestamp(now - 10L * oneDayMillis)
.build(
InternalSession().apply { mSessionID = sessionId },
null,
1L,
)
MessageService.insertMessage(database, "apiKey", oldMessage, 1L, null, null)
}
for (i in 0 until 5) {
val recentMessage =
BaseMPMessage
.Builder("custom_event")
.timestamp(now - 60L * 60L * 1000L)
.build(
InternalSession().apply { mSessionID = sessionId },
null,
1L,
)
MessageService.insertMessage(database, "apiKey", recentMessage, 1L, null, null)
}
Assert.assertEquals(
10L,
MessageService.getMessagesForUpload(database).size.toLong(),
)

// Cut off at 7 days ago - the 5 old messages should be removed and the 5 recent kept.
val cutoffMillis = now - 7L * oneDayMillis
val deleted = MessageService.deleteMessagesOlderThan(database, cutoffMillis)
Assert.assertEquals(5, deleted.toLong())
Assert.assertEquals(
5L,
MessageService.getMessagesForUpload(database).size.toLong(),
)

// Rows exactly at the cutoff must not be removed (strict `<` predicate).
val exactlyAtCutoffMessage =
BaseMPMessage
.Builder("custom_event")
.timestamp(cutoffMillis)
.build(
InternalSession().apply { mSessionID = sessionId },
null,
1L,
)
MessageService.insertMessage(database, "apiKey", exactlyAtCutoffMessage, 1L, null, null)
Assert.assertEquals(
0,
MessageService.deleteMessagesOlderThan(database, cutoffMillis).toLong(),
)
Assert.assertEquals(
6L,
MessageService.getMessagesForUpload(database).size.toLong(),
)
}

private fun getMaxId(messages: List<ReadyMessage>): Int {
var max = 0
for (message in messages) {
Expand Down
Loading
Loading