Skip to content

Conversation

@abdulraqeeb33
Copy link
Contributor

@abdulraqeeb33 abdulraqeeb33 commented Dec 5, 2025

Description

One Line Summary

Expose suspend-safe accessor methods for all SDK managers and configuration properties to prevent ANRs and improve thread safety.

Details

This PR adds suspend-based accessor methods to the OneSignal class, providing non-blocking alternatives to the existing property accessors. These methods are designed to work seamlessly with Kotlin coroutines and prevent Application Not Responding (ANR) errors by ensuring all SDK operations run on background threads.

New Suspend Accessor Methods

Manager Accessors:

  • getUserSuspend() - Suspend-safe version of User property
  • getSessionSuspend() - Suspend-safe version of Session property
  • getNotificationsSuspend() - Suspend-safe version of Notifications property
  • getLocationSuspend() - Suspend-safe version of Location property
  • getInAppMessagesSuspend() - Suspend-safe version of InAppMessages property

Configuration Property Accessors:

  • getConsentRequiredSuspend() / setConsentRequiredSuspend() - Suspend-safe version of consentRequired property
  • getConsentGivenSuspend() / setConsentGivenSuspend() - Suspend-safe version of consentGiven property
  • getDisableGMSMissingPromptSuspend() / setDisableGMSMissingPromptSuspend() - Suspend-safe version of disableGMSMissingPrompt property

User Management Methods:

  • loginSuspend() - Suspend-safe version of login() method (already existed, improved documentation)
  • logoutSuspend() - Suspend-safe version of logout() method (already existed, improved documentation)

Key Benefits

  1. ANR Prevention: All suspend methods automatically handle SDK initialization waiting on background threads, preventing main thread blocking
  2. Thread Safety: Suspend methods ensure proper thread context switching using Dispatchers.IO
  3. Backward Compatible: Existing property accessors and methods remain unchanged - this is purely additive
  4. Consistent API: All suspend accessors follow the same naming pattern (*Suspend) and behavior

Usage Example

in
// Before (can cause ANR if called on main thread before init completes)
val user = OneSignal.User
OneSignal.consentRequired = true

// After (safe to call from any thread, including main thread)
lifecycleScope.launch {
val user = OneSignal.getUserSuspend()
OneSignal.setConsentRequiredSuspend(true)
}### Motivation

Starting in 5.4.0, we've been moving SDK operations to background threads to reduce ANR reports. While the existing property accessors work, they can still block threads if the SDK isn't fully initialized. These suspend methods provide a cleaner, more explicit way for developers to use the SDK in coroutine-based code without worrying about thread blocking or ANRs.

The suspend methods automatically:

  • Wait for SDK initialization to complete (if in progress)
  • Execute on the appropriate background thread (Dispatchers.IO)
  • Return the same instances as their non-suspend counterparts
  • Maintain full compatibility with existing code

Scope

  • Added 11 new suspend accessor methods to OneSignal class
  • All methods are properly documented with KDoc comments
  • Methods delegate to existing IOneSignal interface methods (no duplicate implementation)
  • All methods include @JvmStatic annotation for Java interop
  • Comprehensive test coverage added to verify all methods exist and work correctly

Testing

Unit testing

Added comprehensive test suite (OneSignalSuspendAccessorsTests.kt) that verifies:

  • All suspend accessor methods exist and return correct types
  • All non-suspend accessor properties exist and work correctly
  • Suspend and non-suspend accessors return the same instances
  • Configuration properties work correctly in both suspend and non-suspend forms
  • Login/logout suspend methods work correctly

All existing tests continue to pass.

Manual testing

Tested on:

  • Low-end emulators (Android 8.0, 2GB RAM)
  • High-end emulators (Android 14, 8GB RAM)
  • Physical devices (Pixel 9a, various Android versions)

Verified that:

  • Suspend methods work correctly from coroutines
  • No ANRs occur when using suspend methods from main thread
  • All methods return expected types and values
  • Suspend and non-suspend accessors are consistent

Affected code checklist

  • Notifications
    • Display (via getNotificationsSuspend())
    • Open (via getNotificationsSuspend())
    • Push Processing (via getNotificationsSuspend())
    • Confirm Deliveries (via getNotificationsSuspend())
  • Outcomes (via getUserSuspend())
  • Sessions (via getSessionSuspend())
  • In-App Messaging (via getInAppMessagesSuspend())
  • REST API requests (all suspend methods use background threads)
  • Public API changes

Checklist

Overview

  • I have filled out all REQUIRED sections above
  • PR does one thing - exposes suspend accessor methods for better ANR prevention
  • Any Public API changes are explained in the PR details and conform to existing APIs

Testing

  • I have included test coverage for these changes, or explained why they are not needed
  • All automated tests pass, or I explained why that is not possible
  • I have personally tested this on my device, or explained why that is not possible

Final pass

  • Code is as readable as possible
    • All methods follow consistent naming pattern
    • Comprehensive KDoc comments explain usage and behavior
    • Clear separation between suspend and non-suspend APIs
  • I have reviewed this PR myself, ensuring it meets each checklist item

This change is Reviewable

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.

2 participants