Setup

We support the following providers:

We ship an individual artifact for each of these to make client-side integration with their service quick and simple. See their individual documentation pages linked above for details. You need to add the list of PushDeviceGenerator you want to use:

val notificationConfig = NotificationConfig(
    pushDeviceGenerators = listOf(
        // PushDeviceGenerator
    ),
)

StreamVideoBuilder(
    context = context,
    user = user,
    token = token,
    apiKey = apiKey,
    notificationConfig = notificationConfig,
).build()

Customizing Push Notifications

If you want, you can also customize how the push notifications work.

You can customize push notifications in the following ways:

  • Declaring IntentFilter: Lets you customize activities that will be invoked when the Push Notification is handled by the SDK
  • NotificationHandler: Lets you fully customize how notifications are shown and dismissed
  • Extending our default NotificationHandler: Lets you partially customize the behavior or Push Notification received, but reusing some part of our default implementation.

Declaring IntentFilter in your Android Manifest

It is the easier way to integrate Stream Video Push Notification in your application. You only need to create the Activity/Activities will be called when the Push Notification is handled by the SDK and declare an IntentFilter with the actions we provide. The different actions we provide are:

  • io.getstream.video.android.action.INCOMING_CALL: Action used to process an incoming call. The activity that handles this action should show options to accept/reject the call. You can use our RigningCallContent component to build your screen. This screen can be shown when the device is locked, by adding some arguments on the manifest.
  • io.getstream.video.android.action.OUTGOING_CALL: Action used to process an outgoing call. The activity that handles this action should show options to cancel the call. You can use our RigningCallContent component to build your screen.
  • io.getstream.video.android.action.ACCEPT_CALL: Action used to accept an incoming call. The activity that handles this action should accept the call and show the call screen. You can use our CallContent component to build your screen.
  • io.getstream.video.android.action.LIVE_CALL: Action used to go into a live call. The activity that handles this action should show the live call screen. You can use our CallContent component to build your screen.
  • io.getstream.video.android.action.ONGOING_CALL: Action used to get back into already running call. The activity that handles this action should show the call screen. You can use our CallContent component to build your screen. These actions need to be included on the AndroidManifest while you declare your activities:
<manifest>
    <application>
        <activity
            android:name=".IncomingCallActivity"
            android:exported="false"
            android:showOnLockScreen="true"
            android:showWhenLocked="true">
            <intent-filter android:priority="1">
                <action android:name="io.getstream.video.android.action.INCOMING_CALL" />
            </intent-filter>
        </activity>
        <activity
            android:name=".OutgoingCallActivity"
            android:exported="false"
            android:showOnLockScreen="true"
            android:showWhenLocked="true">
            <intent-filter android:priority="1">
                <action android:name="io.getstream.video.android.action.OUTGOING_CALL" />
            </intent-filter>
        </activity>

        <activity
            android:name=".AcceptCallActivity"
            android:exported="false">
            <intent-filter android:priority="1">
                <action android:name="io.getstream.video.android.action.ACCEPT_CALL" />
            </intent-filter>
        </activity>

        <activity
            android:name=".LiveCallActivity"
            android:exported="false">
            <intent-filter android:priority="1">
                <action android:name="io.getstream.video.android.action.LIVE_CALL" />
            </intent-filter>
        </activity>
        
        <activity
            android:name=".CallActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter android:priority="1">
                <action android:name="io.getstream.video.android.action.ONGOING_CALL" />
            </intent-filter>
        </activity>
    </application>
</manifest>

You can handle multiple IntentFilter within a single activity if you prefer.

Once you have declared your activities in the manifest including the IntentFilter for the actions defined previously, your activities will be started when a Push Notification arrives to the device. The Intent that your Activity will receive contains the StreamCallId related with the call you need to handle. To obtain the StreamCallId we provide an extension fuction that you can use:

class IncomingCallActivity : AppCompatActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val streamCallId = intent.streamCallId(NotificationHandler.INTENT_EXTRA_CALL_CID)
        [...]
    }
}

Customize Notification Handler

The SDK lets you define the theming and behavior of the notification UI that users see after they receive a push notification. To do this, implement the NotificationHandler interface and show your own notification.

class MyNotificationHandler(private val context: Context) : NotificationHandler {
    private val notificationManager: NotificationManager by lazy {
        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    }

    // Called when a Ringing Call arrives. (outgoing or incoming)
    override fun onRingingCall(callId: StreamCallId, callDisplayName: String) {
        val notification = NotificationCompat.Builder(context, notificationChannelId)
            ... // Configure your own notification
            .build()
        notificationManager.notify(notificationId, notification)
    }

    // Called when a Live Call arrives.
    override fun onLiveCall(callId: StreamCallId, callDisplayName: String) {
        val notification = NotificationCompat.Builder(context, notificationChannelId)
            ... // Configure your own notification
            .build()
        notificationManager.notify(notificationId, notification)
    }
    
    // Called when the foreground service is started, to supply the notification
    override fun getOngoingCallNotification(callId: StreamCallId): Notification? {
        val notification = NotificationCompat.Builder(context, notificationChannelId)
        ... // Configure your own notification
        .build()
        return notification
    }

}

Finally, pass as the NotificationHandler implementation to the StreamVideoBuilder when initializing the Stream Android SDK:

val notificationHandler = MyNotificationHandler(context)
val notificationConfig = NotificationConfig(
    pushDeviceGenerators = listOf(
        // PushDeviceGenerator
    ),
    notificationHandler = notificationHandler
)

StreamVideoBuilder(
    context = context,
    user = user,
    token = token,
    apiKey = apiKey,
    notificationConfig = notificationConfig,
).build()

Extending our default NotificationHandler

Stream Video SDK use a default implementation of NotificationHandler that search into the application manifest for activities that declare the previous IntentFilter we detailed on a previous section. By now, we support three different types of push notifications and may be the case that is interesting to maintain the default behavior of the notifications but modify one of the types. If it is your use-case you can extend the open class DefaultNotificationHandler and override the behavior of the desired type of notifications.

class MyNotificationHandler(application: Application) : DefaultNotificationHandler(application) {

    // Override this method if you want a custom behavior for Ringing call notifications
    override fun onRingingCall(callId: StreamCallId, callDisplayName: String) {
        [...]
    }

    // Override this method if you want a custom behavior for default notifications
    override fun onNotification(callId: StreamCallId, callDisplayName: String) {
        [...]
    }

    // Override this method if you want a custom behavior for Live Call notifications
    override fun onLiveCall(callId: StreamCallId, callDisplayName: String) {
        [...]
    }

    // Override this method if you want a custom notification when there is an ongoing call
    override fun getOngoingCallNotification(callId: StreamCallId): Notification? {
        [...]
    }
}

Handling Push Notification Permissions

Starting on Android API level 33, all apps need to request permissions to be able to post notifications to the user. When you integrate Stream Push Notification, our SDK will request permission to post notification whenever it is needed, but maybe it is not the best moment within your app to ask your customer for this permission. If you want to configure this behavior, you can configure it within the NotificationConfig class.

val notificationConfig = NotificationConfig(
    pushDeviceGenerators = listOf(
        // PushDeviceGenerator
    ),
    notificationHandler = notificationHandler,
    // This lambda will be call to check if permission needs to be requested within SDK or not.
    // Returning `true` the SDK will request it whenever the permission is needed.
    requestPermissionOnAppLaunch = { true }
)
© Getstream.io, Inc. All Rights Reserved.