Skip to main content

Overview

Ant Media Server supports push notifications to notify mobile app users about stream events in real-time. This feature integrates with:
  • Firebase Cloud Messaging (FCM) - For Android and iOS apps
  • Apple Push Notification (APN) - For iOS apps
Use cases include:
  • Notify users when a streamer goes live
  • Alert viewers about stream status changes
  • Send custom messages during broadcasts
  • Trigger app actions from server events

Architecture

The push notification system uses a service interface pattern:
public interface IPushNotificationService {
    static final String BEAN_NAME = "push.notification.service";
    
    public enum PushNotificationServiceTypes {
        FIREBASE_CLOUD_MESSAGING("fcm"),
        APPLE_PUSH_NOTIFICATION("apn");
        
        private String name;
        
        PushNotificationServiceTypes(String name) {
            this.name = name;
        }
        
        @Override
        public String toString() {
            return this.name;
        }
    }
    
    /**
     * Send notification to a topic
     */
    Result sendNotification(String topic, JSONObject jsonMessage, String serviceName);
    
    /**
     * Send notification to both FCM and APN
     */
    Result sendNotification(String topic, JSONObject jsonMessage);
    
    /**
     * Send notification to specific subscriber IDs
     */
    Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage);
    
    /**
     * Send notification to specific subscribers via specific service
     */
    Result sendNotification(List<String> subscriberIds, JSONObject jsonMessage, String serviceName);
}

Firebase Cloud Messaging (FCM) Setup

Prerequisites

1

Create Firebase Project

  1. Go to Firebase Console
  2. Click Add Project
  3. Enter project name and follow setup wizard
2

Get Service Account Key

  1. Navigate to Project Settings → Service Accounts
  2. Click Generate New Private Key
  3. Save the JSON file securely
3

Upload to Ant Media Server

Upload the service account JSON file to:
/usr/local/antmedia/webapps/LiveApp/WEB-INF/firebase-service-account.json

Configuration

Enable FCM in application settings:
{
  "pushNotificationEnabled": true,
  "firebaseServiceAccountFile": "/usr/local/antmedia/webapps/LiveApp/WEB-INF/firebase-service-account.json"
}

Apple Push Notification (APN) Setup

Prerequisites

1

Create APN Key

  1. Go to Apple Developer Portal
  2. Click + to create a new key
  3. Enable Apple Push Notifications service (APNs)
  4. Download the .p8 key file
2

Note Your Credentials

You’ll need:
  • Key ID - From the downloaded key filename
  • Team ID - From Apple Developer account
  • Bundle ID - Your iOS app’s bundle identifier
3

Upload Key to Server

/usr/local/antmedia/webapps/LiveApp/WEB-INF/apn-key.p8

Configuration

{
  "apnEnabled": true,
  "apnKeyPath": "/usr/local/antmedia/webapps/LiveApp/WEB-INF/apn-key.p8",
  "apnKeyId": "YOUR_KEY_ID",
  "apnTeamId": "YOUR_TEAM_ID",
  "apnBundleId": "com.yourcompany.yourapp",
  "apnProduction": false
}
Set apnProduction to true for production apps, false for development/sandbox.

Sending Notifications

Via REST API

# Send to all subscribers of a topic
curl -X POST "http://localhost:5080/LiveApp/rest/v2/push-notification/send" \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "stream-updates",
    "message": {
      "title": "Stream Started",
      "body": "Your favorite streamer is now live!",
      "streamId": "stream123"
    },
    "service": "fcm"
  }'

Programmatic Usage

import io.antmedia.pushnotification.IPushNotificationService;
import org.json.simple.JSONObject;

public class NotificationExample {
    
    public void notifyStreamStart(String streamId, String streamerName) {
        IPushNotificationService pushService = 
            (IPushNotificationService) context.getBean(
                IPushNotificationService.BEAN_NAME);
        
        JSONObject message = new JSONObject();
        message.put("title", "Stream Started");
        message.put("body", streamerName + " is now live!");
        message.put("streamId", streamId);
        message.put("action", "watch-stream");
        
        // Send to topic
        Result result = pushService.sendNotification(
            "stream-" + streamId, 
            message
        );
        
        if (result.isSuccess()) {
            logger.info("Notification sent successfully");
        }
    }
}

Message Format

Standard Fields

FieldTypeDescriptionRequired
titlestringNotification titleYes
bodystringNotification messageYes
iconstringIcon URL or nameNo
imagestringLarge image URLNo
soundstringNotification soundNo
badgeintegerBadge count (iOS)No

Custom Data

