Skip to content

Conversation

@SuriyaKannimuthu
Copy link
Contributor

@SuriyaKannimuthu SuriyaKannimuthu commented Nov 11, 2025

Included Network Monitor for internet observeability and wifi connectivity checks.

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented a comprehensive network monitoring system with real-time connectivity state tracking and analysis. Improves event queue processing, bitmap downloads, and in-app message delivery based on network availability and connection conditions.
  • Chores

    • Added ACCESS_NETWORK_STATE runtime permission to support network state monitoring infrastructure.

Included Network Monitor for internet observeability and wifi connectivity checks.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Walkthrough

The PR introduces a new NetworkMonitor component that manages Android device connectivity with real-time state tracking via Kotlin Flow, replacing static network checks from NetworkManager. The component is instantiated in CleverTapFactory and injected into BaseEventQueueManager, InAppController, and exposed via CoreState. The ACCESS_NETWORK_STATE permission is added to the manifest.

Changes

Cohort / File(s) Change Summary
Manifest
clevertap-core/src/main/AndroidManifest.xml
Added android.permission.ACCESS_NETWORK_STATE runtime permission.
New NetworkMonitor Implementation
clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkMonitor.kt
Created new class with NetworkType enum (WIFI, CELLULAR, ETHERNET, VPN, UNKNOWN, DISCONNECTED) and NetworkState data class. Implements ConnectivityManager callbacks for real-time monitoring, exposes reactive networkState Flow and synchronous accessors (getCurrentNetworkState(), isNetworkOnline(), isWifiConnected(), getNetworkType(), performQuickNetworkCheck()). Includes API-level compatibility, graceful exception handling, and cleanup.
Factory & Injection
clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt, clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
Instantiates NetworkMonitor and injects into BaseEventQueueManager, InAppController; exposed in CoreState return value.
Network Check Migration
clevertap-core/src/main/java/com/clevertap/android/sdk/bitmap/BitmapDownloadRequestHandler.kt, clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java, clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
Replaced NetworkManager.isNetworkOnline(context) calls with injected networkMonitor.isNetworkOnline() across bitmap downloads, queue flushing, and in-app visibility logic.
Cleanup
clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt
Removed static isNetworkOnline(context: Context): Boolean method and associated imports.
Test Updates
clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
Updated mocking to use NetworkMonitor instead of NetworkManager for network status assertions.

Sequence Diagram(s)

sequenceDiagram
    participant Factory as CleverTapFactory
    participant NM as NetworkMonitor
    participant CM as ConnectivityManager
    participant EventQ as EventQueueManager
    participant InApp as InAppController
    
    Factory->>NM: new NetworkMonitor(context, config)
    activate NM
    NM->>CM: getActiveNetwork()
    NM->>CM: registerNetworkCallback()
    NM->>NM: computeInitialState()
    deactivate NM
    
    Factory->>EventQ: BaseEventQueueManager(networkMonitor)
    Factory->>InApp: InAppController(networkMonitor)
    
    Note over NM,CM: During Runtime
    CM-->>NM: onAvailable / onLost
    NM->>NM: updateNetworkState()
    NM->>NM: emit to networkState Flow
    
    EventQ->>NM: isNetworkOnline()
    InApp->>NM: isNetworkOnline()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • NetworkMonitor.kt requires careful review for connectivity callback lifecycle, thread safety of state flow emissions, and API-level compatibility paths (M and earlier vs. modern).
  • Constructor signature changes in BaseEventQueueManager, InAppController, and CoreState are breaking changes; verify all instantiation sites have been updated.
  • Migration sites (EventQueueManager.java, InAppController.kt, BitmapDownloadRequestHandler.kt) should be checked for correct parameter passing and null-safety.
  • Error handling and edge cases in network state detection (exceptions, default states, rapid state transitions).

Possibly related PRs

Suggested reviewers

  • vasct
  • piyush-kukadiya
  • nzagorchev

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[SDK - 4890] Network Info fetch and internet check in Android' accurately summarizes the main change: introducing network monitoring and connectivity checks via a new NetworkMonitor component.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch task/android/SDK-4890

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@francispereira
Copy link

francispereira commented Nov 11, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt (1)

644-644: Fix inconsistent reference to NetworkManager.

Line 644 still references NetworkManager.isNetworkOnline(any()), but this should be NetworkMonitor.isNetworkOnline(any()) to match the other changes in this test file (lines 24, 62, 83-85). This inconsistency will likely cause compilation or test failures.

Apply this diff:

