Events
The SDK emits events from the native layer for tracking, analytics, and custom UI.
Event Types
| Event | Description |
|---|---|
DOWNLOAD_PROD_STARTED | Download started |
DOWNLOAD_PROD_COMPLETED | Download succeeded |
DOWNLOAD_PROD_FAILED | Download failed |
INSTALLED_PROD | Update installed |
ROLLBACK_PROD | Rolled back to previous bundle |
STABILIZE_PROD | Bundle promoted to stable |
CORRUPTION_PROD | Bundle corruption detected |
SYNC_ERROR | Error syncing events with server |
VERSION_CHANGED | Active bundle version changed |
CRASH_DETECTED | Crash detected within the detection window |
Event Shape
interface SwiftPatchEvent {
id: string; // Unique event ID
eventType: SwiftPatchEventType; // One of the types above
timestamp: number; // Unix timestamp
releaseHash?: string; // Associated bundle hash
errorMessage?: string; // Error details (for failures)
metadata?: Record<string, unknown>; // Additional context
}
Native Event Subscriptions
These fire in real time from the native layer -- not through the polled event queue (a queue where the SDK periodically checks for new events from native code).
Step 1: Import the Listeners
import {
onDownloadProgress,
onRollback,
onVersionChanged,
onNativeEvent,
} from '@swiftpatch/react-native';
Step 2: Subscribe in a useEffect
Download Progress
import { onDownloadProgress } from '@swiftpatch/react-native';
useEffect(() => {
const unsubscribe = onDownloadProgress((progress) => {
console.log(`${progress.percentage}% complete`);
});
return unsubscribe;
}, []);
Rollback Events
import { onRollback } from '@swiftpatch/react-native';
useEffect(() => {
const unsubscribe = onRollback((reason) => {
analytics.track('ota_rollback', { reason });
});
return unsubscribe;
}, []);
Version Changes
import { onVersionChanged } from '@swiftpatch/react-native';
useEffect(() => {
const unsubscribe = onVersionChanged((reason) => {
analytics.track('ota_version_changed', { reason });
});
return unsubscribe;
}, []);
All Native Events
import { onNativeEvent } from '@swiftpatch/react-native';
useEffect(() => {
const unsubscribe = onNativeEvent((event) => {
console.log('Native event:', JSON.stringify(event));
});
return unsubscribe;
}, []);
Always return the unsubscribe function from useEffect to clean up listeners.
Event Polling
The SDK also polls the native event queue to ensure no events are lost. This runs automatically inside SwiftPatchProvider.
Adaptive Backoff
Polling uses adaptive backoff (gradually increasing the time between checks when there is no new activity):
| Tier | Interval | Condition |
|---|---|---|
| Active | 3s | 0-2 empty polls |
| Cooling | 6s | 3-9 empty polls |
| Idle | 15s | 10-19 empty polls |
| Deep idle | 60s | 20+ empty polls |
Any received event resets to the Active tier.
Background Behavior
Polling pauses when the app goes to the background and resumes when it returns. This prevents unnecessary battery and network usage.
Polling Cycle
- JS calls
popEvents()to retrieve queued native events - Events are processed and dispatched to listeners
- Events are sent to the server at
/sdk/log-bulk-events - Acknowledged events are cleared via
acknowledgeEvents()
Analytics Integration
Forward OTA events to your analytics provider:
import { onRollback, onNativeEvent } from '@swiftpatch/react-native';
useEffect(() => {
const subs = [
onRollback((reason) => {
analytics.track('ota_rollback', { reason });
}),
onNativeEvent((event) => {
analytics.track('swiftpatch_event', event);
}),
];
return () => subs.forEach(unsub => unsub());
}, []);
Download Progress via Hook
For UI display, use the useSwiftPatch hook instead -- it provides downloadProgress as reactive state:
import { useSwiftPatch, UpdateStatus } from '@swiftpatch/react-native';
function ProgressBar() {
const { status, downloadProgress } = useSwiftPatch();
if (status !== UpdateStatus.DOWNLOADING || !downloadProgress) return null;
return (
<View>
<Text>{downloadProgress.percentage}%</Text>
<Text>{downloadProgress.downloadedBytes} / {downloadProgress.totalBytes} bytes</Text>
</View>
);
}
For most UI use cases, the useSwiftPatch hook is easier than raw event subscriptions. Use native subscriptions for analytics and logging.