Add any custom fields for your app logic:
{
  "title": "New Comment",
  "body": "Someone commented on your stream",
  "streamId": "stream123",
  "commentId": "comment456",
  "action": "view-comment",
  "timestamp": 1709566230000
}

Topic Management

Subscribe Users to Topics

Manage topic subscriptions from your mobile app:
FirebaseMessaging.getInstance().subscribeToTopic("stream-updates")
    .addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            Log.d(TAG, "Subscribed to stream-updates");
        }
    });

Topic Naming Conventions

Organize topics logically:
stream-{streamId}           # Stream-specific notifications
user-{userId}               # User-specific notifications  
live-alerts                 # All live stream alerts
category-{category}         # Category-based notifications
language-{lang}             # Language-specific content

Integration with Stream Events

Automatic Notifications

Trigger notifications on stream events using webhooks:
{
  "listenerHookURL": "http://localhost:3000/webhook",
  "pushNotificationEnabled": true
}

Supported Events

EventAction ValueUse Case
Stream StartedliveStreamStartedNotify followers
Stream EndedliveStreamEndedUpdate watch history
Recording ReadyvodReadyNotify about available replay
Viewer Milestone-”100 viewers watching”
Comment Added-Notify streamer of comments

Mobile App Implementation

Android (FCM)

import com.google.firebase.messaging.FirebaseMessaging

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Get FCM token
        FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
            if (task.isSuccessful) {
                val token = task.result
                // Send token to your server for subscriber management
                registerDevice(token)
            }
        }
        
        // Subscribe to topics
        FirebaseMessaging.getInstance().subscribeToTopic("stream-updates")
    }
    
    private fun registerDevice(token: String) {
        // Send to AMS or your backend
        // Store token with user ID for targeted notifications
    }
}

iOS (APN)

import UIKit
import UserNotifications
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication,
                    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Configure Firebase
        FirebaseApp.configure()
        
        // Request notification permissions
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
        }
        
        return true
    }
    
    func application(_ application: UIApplication,
                    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Send token to server
        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        registerDevice(token: token)
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                               didReceive response: UNNotificationResponse,
                               withCompletionHandler completionHandler: @escaping () -> Void) {
        
        let userInfo = response.notification.request.content.userInfo
        
        if let streamId = userInfo["streamId"] as? String,
           let action = userInfo["action"] as? String {
            
            switch action {
            case "watch-stream":
                openStream(streamId: streamId)
            default:
                break
            }
        }
        
        completionHandler()
    }
}

Testing Notifications

Test FCM

curl -X POST "http://localhost:5080/LiveApp/rest/v2/push-notification/send" \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "test",
    "message": {
      "title": "Test Notification",
      "body": "This is a test"
    },
    "service": "fcm"
  }'

Test APN

curl -X POST "http://localhost:5080/LiveApp/rest/v2/push-notification/send" \
  -H "Content-Type: application/json" \
  -d '{
    "subscriberIds": ["YOUR_DEVICE_TOKEN"],
    "message": {
      "title": "Test APN",
      "body": "Testing Apple Push Notification"
    },
    "service": "apn"
  }'

Troubleshooting

Check:
  • Service account JSON file is correct and in right location
  • Device/app is subscribed to the topic
  • FCM token is valid and not expired
  • App has notification permissions
Debug:
# Check AMS logs
tail -f /usr/local/antmedia/log/ant-media-server.log | grep -i "push"

# Verify Firebase project settings in JSON file
cat /usr/local/antmedia/webapps/LiveApp/WEB-INF/firebase-service-account.json
Common issues:
  • Using production key with development app (or vice versa)
  • Wrong bundle ID
  • Invalid .p8 key file
  • Device token format incorrect
Solutions:
  • Match apnProduction setting with app build type
  • Verify bundle ID matches app’s bundle identifier
  • Regenerate .p8 key if necessary
  • Ensure device token is properly formatted (no spaces/special chars)
Causes:
  • Network issues between AMS and FCM/APN servers
  • Rate limiting by FCM/APN
  • Server overload
Solutions:
  • Check server internet connectivity
  • Implement batching for bulk notifications
  • Monitor notification send rates

Best Practices

Personalize Messages

Use subscriber-specific data to make notifications relevant. Include streamer names, custom actions, etc.

Rate Limiting

Don’t spam users. Implement throttling for frequent events like viewer count updates.

Action Buttons

Include actionable data in notifications so users can directly interact (watch stream, reply, etc.).

Analytics

Track notification delivery rates and user engagement to optimize messaging strategy.

Build docs developers (and LLMs) love