Documentation Index
Fetch the complete documentation index at: https://learn.social.plus/llms.txt
Use this file to discover all available pages before exploring further.
Notification Troubleshooting
Common issues and solutions when implementing push notifications and stream event handling in your video streaming application.
Common Issues
Push Notifications Not Received
Symptoms:
- Users not receiving stream start notifications
- Missing viewer activity alerts
- Recording completion notifications not delivered
Possible Causes & Solutions:
-
Platform Configuration Issues
// Verify platform setup
// iOS: Check APNs certificate configuration
// Android: Verify FCM configuration
// Web: Ensure service worker is registered
// Test notification delivery
await VideoNotifications.test({
event: 'stream.started',
targetPlatform: 'ios', // or 'android', 'web'
deviceToken: 'user-device-token'
});
-
Permission Issues
// Check notification permissions
const permission = await VideoNotifications.checkPermission();
if (permission !== 'granted') {
// Request permission at appropriate time
const result = await VideoNotifications.requestPermission();
console.log('Permission result:', result);
}
-
Device Token Registration
// Ensure device token is properly registered
const deviceToken = await VideoNotifications.getDeviceToken();
if (!deviceToken) {
console.error('Device token not available');
// Re-register for notifications
await VideoNotifications.register();
}
Stream Events Not Firing
Symptoms:
- Stream start/end events not triggered
- Viewer count updates missing
- Chat messages not received
Troubleshooting Steps:
-
Check Event Listener Registration
// Verify event listeners are properly set up
VideoStreamManager.getInstance().listEventListeners();
// Re-register listeners if needed
videoStreamManager.on('stream.started', handleStreamStarted);
videoStreamManager.on('viewer.joined', handleViewerJoined);
-
Verify Connection Status
// Check connection to stream events
const connectionStatus = await VideoStreamManager.getConnectionStatus();
if (connectionStatus !== 'connected') {
// Reconnect to event stream
await VideoStreamManager.reconnect();
}
-
Debug Event Flow
// Enable debug mode
VideoStreamManager.setDebugMode(true);
// Monitor all events
VideoStreamManager.on('*', (eventType, data) => {
console.log('Event received:', eventType, data);
});
High Event Volume Issues
Symptoms:
- UI freezing during high viewer activity
- Memory usage increasing over time
- Delayed event processing
Solutions:
-
Implement Event Throttling
// Throttle high-frequency events
const throttledHandler = throttle(handleViewerActivity, 1000);
videoStreamManager.on('viewer.joined', throttledHandler);
-
Use Event Batching
// Batch similar events
const eventBatcher = new EventBatcher(5000); // 5 second batch window
eventBatcher.addEvent('viewer.joined', viewerData);
eventBatcher.addEvent('viewer.left', viewerData);
eventBatcher.onBatch((events) => {
// Process batched events
processBatchedViewerEvents(events);
});
-
Selective Event Subscription
// Only subscribe to necessary events
videoStreamManager.configure({
events: {
'stream.started': true,
'stream.ended': true,
'viewer.joined': false, // Disable if not needed
'viewer.milestone': true,
'chat.message': true
}
});
Webhook Delivery Failures
Symptoms:
- Webhook endpoints not receiving events
- Delayed webhook delivery
- Missing webhook payloads
Debugging Steps:
-
Verify Webhook Configuration
// Check webhook endpoint configuration
const webhookConfig = await VideoNotifications.getWebhookConfig();
console.log('Webhook config:', webhookConfig);
// Test webhook endpoint
await VideoNotifications.testWebhook({
url: 'https://your-server.com/webhooks',
event: 'stream.started',
testData: { streamId: 'test-123' }
});
-
Check Endpoint Accessibility
# Test webhook endpoint accessibility
curl -X POST https://your-server.com/webhooks \
-H "Content-Type: application/json" \
-d '{"test": true}'
-
Implement Webhook Retry Logic
// Server-side webhook handler with retry
app.post('/webhooks', async (req, res) => {
try {
await processWebhookEvent(req.body);
res.status(200).send('OK');
} catch (error) {
console.error('Webhook processing failed:', error);
// Return 500 to trigger retry
res.status(500).send('Processing failed');
}
});
iOS Issues
APNs Certificate Problems:
// Check APNs configuration
#if DEBUG
let apnsEnvironment = "development"
#else
let apnsEnvironment = "production"
#endif
print("APNs Environment: \(apnsEnvironment)")
// Verify device token format
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("Device Token: \(tokenString)")
// Register with social.plus Video SDK
VideoNotificationManager.shared.registerDevice(token: tokenString)
}
Silent Notification Issues:
// Handle silent notifications for stream events
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let streamEvent = userInfo["stream_event"] as? String {
// Process stream event silently
VideoStreamManager.shared.processBackgroundEvent(userInfo)
completionHandler(.newData)
} else {
completionHandler(.noData)
}
}
Android Issues
FCM Configuration:
// Check FCM configuration
class VideoFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d("FCM", "New token: $token")
// Register with social.plus Video SDK
VideoNotificationManager.getInstance().registerDevice(token)
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
Log.d("FCM", "Message received from: ${remoteMessage.from}")
Log.d("FCM", "Message data: ${remoteMessage.data}")
// Process video notification
VideoNotificationHandler.processMessage(remoteMessage)
}
}
Background Processing:
// Handle background video events
class VideoBackgroundProcessor : JobIntentService() {
override fun onHandleWork(intent: Intent) {
val eventType = intent.getStringExtra("event_type")
val streamId = intent.getStringExtra("stream_id")
when (eventType) {
"stream.started" -> handleStreamStarted(streamId)
"recording.ready" -> handleRecordingReady(intent.extras)
}
}
}
Web Issues
Service Worker Registration:
// Check service worker registration
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered:', registration);
// Check if already subscribed
return registration.pushManager.getSubscription();
})
.then(subscription => {
if (!subscription) {
// Subscribe to push notifications
return subscribeUserToPush();
}
console.log('Already subscribed:', subscription);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
}
VAPID Key Issues:
// Verify VAPID key configuration
function subscribeUserToPush() {
const applicationServerKey = urlBase64ToUint8Array(VAPID_PUBLIC_KEY);
return navigator.serviceWorker.ready
.then(registration => {
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
});
})
.then(subscription => {
console.log('Push subscription:', subscription);
// Send subscription to server
return sendSubscriptionToServer(subscription);
})
.catch(error => {
console.error('Failed to subscribe user:', error);
});
}
Memory Management
// Prevent memory leaks from event listeners
class EventListenerManager {
private listeners: Map<string, Function[]> = new Map();
addListener(event: string, callback: Function): () => void {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event)!.push(callback);
// Return cleanup function
return () => {
const callbacks = this.listeners.get(event);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
};
}
cleanup(): void {
this.listeners.clear();
}
}
Event Queue Management
// Manage event queue to prevent overflow
class EventQueue {
private queue: StreamEvent[] = [];
private processing = false;
private maxQueueSize = 1000;
addEvent(event: StreamEvent): void {
if (this.queue.length >= this.maxQueueSize) {
// Remove oldest events
this.queue.splice(0, this.queue.length - this.maxQueueSize + 1);
}
this.queue.push(event);
this.processQueue();
}
private async processQueue(): Promise<void> {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
while (this.queue.length > 0) {
const event = this.queue.shift()!;
try {
await this.processEvent(event);
} catch (error) {
console.error('Event processing failed:', error);
}
}
this.processing = false;
}
}
Testing & Debugging
Debug Mode
// Enable comprehensive debugging
VideoStreamManager.configure({
debug: {
enabled: true,
logLevel: 'verbose',
logEvents: true,
logNotifications: true,
logWebhooks: true
}
});
// Custom debug logger
VideoStreamManager.setDebugLogger((level, message, data) => {
console.log(`[VIDEO-${level.toUpperCase()}]`, message, data);
// Send to analytics if needed
if (level === 'error') {
Analytics.track('video_debug_error', { message, data });
}
});
Test Utilities
// Test notification delivery
async function testNotificationFlow() {
const testCases = [
{ event: 'stream.started', platform: 'ios' },
{ event: 'viewer.milestone', platform: 'android' },
{ event: 'recording.ready', platform: 'web' }
];
for (const testCase of testCases) {
try {
const result = await VideoNotifications.test(testCase);
console.log(`✅ ${testCase.event} on ${testCase.platform}:`, result);
} catch (error) {
console.error(`❌ ${testCase.event} on ${testCase.platform}:`, error);
}
}
}
Support & Resources
Getting Help
- Check Debug Logs - Enable debug mode for detailed logging
- Test Components - Use built-in test utilities to isolate issues
- Monitor Analytics - Track notification delivery and event processing rates
- Community Support - Visit community.social.plus.co for help
Additional Resources
// Removed deprecated API reference link (file not present). Core concepts above now cover relevant details.
Production Debugging: Be careful with debug mode in production as it can impact performance and expose sensitive information in logs.