diff --git a/CHANGELOG.md b/CHANGELOG.md
index 251b9d7..3021b8b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,44 @@
## CHANGE LOG
+### Version 4.2.0 *(11 August 2026)*
+-------------------------------------------
+**What's new**
+
+* **[Android Platform]**
+ * Supports [CleverTap Android SDK v8.4.1](https://github.com/CleverTap/clevertap-android-sdk/blob/master/docs/CTCORECHANGELOG.md#version-841-august-7-2026).
+ * Custom-HTML header and footer in-apps now render when the host Activity is not a `FragmentActivity`. Opt in by adding the `CLEVERTAP_INAPP_FRAGMENTLESS_BANNERS` flag to your app's `AndroidManifest.xml`; default off, so existing integrations are unaffected.
+ * Improves accessibility across in-app notifications and App Inbox with dynamic text scaling, screen-reader announcements and content descriptions, a larger 48dp dismiss-button tap area, and corrected carousel TalkBack navigation.
+
+* **[iOS Platform]**
+ * Supports [CleverTap iOS SDK v7.8.1](https://github.com/CleverTap/clevertap-ios-sdk/blob/master/CHANGELOG.md#version-781-august-7-2026).
+ * Improves accessibility across in-app notifications and App Inbox with VoiceOver labels, a larger dismiss-button tap area, and better handling of image content descriptions.
+ * Adds Swift Package Manager (SPM) support alongside the existing CocoaPods integration - consumers can pick either package manager based on their project setup. Raises the minimum iOS deployment target to 13.0; projects below this are auto-promoted by Flutter's SPM tooling with a build log notice. See [Integrate-iOS-SPM.md](https://github.com/CleverTap/clevertap-flutter/blob/master/doc/Integrate-iOS-SPM.md) for setup and migration guidance.
+ * Adds `UIScene` lifecycle support via a new `sceneWillConnectWithOptions:` method on `CleverTapPlugin`. Apps that use a `SceneDelegate` should call it from `scene(_:willConnectTo:options:)` so `getInitialUrl()` returns the deep link on a cold launch; apps that do not use the `UIScene` lifecycle need no changes.
+
+* **[Android and iOS Platform]**
+ * Adds Spin-the-Wheel and Scratch Card gamified templates to Advanced InApp Builder in-app notifications — campaign-driven, no app-side wiring needed.
+ * Adds per-element click attribution to the in-app `Notification Clicked` event across all in-app templates, plus configurable dismiss gestures (swipe-to-dismiss, and tap-outside on iOS) that are also tracked as `Notification Clicked` events.
+
+**API changes**
+* **[Android and iOS Platform]**
+ * New API: `dismissPipInApp()` - Dismisses the currently visible Picture-in-Picture (PIP) in-app notification. A no-op when no PIP in-app is visible, and other in-app types are never affected. Dismissing frees the in-app display slot, so pair it with `suspendInAppNotifications()` and `resumeInAppNotifications()` to keep a screen free of all in-apps.
+
+**Bug Fixes**
+* **[Android Platform]**
+ * Fixes a critical issue where App Inbox messages were never saved on the device on Android 6.0 through Android 10 (API 23 – 29), leaving the inbox permanently empty. Affects every app using App Inbox on `v4.0.0` and `v4.1.0`; messages reappear automatically on the next inbox fetch after updating, with no code change required.
+ * Fixes an `AbstractMethodError` crash when a Picture-in-Picture in-app notification played a video on Android 6.0 (API 23). Only affects apps whose `minSdkVersion` is below 24; the fix also covers in-app and App Inbox video playback.
+
+* **[iOS Platform]**
+ * Fixes `getAppLaunchNotification()` not being implemented on iOS, which caused a `PlatformException` (`MissingPluginException`) when called.
+ * Fixes an issue where in-apps that were missed while the app was in the background were not shown when the app returned to the foreground.
+ * Fixes an issue where the `Notification Clicked` event did not include deeplink properties for custom-HTML in-apps.
+ * Fixes an issue where Advanced InApp Builder full-screen cover in-apps did not respect the device safe area.
+ * Fixes an issue where client-side in-apps were not persisted when an empty campaign list was received.
+ * Fixes a potential crash while saving variable diffs, and a potential crash when `syncVariables()` and concurrent variable updates ran at the same time.
+
+* **[Android and iOS Platform]**
+ * Fixes an issue where the built-in App Inbox did not repaint the message list after a pull-to-refresh — newly fetched messages only appeared after closing and reopening the inbox.
+
### Version 4.1.0 *(9 June 2026)*
-------------------------------------------
**What's new**
diff --git a/README.md b/README.md
index c89d05a..95ea071 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ To get started, sign up [here](https://clevertap.com/live-product-demo/).
```yaml
dependencies:
- clevertap_plugin: 4.1.0
+ clevertap_plugin: 4.2.0
```
- Run `flutter packages get` to install the SDK
diff --git a/android/build.gradle b/android/build.gradle
index 569fc8a..427977d 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,5 +1,5 @@
group = 'com.clevertap.clevertap_plugin'
-version = '4.1.0'
+version = '4.2.0'
buildscript {
ext.kotlin_version = "1.8.22"
@@ -62,7 +62,7 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
testImplementation 'junit:junit:4.13.2'
- api 'com.clevertap.android:clevertap-android-sdk:8.3.0'
+ api 'com.clevertap.android:clevertap-android-sdk:8.4.1'
compileOnly 'androidx.fragment:fragment:1.3.6'
compileOnly 'androidx.core:core:1.9.0'
}
diff --git a/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt b/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt
index 136890b..dc8ea19 100644
--- a/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt
+++ b/android/src/main/java/com/clevertap/clevertap_plugin/DartToNativePlatformCommunicator.kt
@@ -373,6 +373,10 @@ class DartToNativePlatformCommunicator(
resumeInAppNotifications(result)
}
+ "dismissPipInApp" -> {
+ dismissPipInApp(result)
+ }
+
"initializeInbox" -> {
initializeInbox(result)
}
@@ -1536,6 +1540,15 @@ class DartToNativePlatformCommunicator(
}
}
+ private fun dismissPipInApp(result: MethodChannel.Result) {
+ if (cleverTapAPI != null) {
+ cleverTapAPI.dismissPipInApp()
+ result.success(null)
+ } else {
+ result.error(TAG, ERROR_MSG, null)
+ }
+ }
+
private fun initializeInbox(result: MethodChannel.Result) {
if (cleverTapAPI != null) {
cleverTapAPI.initializeInbox()
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
index 7ad3451..7ef6184 100644
--- a/example/android/gradle.properties
+++ b/example/android/gradle.properties
@@ -3,4 +3,8 @@ android.useAndroidX=true
#android.enableDexingArtifactTransform.desugaring=false -> this was used before -> check below line
android.useFullClasspathForDexingTransform=true
android.nonTransitiveRClass=false
-android.nonFinalResIds=false
\ No newline at end of file
+android.nonFinalResIds=false
+# This builtInKotlin flag was added automatically by Flutter migrator
+android.builtInKotlin=false
+# This newDsl flag was added automatically by Flutter migrator
+android.newDsl=false
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
index e96ef60..61fa3c4 100644
--- a/example/ios/.gitignore
+++ b/example/ios/.gitignore
@@ -22,6 +22,7 @@ Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
+Flutter/ephemeral/
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index d57061d..ab8e063 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -20,7 +20,5 @@
????
CFBundleVersion
1.0
- MinimumOSVersion
- 13.0
diff --git a/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/example/ios/Flutter/ephemeral/flutter_lldb_helper.py
new file mode 100644
index 0000000..a88caf9
--- /dev/null
+++ b/example/ios/Flutter/ephemeral/flutter_lldb_helper.py
@@ -0,0 +1,32 @@
+#
+# Generated file, do not edit.
+#
+
+import lldb
+
+def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
+ """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
+ base = frame.register["x0"].GetValueAsAddress()
+ page_len = frame.register["x1"].GetValueAsUnsigned()
+
+ # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
+ # first page to see if handled it correctly. This makes diagnosing
+ # misconfiguration (e.g. missing breakpoint) easier.
+ data = bytearray(page_len)
+ data[0:8] = b'IHELPED!'
+
+ error = lldb.SBError()
+ frame.GetThread().GetProcess().WriteMemory(base, data, error)
+ if not error.Success():
+ print(f'Failed to write into {base}[+{page_len}]', error)
+ return
+
+def __lldb_init_module(debugger: lldb.SBDebugger, _):
+ target = debugger.GetDummyTarget()
+ # Caveat: must use BreakpointCreateByRegEx here and not
+ # BreakpointCreateByName. For some reasons callback function does not
+ # get carried over from dummy target for the later.
+ bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
+ bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
+ bp.SetAutoContinue(True)
+ print("-- LLDB integration loaded --")
diff --git a/example/ios/Flutter/ephemeral/flutter_lldbinit b/example/ios/Flutter/ephemeral/flutter_lldbinit
new file mode 100644
index 0000000..e3ba6fb
--- /dev/null
+++ b/example/ios/Flutter/ephemeral/flutter_lldbinit
@@ -0,0 +1,5 @@
+#
+# Generated file, do not edit.
+#
+
+command script import --relative-to-command-file flutter_lldb_helper.py
diff --git a/example/ios/Flutter/ephemeral/flutter_native_integration.env b/example/ios/Flutter/ephemeral/flutter_native_integration.env
new file mode 100644
index 0000000..0828b25
--- /dev/null
+++ b/example/ios/Flutter/ephemeral/flutter_native_integration.env
@@ -0,0 +1,13 @@
+FLUTTER_ROOT=/Users/runner/hostedtoolcache/flutter/stable-3.44.9-arm64/flutter
+FLUTTER_APPLICATION_PATH=/Users/runner/work/clevertap-flutter/clevertap-flutter/wrapper/example
+FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/runner/work/clevertap-flutter/clevertap-flutter/wrapper/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework
+COCOAPODS_PARALLEL_CODE_SIGN=true
+FLUTTER_TARGET=lib/main.dart
+FLUTTER_BUILD_DIR=build
+FLUTTER_BUILD_NAME=1.0.0
+FLUTTER_BUILD_NUMBER=1
+DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuNDQuOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NmIxODJkMmM3NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NWEyYTZhNDJjYw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMi4y
+DART_OBFUSCATION=false
+TRACK_WIDGET_CREATION=false
+TREE_SHAKE_ICONS=false
+PACKAGE_CONFIG=/Users/runner/work/clevertap-flutter/clevertap-flutter/wrapper/example/.dart_tool/package_config.json
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index cd9901d..0be0735 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1,8 +1,8 @@
PODS:
- - CleverTap-iOS-SDK (7.7.1):
+ - CleverTap-iOS-SDK (7.8.1):
- SDWebImage (~> 5.11)
- - clevertap_plugin (4.1.0):
- - CleverTap-iOS-SDK (= 7.7.1)
+ - clevertap_plugin (4.2.0):
+ - CleverTap-iOS-SDK (= 7.8.1)
- Flutter
- Firebase/CoreOnly (10.25.0):
- FirebaseCore (= 10.25.0)
@@ -71,7 +71,7 @@ PODS:
- nanopb/encode (= 2.30910.0)
- nanopb/decode (2.30910.0)
- nanopb/encode (2.30910.0)
- - PromisesObjC (2.4.0)
+ - PromisesObjC (2.4.1)
- SDWebImage (5.21.7):
- SDWebImage/Core (= 5.21.7)
- SDWebImage/Core (5.21.7)
@@ -107,8 +107,8 @@ EXTERNAL SOURCES:
:path: Flutter
SPEC CHECKSUMS:
- CleverTap-iOS-SDK: c80354ca6bca086bd9ea242c0ad15e859b867ea5
- clevertap_plugin: 967312b3841bf78738a922ebe1becbe6085e8029
+ CleverTap-iOS-SDK: 5cdc6452d832182516340f76444f757962b75db8
+ clevertap_plugin: 4b1cd9391438bcb537ba4020c3cc7c16271f694b
Firebase: 0312a2352584f782ea56f66d91606891d4607f06
firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197
firebase_messaging: 06391e8f35dc65a00c56580266285263d2861f10
@@ -120,9 +120,9 @@ SPEC CHECKSUMS:
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
nanopb: 438bc412db1928dac798aa6fd75726007be04262
- PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
+ PromisesObjC: 752c3227f599e3467650e47ea36f433eeb10c273
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
PODFILE CHECKSUM: 291c6e37be125d1f160f3b46b95592d2c695ff17
-COCOAPODS: 1.15.2
+COCOAPODS: 1.16.2
diff --git a/example/lib/main.dart b/example/lib/main.dart
index e49fb2e..714ab33 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -766,6 +766,10 @@ class _MyAppState extends State {
"Resume InApp notifications",
resumeInAppNotifications,
"Resumes display of InApp Notifications."),
+ _buildListTile(
+ "Dismiss PIP InApp",
+ dismissPipInApp,
+ "Dismisses the currently visible Picture-in-Picture InApp notification, if any."),
]),
if (!kIsWeb)
_buildExpansionTile("Event History", [
@@ -1793,6 +1797,12 @@ class _MyAppState extends State {
showToast("InApp notification is resumed");
}
+ void dismissPipInApp() {
+ CleverTapPlugin.dismissPipInApp();
+ showToast("PIP InApp notification dismissed (if visible)");
+ print("InApp -> dismissPipInApp called");
+ }
+
void enablePersonalization() {
CleverTapPlugin.enablePersonalization();
showToast("Personalization enabled");
diff --git a/ios/Classes/CleverTapPlugin.m b/ios/Classes/CleverTapPlugin.m
index 5daa851..9d095f5 100644
--- a/ios/Classes/CleverTapPlugin.m
+++ b/ios/Classes/CleverTapPlugin.m
@@ -167,6 +167,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
[self discardInAppNotifications:call withResult:result];
else if ([@"resumeInAppNotifications" isEqualToString:call.method])
[self resumeInAppNotifications];
+ else if ([@"dismissPipInApp" isEqualToString:call.method])
+ [self dismissPipInApp:call withResult:result];
else if ([@"fetchInbox" isEqualToString:call.method])
[self fetchInbox:call withResult:result];
else if ([@"fetchInboxWithCallback" isEqualToString:call.method])
@@ -671,10 +673,15 @@ - (void)discardInAppNotifications:(FlutterMethodCall *)call withResult:(FlutterR
}
- (void)resumeInAppNotifications {
-
+
[[CleverTap sharedInstance] resumeInAppNotifications];
}
+- (void)dismissPipInApp:(FlutterMethodCall *)call withResult:(FlutterResult)result {
+ [[CleverTap sharedInstance] dismissPipInApp];
+ result(nil);
+}
+
#pragma mark - InApp Controls
- (void)fetchInApps:(FlutterMethodCall *)call withResult:(FlutterResult)result {
diff --git a/ios/clevertap_plugin.podspec b/ios/clevertap_plugin.podspec
index 7777a58..e3babd4 100644
--- a/ios/clevertap_plugin.podspec
+++ b/ios/clevertap_plugin.podspec
@@ -3,7 +3,7 @@
#
Pod::Spec.new do |s|
s.name = 'clevertap_plugin'
- s.version = '4.1.0'
+ s.version = '4.2.0'
s.summary = 'CleverTap Flutter plugin.'
s.description = 'The CleverTap iOS SDK for App Analytics and Engagement.'
s.homepage = 'https://github.com/CleverTap/clevertap-ios-sdk'
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
- s.dependency 'CleverTap-iOS-SDK', '7.7.1'
+ s.dependency 'CleverTap-iOS-SDK', '7.8.1'
s.ios.deployment_target = '9.0'
end
diff --git a/lib/clevertap_plugin.dart b/lib/clevertap_plugin.dart
index 575b008..fb7d345 100644
--- a/lib/clevertap_plugin.dart
+++ b/lib/clevertap_plugin.dart
@@ -80,7 +80,7 @@ class CleverTapPlugin {
static const libName = 'Flutter';
static const libVersion =
- 40100; // If the current version is X.X.X then pass as X0X0X
+ 40200; // If the current version is X.X.X then pass as X0X0X
CleverTapPlugin._internal() {
/// Set the CleverTap Flutter library name and the current version for version tracking
@@ -1043,6 +1043,18 @@ class CleverTapPlugin {
.invokeMethod('resumeInAppNotifications', {});
}
+ /// Dismisses the currently visible Picture-in-Picture (PIP) InApp Notification, if any.
+ ///
+ /// This is a no-op when no PIP InApp is visible. Other InApp Notification types are
+ /// never affected. Safe to call from any thread.
+ ///
+ /// Note: dismissing releases the InApp display slot, so the next queued InApp (if any)
+ /// may show immediately. To keep a screen free of all InApps, pair this with
+ /// suspendInAppNotifications() on screen entry and resumeInAppNotifications() on exit.
+ static Future dismissPipInApp() async {
+ return await _dartToNativeMethodChannel.invokeMethod('dismissPipInApp', {});
+ }
+
/// Resumes event tracking, overriding any active mute period.
static Future unmute() async {
return await _dartToNativeMethodChannel.invokeMethod('unmute', {});
diff --git a/pubspec.yaml b/pubspec.yaml
index 448f14b..4779bb5 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: clevertap_plugin
description: The CleverTap Flutter SDK for Mobile Customer Engagement,Analytics and Retention solutions.
-version: 4.1.0
+version: 4.2.0
homepage: https://github.com/CleverTap/clevertap-flutter
environment: