Callbacks
SDK callbacks for monitoring state and events — messages, connection state, registration, errors, network, app state, notification clicks, action buttons, reconnecting state, analytics handler.
Monitor SDK state and events with these callbacks. The callback set is shared across SDKs; syntax varies by platform.
Flutter#
Message Received
AbrovaPush.onMessage((message) {
print('Title: ${message.title}');
print('Body: ${message.body}');
print('Data: ${message.data}');
// Show local notification or update UI
});Connection State
AbrovaPush.onConnectionState((connected) {
if (connected) {
print('Connected to server');
} else {
print('Disconnected from server');
}
});Registration Success
AbrovaPush.onRegistered((deviceId) {
print('Device registered with ID: $deviceId');
// Store deviceId for later use
});Error Handling
// 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
AbrovaPush.onNetworkState((state) {
print('Network available: ${state.isAvailable}');
print('Network type: ${state.networkType}');
// wifi, cellular, ethernet, vpn, none, unknown
});App State
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.
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
// 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)
// 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.
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
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
const unsubscribe = AbrovaPush.onConnectionState((connected) => {
console.log(connected ? 'Connected' : 'Disconnected');
});Registration Success
const unsubscribe = AbrovaPush.onRegistered((deviceId) => {
console.log('Device ID:', deviceId);
});Complete Hook Example
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.
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 = pushHandlerInitial Message (App Opened from Notification)
// 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)")
}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
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
abrovaPush.onConnectionState((state) => {
console.log('Connection state:', state);
// 'connecting' | 'connected' | 'disconnected' | 'error'
});Registration Success
abrovaPush.onRegistered((deviceId) => {
console.log('Device ID:', deviceId);
});Notification Click
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
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
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
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
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)
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)
// 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
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();