Abrova
☰ Docs menu · Callbacks
Coming soon. Abrova Push is coming soon. This page describes how it will work; it can’t be used yet.

Callbacks

SDK callbacks for monitoring state and events — messages, connection state, registration, errors, network, app state, notification clicks, action buttons, reconnecting state, analytics handler.

Last updated: 27 Oct 2026

Monitor SDK state and events with these callbacks. The callback set is shared across SDKs; syntax varies by platform.

Flutter#

Message Received

dart
AbrovaPush.onMessage((message) {
  print('Title: ${message.title}');
  print('Body: ${message.body}');
  print('Data: ${message.data}');

  // Show local notification or update UI
});

Connection State

dart
AbrovaPush.onConnectionState((connected) {
  if (connected) {
    print('Connected to server');
  } else {
    print('Disconnected from server');
  }
});

Registration Success

dart
AbrovaPush.onRegistered((deviceId) {
  print('Device registered with ID: $deviceId');
  // Store deviceId for later use
});

Error Handling

dart
// Simple error callback
AbrovaPush.onError((error) {
  print('Error: $error');
});

// Detailed error with codes
AbrovaPush.onDetailedError((error) {
  print('Code: ${error.code}');
  print('Message: ${error.message}');
  print('Details: ${error.details}');
});

Network State

dart
AbrovaPush.onNetworkState((state) {
  print('Network available: ${state.isAvailable}');
  print('Network type: ${state.networkType}');
  // wifi, cellular, ethernet, vpn, none, unknown
});

App State

dart
AbrovaPush.onAppState((state) {
  print('In foreground: ${state.isInForeground}');
  // SDK auto-reconnects when app returns to foreground
});

Android (Kotlin)#

The Android SDK uses a single AbrovaPushCallback interface — implement the methods you need and register it once via setCallback(...). Extend AbrovaPushCallbackAdapter for empty defaults on the methods you don't override.

kotlin
import ir.abrova.push.sdk.AbrovaPush
import ir.abrova.push.sdk.AbrovaPushCallback
import ir.abrova.push.sdk.AbrovaPushCallbackAdapter
import ir.abrova.push.sdk.AbrovaPushMessage
import ir.abrova.push.sdk.AbrovaPushError

AbrovaPush.setCallback(object : AbrovaPushCallback {
    override fun onMessageReceived(message: AbrovaPushMessage) {
        Log.d("AbrovaPush", "Title: ${message.title}")
        Log.d("AbrovaPush", "Body: ${message.body}")
        Log.d("AbrovaPush", "Data: ${message.data}")
    }

    override fun onConnectionStateChanged(connected: Boolean) {
        Log.d("AbrovaPush", if (connected) "Connected" else "Disconnected")
    }

    override fun onRegistered(deviceId: String) {
        Log.d("AbrovaPush", "Device registered: $deviceId")
    }

    override fun onError(error: String) {
        Log.e("AbrovaPush", "Error: $error")
    }

    override fun onDetailedError(error: AbrovaPushError) {
        Log.e("AbrovaPush", "Code: ${error.code}, Message: ${error.message}")
    }

    override fun onReconnecting(attempt: Int, nextRetryMs: Long) {
        Log.d("AbrovaPush", "Retry $attempt, next in ${nextRetryMs}ms")
    }

    override fun onNetworkStateChanged(isAvailable: Boolean, networkType: String) {
        Log.d("AbrovaPush", "Network: $isAvailable ($networkType)")
        // networkType: wifi, cellular, ethernet, vpn, none, unknown
    }

    override fun onAppStateChanged(isInForeground: Boolean) {
        Log.d("AbrovaPush", "Foreground: $isInForeground")
    }

    override fun onAppUpdated(previousVersion: String, currentVersion: String, needsReregistration: Boolean) {
        Log.d("AbrovaPush", "Updated $previousVersion → $currentVersion")
        if (needsReregistration) {
            AbrovaPush.register(userId = "user_123")
        }
    }

    override fun onNotificationTapped(message: AbrovaPushMessage) {
        Log.d("AbrovaPush", "Notification tapped: ${message.title}")
        // Handle when app is in foreground / resumed
    }

    override fun onNotificationAction(message: AbrovaPushMessage, actionId: String) {
        Log.d("AbrovaPush", "Action clicked: $actionId for ${message.title}")
    }
})

Adapter for Selected Callbacks

kotlin
// Only override what you need
AbrovaPush.setCallback(object : AbrovaPushCallbackAdapter() {
    override fun onMessageReceived(message: AbrovaPushMessage) {
        showNotification(message)
    }

    override fun onNotificationTapped(message: AbrovaPushMessage) {
        navigateToDeepLink(message.data?.get("deepLink") as? String)
    }
})

Initial Message (App Opened from Notification)

kotlin
// Returns the notification that launched the app, or null
val initialMessage = AbrovaPush.getInitialMessage()
if (initialMessage != null) {
    val deepLink = initialMessage.data?.get("deepLink") as? String
    if (deepLink != null) {
        // Navigate to deep link
    }
}

Analytics Handler

Not supported on Android: the handler is never called. Use the AbrovaPushCallback methods above for telemetry.

kotlin
import ir.abrova.push.sdk.AbrovaPush
import ir.abrova.push.sdk.AbrovaPushAnalyticsCallback
import ir.abrova.push.sdk.AbrovaPushAnalyticsEvent

AbrovaPush.setAnalyticsHandler(AbrovaPushAnalyticsCallback { event, properties ->
    Log.d("AbrovaPush", "Event: $event, Properties: $properties")

    // Send to your analytics service (Firebase, Mixpanel, etc.)
    when (event) {
        AbrovaPushAnalyticsEvent.MESSAGE_RECEIVED ->
            FirebaseAnalytics.getInstance(context).logEvent("push_received", null)
        AbrovaPushAnalyticsEvent.NOTIFICATION_CLICKED ->
            FirebaseAnalytics.getInstance(context).logEvent("push_clicked", null)
        AbrovaPushAnalyticsEvent.CONNECTION_ERROR ->
            FirebaseAnalytics.getInstance(context).logEvent("push_error", null)
        else -> { /* ignore */ }
    }
})

// Disable / re-enable / check
AbrovaPush.disableAnalytics()
val enabled = AbrovaPush.isAnalyticsEnabled()

React Native#

Message Received

typescript
const unsubscribe = AbrovaPush.onMessage((message) => {
  console.log('Title:', message.title);
  console.log('Body:', message.body);
  console.log('Data:', message.data);
});

// Clean up in useEffect
useEffect(() => {
  return () => unsubscribe();
}, []);

Connection State

typescript
const unsubscribe = AbrovaPush.onConnectionState((connected) => {
  console.log(connected ? 'Connected' : 'Disconnected');
});

Registration Success

typescript
const unsubscribe = AbrovaPush.onRegistered((deviceId) => {
  console.log('Device ID:', deviceId);
});

Complete Hook Example

typescript
import { useEffect, useState } from 'react';
import AbrovaPush from 'abrova-push-react-native';

export function useAbrovaPush(userId: string) {
  const [connected, setConnected] = useState(false);
  const [deviceId, setDeviceId] = useState<string | null>(null);

  useEffect(() => {
    const unsubMessage = AbrovaPush.onMessage((msg) => {
      console.log('Message:', msg);
    });

    const unsubConnection = AbrovaPush.onConnectionState(setConnected);
    const unsubRegistered = AbrovaPush.onRegistered(setDeviceId);

    AbrovaPush.register({ userId });

    return () => {
      unsubMessage();
      unsubConnection();
      unsubRegistered();
    };
  }, [userId]);

  return { connected, deviceId };
}

iOS (Swift)#

The iOS SDK uses a delegate pattern. Conform to AbrovaPushDelegate and assign it via AbrovaPush.shared.delegate. All methods are optional via the default extension — implement only the ones you need.

swift
import AbrovaPushSDK

class PushHandler: NSObject, AbrovaPushDelegate {
    func abrovaPush(_ abrovaPush: AbrovaPush, didReceiveMessage message: AbrovaPushMessage) {
        print("Title: \(message.title)")
        print("Body: \(message.body)")
        print("Data: \(message.data ?? [:])")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didChangeConnectionState connected: Bool) {
        print(connected ? "Connected" : "Disconnected")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didRegisterWithDeviceId deviceId: String) {
        print("Device registered: \(deviceId)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didReceiveAPNsToken token: String) {
        print("APNs token: \(token)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didReceiveVoIPToken token: String) {
        print("VoIP token: \(token)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didFailWithError error: Error) {
        print("Error: \(error.localizedDescription)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didFailWithDetailedError error: AbrovaPushError) {
        print("Code: \(error.code), Message: \(error.message)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didStartReconnecting state: ReconnectionState) {
        print("Retry \(state.attempt), next in \(state.nextRetryMs)ms")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didChangeNetworkState state: NetworkState) {
        print("Network: \(state.isAvailable) (\(state.networkType))")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didChangeAppState state: AppState) {
        print("Foreground: \(state.isInForeground)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didDetectAppUpdate info: AppUpdateInfo) {
        print("Updated \(info.previousVersion) → \(info.currentVersion)")
        if info.needsReregistration {
            AbrovaPush.shared.register(userId: "user_123")
        }
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didTapNotification message: AbrovaPushMessage) {
        print("Notification tapped: \(message.title)")
    }

    func abrovaPush(_ abrovaPush: AbrovaPush, didReceiveNotificationAction action: NotificationAction, forMessage message: AbrovaPushMessage) {
        print("Action: \(action.id) for \(message.title)")
    }
}

// Wire it up once (e.g., in AppDelegate or App init).
// `delegate` is weak, so keep a strong reference to the handler (e.g., a property).
let pushHandler = PushHandler()
AbrovaPush.shared.delegate = pushHandler

Initial Message (App Opened from Notification)

swift
// Returns the notification that launched the app, or nil
if let initialMessage = AbrovaPush.shared.getInitialMessage() {
    if let deepLink = initialMessage.deepLink ?? (initialMessage.data?["deepLink"]?.value as? String) {
        // Navigate to deep link
    }
    AbrovaPush.shared.clearInitialMessage()
}

// If the app was opened by tapping an action button on the launching notification
if let clicked = AbrovaPush.shared.getClickedAction() {
    print("Launched via action \(clicked.action.id) on \(clicked.message.title)")
}
Analytics Handler Not Available on iOS.

The iOS SDK does not currently expose setAnalyticsHandler. For SDK telemetry, observe the relevant delegate methods (didReceiveMessage, didChangeConnectionState, didFailWithDetailedError, etc.) and forward those events to your analytics provider directly. Flutter and Web support setAnalyticsHandler; Android exposes it but it is not supported there, and the React Native wrapper does not expose it either.

Web#

Message Received

typescript
abrovaPush.onMessage((message) => {
  console.log('Title:', message.title);
  console.log('Body:', message.body);
  console.log('Data:', message.data);

  // Show notification or update UI
});

Connection State

typescript
abrovaPush.onConnectionState((state) => {
  console.log('Connection state:', state);
  // 'connecting' | 'connected' | 'disconnected' | 'error'
});

Registration Success

typescript
abrovaPush.onRegistered((deviceId) => {
  console.log('Device ID:', deviceId);
});

Notification Click

typescript
abrovaPush.onNotificationClick((message, action) => {
  console.log('Notification clicked:', message);
  console.log('Action:', action);

  // Navigate to specific page based on message data
  if (message.data?.url) {
    window.location.href = message.data.url;
  }
});

Action Button Clicked

typescript
abrovaPush.onActionClicked((actionId, message) => {
  console.log('Action clicked:', actionId);
  console.log('Message:', message);

  // Handle specific actions
  switch (actionId) {
    case 'view':
      window.location.href = message.data?.deepLink || '/';
      break;
    case 'dismiss':
      // Handle dismiss
      break;
  }
});

Error Handling

typescript
import { AbrovaPushErrorCode } from '@abrova/push-web';

// Simple error callback
abrovaPush.onError((error) => {
  console.error('Error:', error.message);
});

// Detailed error with codes
abrovaPush.onDetailedError((error) => {
  console.error('Code:', error.code);
  console.error('Message:', error.message);
  console.error('Details:', error.details);

  switch (error.code) {
    case AbrovaPushErrorCode.CONNECTION_FAILED:
      // Handle connection failure
      break;
    case AbrovaPushErrorCode.PERMISSION_DENIED:
      // Handle permission denied
      break;
  }
});

Reconnecting State

typescript
abrovaPush.onReconnecting((state) => {
  console.log('Retry attempt:', state.retryAttempt);
  console.log('Next retry in:', state.nextRetryMs, 'ms');
  console.log('Max attempts:', state.maxRetryAttempts);

  // Show reconnecting UI
  showReconnectingBanner(state.retryAttempt, state.maxRetryAttempts);
});

Network State

typescript
abrovaPush.onNetworkState((state) => {
  console.log('Network available:', state.isAvailable);
  console.log('Network type:', state.networkType);
  // wifi, cellular, ethernet, none, unknown

  if (!state.isAvailable) {
    showOfflineBanner();
  }
});

// Get current network state
const networkState = abrovaPush.getNetworkState();

App State (Visibility)

typescript
abrovaPush.onAppState((state) => {
  console.log('Is visible:', state.isVisible);
  console.log('Visibility state:', state.visibilityState);
  // visible, hidden, prerender

  // SDK auto-reconnects when page becomes visible
});

// Get current app state
const appState = abrovaPush.getAppState();

Initial Message (App Opened from Notification)

typescript
// Get the notification that launched/opened the app
const initialMessage = abrovaPush.getInitialMessage();

if (initialMessage) {
  console.log('App opened from notification:', initialMessage.title);
  // Navigate to relevant page
  if (initialMessage.data?.deepLink) {
    window.location.href = initialMessage.data.deepLink;
  }
}

Analytics Handler

typescript
import { AbrovaPushAnalyticsEvent } from '@abrova/push-web';

abrovaPush.setAnalyticsHandler((event, properties) => {
  console.log('Event:', event, properties);

  // Send to your analytics service
  switch (event) {
    case AbrovaPushAnalyticsEvent.MESSAGE_RECEIVED:
      analytics.track('push_received', properties);
      break;
    case AbrovaPushAnalyticsEvent.NOTIFICATION_CLICKED:
      analytics.track('push_clicked', properties);
      break;
    case AbrovaPushAnalyticsEvent.CONNECTION_ERROR:
      analytics.track('push_error', properties);
      break;
  }
});

// Disable analytics
abrovaPush.disableAnalytics();
Was this page helpful?
Report a problem