-        every { NetworkManager.isNetworkOnline(any()) } returns false
+        every { NetworkMonitor.isNetworkOnline(any()) } returns false
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4583495 and 317e20f.

📒 Files selected for processing (9)
  • clevertap-core/src/main/AndroidManifest.xml (1 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt (5 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt (2 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/bitmap/BitmapDownloadRequestHandler.kt (2 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java (7 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt (3 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt (0 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkMonitor.kt (1 hunks)
  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt (3 hunks)
💤 Files with no reviewable changes (1)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt
🧰 Additional context used
🧠 Learnings (27)
📓 Common learnings
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt:0-0
Timestamp: 2025-07-01T13:00:26.100Z
Learning: In the CleverTap Android SDK's encryption system, the NetworkManager's behavior of silently falling back to unencrypted requests when encryption fails (EncryptionFailure) is intentional by design, not a security oversight. This fallback ensures request reliability and is planned to be documented.
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 866
File: clevertap-core/src/main/java/com/clevertap/android/sdk/ManifestInfo.java:266-268
Timestamp: 2025-10-07T14:10:07.979Z
Learning: In the CleverTap Android SDK, when reviewing visibility modifiers for getters in ManifestInfo.java, the team prefers to defer access control standardization to a future dedicated task rather than addressing individual getters incrementally during unrelated PRs.
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 830
File: clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt:223-240
Timestamp: 2025-06-27T10:11:22.171Z
Learning: In the CleverTap Android SDK, the asynchronous initialization of inAppFCManager in CleverTapFactory.kt is intentional behavior. It's acceptable for inAppFCManager to remain null initially after CoreState creation, as it will be created in another background thread later in the workflow if needed. This async pattern is designed to avoid blocking the main initialization flow.
📚 Learning: 2025-06-30T13:08:50.158Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 829
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java:71-81
Timestamp: 2025-06-30T13:08:50.158Z
Learning: In the CleverTap Android SDK InAppController class, the static `currentlyDisplayingInApp` field is intentionally designed to ensure only one in-app notification can be displayed on the UI at any given time across the entire application, regardless of how many InAppController instances exist. This prevents multiple in-app notifications from overlapping or competing for screen space.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
📚 Learning: 2025-06-27T10:11:22.171Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 830
File: clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt:223-240
Timestamp: 2025-06-27T10:11:22.171Z
Learning: In the CleverTap Android SDK, the asynchronous initialization of inAppFCManager in CleverTapFactory.kt is intentional behavior. It's acceptable for inAppFCManager to remain null initially after CoreState creation, as it will be created in another background thread later in the workflow if needed. This async pattern is designed to avoid blocking the main initialization flow.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java
📚 Learning: 2025-07-09T13:28:16.360Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 846
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.kt:412-417
Timestamp: 2025-07-09T13:28:16.360Z
Learning: In the CleverTap Android SDK CTInAppNotification class, CTLalit considers the media validation logic that mutates mediaUrl properties as legacy code and prefers not to refactor it, even when mutation could be avoided through filtering approaches.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-07-09T13:28:25.364Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 846
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.kt:422-432
Timestamp: 2025-07-09T13:28:25.364Z
Learning: CTLalit considers the CTInAppNotification class in the CleverTap Android SDK as legacy code and prefers not to refactor it, even when the code has potential improvements like media validation logic that could be more efficient.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java
  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-07-09T13:27:32.141Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 846
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/fragment/CTInAppNativeHalfInterstitialImageFragment.kt:20-143
Timestamp: 2025-07-09T13:27:32.141Z
Learning: In the CleverTap Android SDK, CTLalit considers the CTInAppNativeHalfInterstitialImageFragment class as legacy code and prefers not to refactor it, even when the code has complex methods that could benefit from restructuring.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java
📚 Learning: 2025-04-28T08:41:36.134Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 797
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java:184-185
Timestamp: 2025-04-28T08:41:36.134Z
Learning: In the CleverTap Android SDK, parcels in the CTInAppNotification class exist only in memory and are not persisted, so backward compatibility concerns between different SDK versions are not applicable for these parcels.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-05-08T08:25:14.692Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 802
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFullHtmlFragment.java:44-48
Timestamp: 2025-05-08T08:25:14.692Z
Learning: In the CleverTap Android SDK, fragments are managed using add and remove methods rather than replace, so resources are properly cleaned up in onDestroyView() without needing additional cleanup in onDestroy().

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
📚 Learning: 2025-06-17T13:54:08.138Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 830
File: clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java:168-169
Timestamp: 2025-06-17T13:54:08.138Z
Learning: In the CleverTap Android SDK, the static mutable clevertapClock field in CleverTapAPI.java is acceptable because all instances consistently use Clock.SYSTEM, so the mutation doesn't cause practical multi-instance issues in their use case.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
📚 Learning: 2025-06-27T10:13:58.579Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 830
File: clevertap-core/src/test/java/com/clevertap/android/sdk/MockCoreState.kt:37-38
Timestamp: 2025-06-27T10:13:58.579Z
Learning: In the CleverTap Android SDK tests, MockCTExecutors has a no-argument constructor that provides default mock implementations, so it doesn't require CleverTapInstanceConfig parameter like the production CTExecutors class does.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt
  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java
📚 Learning: 2025-04-28T09:52:18.094Z
Learnt from: vasct
Repo: CleverTap/clevertap-android-sdk PR: 797
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTInboxActivity.java:89-92
Timestamp: 2025-04-28T09:52:18.094Z
Learning: In the CleverTap Android SDK, if a CleverTapAPI instance is not null, then its getCoreState() method will never return null because CoreState is initialized in the constructor and set via setCoreState(). The CleverTapFactory.getCoreState() method throws a RuntimeException if it can't create a valid state.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
📚 Learning: 2025-10-07T14:10:07.979Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 866
File: clevertap-core/src/main/java/com/clevertap/android/sdk/ManifestInfo.java:266-268
Timestamp: 2025-10-07T14:10:07.979Z
Learning: In the CleverTap Android SDK, when reviewing visibility modifiers for getters in ManifestInfo.java, the team prefers to defer access control standardization to a future dedicated task rather than addressing individual getters incrementally during unrelated PRs.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-07-01T13:00:26.100Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt:0-0
Timestamp: 2025-07-01T13:00:26.100Z
Learning: In the CleverTap Android SDK's encryption system, the NetworkManager's behavior of silently falling back to unencrypted requests when encryption fails (EncryptionFailure) is intentional by design, not a security oversight. This fallback ensures request reliability and is planned to be documented.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
  • clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java
📚 Learning: 2025-07-01T12:49:30.819Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/api/EncryptedResponseBody.kt:10-16
Timestamp: 2025-07-01T12:49:30.819Z
Learning: In the CleverTap Android SDK's encryption system, exception handling for JSON parsing in EncryptedResponseBody.fromJsonString() is intentionally handled at the call site level (in NetworkEncryptionManager.decryptResponse) rather than within the parsing method itself, following a centralized exception handling pattern.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
📚 Learning: 2025-06-24T05:54:46.949Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/IJRepo.kt:50-54
Timestamp: 2025-06-24T05:54:46.949Z
Learning: In CleverTap Android SDK's IJRepo class, the IJ SharedPreferences namespace is dedicated exclusively to storing the I and J values, so using editor.clear() in clearIJ() is appropriate and intended, rather than removing individual keys.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
📚 Learning: 2025-06-06T10:41:32.111Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/cryption/CryptRepository.kt:64-66
Timestamp: 2025-06-06T10:41:32.111Z
Learning: In the CleverTap Android SDK's encryption system, the CryptRepository's plain SharedPreferences storage for encryption keys is intentionally designed as a fallback mechanism for Android API levels below 23, where Android Keystore is not available. The primary secure storage path uses Android Keystore for API 23+ devices, which represents the majority of modern client deployments. This is part of the backward compatibility strategy.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt
📚 Learning: 2025-09-22T04:00:43.536Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ProductDisplayLinearBigContentView.kt:144-144
Timestamp: 2025-09-22T04:00:43.536Z
Learning: In ProductDisplayLinearBigContentView.kt, the `imageUrl!!` non-null assertion is safe because it's guarded by the `!fallback` condition. When imageUrl is null, loadImageURLIntoRemoteView returns true (fallback = true), so the line with `imageUrl!!` never executes.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/bitmap/BitmapDownloadRequestHandler.kt
📚 Learning: 2025-09-29T11:43:18.372Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 865
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/media/TemplateMediaManager.kt:15-18
Timestamp: 2025-09-29T11:43:18.372Z
Learning: For TemplateMediaManager in CleverTap Android SDK push templates: Simple mutable map caches are preferred over LRU cache implementations as the use case doesn't warrant the additional complexity. The cache clearing mechanism via clearCaches() and bounded nature of push template usage makes LRU unnecessary.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-04-28T08:57:50.096Z
Learnt from: vasct
Repo: CleverTap/clevertap-android-sdk PR: 797
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/customtemplates/TemplatesManager.kt:34-42
Timestamp: 2025-04-28T08:57:50.096Z
Learning: In the CleverTap Android SDK, the CustomTemplate class implements equals() and hashCode() to compare templates based on their name property, enabling collections to correctly identify duplicate templates without additional explicit name comparisons.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-09-24T12:32:37.589Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 885
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/validators/TimerTemplateValidator.kt:11-13
Timestamp: 2025-09-24T12:32:37.589Z
Learning: In CleverTap push templates validation system, the TimerTemplateValidator uses legacy patterns with non-null assertions (e.g., keys[PT_TIMER_DISMISS_AFTER]!!) which are acceptable because the validation system guarantees these keys exist in the keys map.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-09-22T04:44:06.841Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/handlers/CancelTemplateHandler.kt:10-21
Timestamp: 2025-09-22T04:44:06.841Z
Learning: The CancelTemplateHandler.renderCancelNotification method in the CleverTap Android SDK push templates is legacy code. When flagging potential safety issues like NumberFormatException handling or null service guards, the team prefers to defer such improvements rather than modify legacy code during feature-focused PRs.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-06-27T10:13:58.579Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 830
File: clevertap-core/src/test/java/com/clevertap/android/sdk/MockCoreState.kt:37-38
Timestamp: 2025-06-27T10:13:58.579Z
Learning: In the CleverTap Android SDK tests, MockCTExecutors has a JvmOverloads constructor with a default parameter (config: CleverTapInstanceConfig? = null), so it can be instantiated without arguments using MockCTExecutors() for testing purposes.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-09-24T12:08:40.196Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 872
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/Style.kt:39-45
Timestamp: 2025-09-24T12:08:40.196Z
Learning: The Style.kt setNotificationBuilderBasics method in the CleverTap Android SDK push templates is legacy code. When flagging potential safety issues like NPE from Html.fromHtml(pt_title) with null values or Color.parseColor crashes with blank strings, the team prefers to defer such improvements rather than modify legacy code during feature-focused PRs.

Applied to files:

  • clevertap-core/src/test/java/com/clevertap/android/sdk/inapp/InAppControllerTest.kt
📚 Learning: 2025-06-05T11:55:02.777Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/http/NetworkRepo.kt:0-0
Timestamp: 2025-06-05T11:55:02.777Z
Learning: In CleverTap Android SDK, StorageHelper.getIntFromPrefs(context, config, key, default) and StorageHelper.putInt(context, StorageHelper.storageKeyWithSuffix(config.accountId, key), value) are consistent in their internal key handling despite appearing to use different patterns at the API level. The existing usage patterns in NetworkRepo.kt are correct and intentional.

Applied to files:

  • clevertap-core/src/main/java/com/clevertap/android/sdk/CoreState.kt
📚 Learning: 2025-05-08T08:31:50.340Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 802
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java:180-182
Timestamp: 2025-05-08T08:31:50.340Z
Learning: The CTInAppNotification class in the CleverTap Android SDK adds new fields `aspectRatio` and `isRequestForPushPermission` to its Parcel implementation in version 7.4.0, but doesn't require parcel versioning as these parcels only exist in memory during a single app session.

Applied to files:

  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-01-24T11:56:39.526Z
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 741
File: clevertap-core/src/main/java/com/clevertap/android/sdk/AnalyticsManager.java:1143-1143
Timestamp: 2025-01-24T11:56:39.526Z
Learning: Privacy and security related changes in the CleverTap Android SDK, such as PII exposure in logs, should be discussed with the team before implementation to ensure proper handling of sensitive data.

Applied to files:

  • clevertap-core/src/main/AndroidManifest.xml
📚 Learning: 2025-05-28T11:10:51.166Z
Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 734
File: clevertap-pushtemplates/src/main/res/layout-v31/timer.xml:58-60
Timestamp: 2025-05-28T11:10:51.166Z
Learning: For API 31+ (Android 12+) in CleverTap push templates, action buttons are handled through official Android notification APIs rather than custom layout includes. The API 31+ layout versions intentionally omit layout/action_buttons inclusions because the action buttons are managed by the Android system's notification builder APIs directly.

Applied to files:

  • clevertap-core/src/main/AndroidManifest.xml
🧬 Code graph analysis (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/events/EventQueueManager.java (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkMonitor.kt (2)
  • isNetworkOnline (23-26)
  • isNetworkOnline (204-204)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-staticChecks-test-build
🔇 Additional comments (2)
clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.kt (1)

74-74: LGTM! Clean dependency injection.

The networkMonitor parameter is properly added to the constructor and used for network checks at line 660. This follows dependency injection best practices and aligns with the PR's objective to introduce NetworkMonitor for connectivity management.

clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt (1)

362-365: LGTM! NetworkMonitor properly instantiated.

The NetworkMonitor is cleanly instantiated with necessary dependencies (context and config) and correctly wired into the dependency graph, being passed to EventQueueManager (line 384), InAppController (line 441), and exposed via CoreState (line 518).

Comment on lines +96 to +97
private var _currentState: NetworkState = NetworkState.DISCONNECTED

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Mark _currentState as volatile (or use an atomic)

ConnectivityManager.NetworkCallback delivers updates on binder threads while consumers like EventQueueManager query isNetworkOnline() from other threads. Without a happens-before edge, _currentState updates can remain invisible, keeping callers stuck in the wrong connectivity mode. Please mark _currentState as @Volatile (or wrap it in an AtomicReference) so cross-thread readers always observe the latest state.

@Volatile
private var _currentState: NetworkState = NetworkState.DISCONNECTED
🤖 Prompt for AI Agents
In
clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkMonitor.kt
around lines 96-97, the private field _currentState is updated from
ConnectivityManager.NetworkCallback on binder threads but read from other
threads, so make the update visible across threads: mark _currentState as
@Volatile (or replace it with an AtomicReference<NetworkState>) and update the
usages accordingly so readers always observe the latest state.

Comment on lines +155 to +197
private fun registerNetworkCallback() {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
updateInternalNetworkState() // Update internal state
logger.verbose(config.accountId, "Network became available: ${_currentState.networkType}")
}

override fun onLost(network: Network) {
updateInternalNetworkState() // Update internal state
logger.verbose(config.accountId, "Network lost")
}

override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
updateInternalNetworkState() // Update internal state
logger.verbose(config.accountId, "Network capabilities changed: ${_currentState.networkType}")
}

override fun onUnavailable() {
updateInternalNetworkState() // Update internal state
logger.verbose(config.accountId, "Network unavailable")
}
}

networkCallback = callback

try {
val networkRequest = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.build()

connectivityManager?.registerNetworkCallback(networkRequest, callback)
logger.verbose(config.accountId, "Network callback registered successfully")

} catch (e: SecurityException) {
logger.debug(config.accountId, "Network callback registration failed: ${e.message}")
} catch (e: Exception) {
logger.debug(config.accountId, "Network callback registration failed: ${e.message}")
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard network callbacks for pre-Lollipop and keep state fresh

ConnectivityManager.registerNetworkCallback(...) only exists from API 21. Calling it on older devices throws NoSuchMethodError, and even if you guard the call later, _currentState would never refresh because callbacks aren’t supported there. Please feature-detect the API level before building the request, skip registration pre-L, and fall back to synchronous checks when networkCallback is null. Example:

-    private fun registerNetworkCallback() {
-        val callback = object : ConnectivityManager.NetworkCallback() {
+    private val supportsCallbacks = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
+
+    private fun registerNetworkCallback() {
+        if (!supportsCallbacks) {
+            logger.verbose(config.accountId, "Network callbacks unsupported pre-L; relying on synchronous checks")
+            return
+        }
+        val callback = object : ConnectivityManager.NetworkCallback() {
             ...
         }
         networkCallback = callback
-
-        try {
-            val networkRequest = NetworkRequest.Builder()
+        try {
+            val networkRequest = NetworkRequest.Builder()
                 ...
             connectivityManager?.registerNetworkCallback(networkRequest, callback)
             logger.verbose(config.accountId, "Network callback registered successfully")

And in the synchronous API surface do a quick recomputation when callbacks aren’t available:

-    fun isNetworkOnline(): Boolean = _currentState.isAvailable
+    fun isNetworkOnline(): Boolean = if (supportsCallbacks) {
+        _currentState.isAvailable
+    } else {
+        isNetworkConnected(context).also { updateInternalNetworkState() }
+    }

This prevents crashes on legacy devices and keeps behaviour aligned with the old per-call polling.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkMonitor.kt
around lines 155 to 197, guard usage of
ConnectivityManager.registerNetworkCallback with an API-level check (only call
and build NetworkRequest/register callback when API >= 21) and catch/handle
NoSuchMethodError; for pre-L devices skip registration (leave networkCallback
null), immediately call updateInternalNetworkState() so _currentState is
recomputed, and ensure all public synchronous network-check paths treat a null
networkCallback as “callbacks unsupported” and perform the synchronous
polling/recomputation flow instead; keep the existing logging for
success/failure but log and skip registration on older APIs to avoid crashes and
preserve state freshness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants