Skip to content

Commit

Permalink
Merge branch 'main' into chore/remove-deprecated-background-package
Browse files Browse the repository at this point in the history
  • Loading branch information
Brazol authored Sep 19, 2024
2 parents 870fcfd + ba031c0 commit 00cb2ba
Show file tree
Hide file tree
Showing 20 changed files with 323 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
slug: /participant-sorting
title: Participant
title: Participant Sorting
sidebar_position: 9
---

Expand Down
5 changes: 0 additions & 5 deletions docusaurus/docs/Flutter/05-advanced/02-ringing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ allows you to add an immersive calling experience to your application.

Ringing requires push/VoIP notifications to be sent to your device. Stream Video sends push/VoIP notifications to members that have at least one registered device.

Push notifications are sent in the following scenarios:
- you create a call with the `ring` value set to true. In this case, a notification that shows a ringing screen is sent.
- you create a call with the `notify` value set to true. In this case, a regular push notification is sent.
- you haven't answered a call. In this case, a missed call notification is sent (regular push notification).

To receive push notifications from Stream Video, you'll need to:

1. Configure your push notification provider on the Stream Dashboard.
Expand Down
2 changes: 1 addition & 1 deletion docusaurus/docs/Flutter/05-advanced/03-screen-sharing.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
id: screen_sharing
sidebar_position: 3
sidebar_position: 4
title: Screen Sharing
---

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
id: picture_in_picture
sidebar_position: 4
sidebar_position: 5
title: Picture in Picture (PiP)
---

Expand Down
2 changes: 1 addition & 1 deletion docusaurus/docs/Flutter/05-advanced/05-call-recording.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
slug: /recording
sidebar_position: 5
sidebar_position: 6
title: Recording
---
A key feature of modern communication tools is the ability to quickly and easily record calls. This functionality is used for everything from quality assurance and training to legal compliance or simply as a matter of convenience for keeping track of conversations and later reviewing them.
Expand Down
2 changes: 1 addition & 1 deletion docusaurus/docs/Flutter/05-advanced/06-screenshots.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
slug: /screenshots
sidebar_position: 6
sidebar_position: 7
title: Screenshots
---
You can take a picture of a VideoTrack at highest possible resolution. This can be useful for example if you want to take a screenshot of a screenshare at full resolution.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Background modes
slug: /background-modes
sidebar_position: 7
sidebar_position: 8
description: How to keep the call alive in the background
---

Expand Down
79 changes: 79 additions & 0 deletions docusaurus/docs/Flutter/05-advanced/08-custom-data.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
title: Custom Data
slug: /custom-data
sidebar_position: 9
description: Learn how to add and read custom data in the Stream Video Flutter SDK.
---

Custom data is additional information that can be added to the default data of Stream. It is a dictionary of key-value pairs that can be attached to users, events, and pretty much almost every domain model in the Stream SDK.

In the SDK, custom data is represented by the `Map<String, Object>`. This means that the key must be a string and the value can be any object.

## Adding Custom Data

Adding extra data can be done through the Server-Side SDKs or through the Client SDKs. In the Flutter Stream Video SDK, you can add extra data when creating/updating a call, updating a user and sending event or reaction.

###### Example of updating the call custom data

```dart
call.update(custom: {'mycustomfield': 'mycustomvalue'});
```

###### Example of sending a reaction with custom data

```dart
call.sendReaction(
reactionType: 'raise-hand',
emojiCode: ':smile:',
custom: {'mycustomfield': 'mycustomvalue'},
);
```

###### Example of sending a custom event with custom data

```dart
call.sendCustomEvent(
eventType: 'my-custom-event',
custom: {'mycustomfield': 'mycustomvalue'},
);
```

###### Example of updating the user custom data while initializing the StreamVideo

```dart
StreamVideo(
apiKey,
user: User.regular(userId: 'userId', extraData: {'mycustomfield': 'mycustomvalue'}),
userToken: token,
);
```

## Reading Custom Data
Reading the custom data is as simple as accessing the `custom` field of the object. For example, to read the custom data of a reaction, you can access the `custom` field of the reaction event object.

```dart
call.callEvents.listen((event) {
if (event is StreamCallReactionEvent) {
final customData = event.custom;
}
});
```

For `Call` object the custom data is stored in call metadata that can be accessed when calling `getOrCreate()` or `get()` method.

```dart
final result = await call.getOrCreate();
final customData = result.fold(
success: (success) => success.data.data.metadata.details.custom,
failure: (_) => null,
);
//or
final result = await call.get();
final customData = result.fold(
success: (success) => success.data.metadata.details.custom,
failure: (_) => null,
);
```
163 changes: 163 additions & 0 deletions docusaurus/docs/Flutter/05-advanced/09-push-notifications.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
title: Push Notifications
slug: /push-notifications
sidebar_position: 3
description: Learn how to enable push notifications in the Stream Video Flutter SDK.
---

Apart from the VoIP notifications for call ringing features, Stream Video Flutter SDK also supports standard push notifications. This guide will show you how to enable push notifications in your Flutter app using the Stream Video SDK.

Push notifications are sent in the following scenarios:
- you create a call with the `ring` value set to true. In this case, a notification that shows a ringing screen is sent. (covered in the [ringing documentation](https://getstream.io/video/docs/flutter/advanced/ringing_and_callkit/))
- you create a call with the `notify` value set to true. In this case, a regular push notification is sent.
- you haven't answered a call. In this case, a missed call notification is sent (regular push notification).

## Android and Firebase Cloud Messaging (FCM)

For FCM the steps taken in [ringing documentation](https://getstream.io/video/docs/flutter/advanced/ringing_and_callkit/) are enough and will also handle standard push notifications.

In case of missed call the notification will be shown using [flutter_callkit_incoming](https://pub.dev/packages/flutter_callkit_incoming) package. It can be configured by `pushParams` when initializing `StreamVideo`:

```dart
StreamVideo(
apiKey,
user: user,
pushNotificationManagerProvider: StreamVideoPushNotificationManager.create(
iosPushProvider: const StreamVideoPushProvider.apn(
name: 'apn',
),
androidPushProvider: const StreamVideoPushProvider.firebase(
name: 'firebase',
),
pushParams: const StreamVideoPushParams(
appName: kAppName,
ios: IOSParams(iconName: 'IconMask'),
missedCallNotification: NotificationParams(
showNotification: true,
subtitle: 'Missed Call',
callbackText: 'Call Back',
)
),
),
);
```

If you want to handle missed call notification differently or handle the notification about incoming call (when `notify` is set to true) use the existing `_handleRemoteMessage()` method (see [ringing documentation](https://getstream.io/video/docs/flutter/advanced/ringing_and_callkit/)):

```dart
Future<bool> _handleRemoteMessage(RemoteMessage message) async {
final payload = message.data;
final sender = payload['sender'] as String?;
final type = payload['type'] as String?;
if (sender == 'stream.video' && type == 'call.notification') {
final callCid = payload['call_cid'] as String?;
// Show notification, for example using `flutter_local_notifications` package
}
final streamVideo = locator.get<StreamVideo>();
return streamVideo.handleVoipPushNotification(
message.data,
handleMissedCall: false, //<-- Add this flag if you dont want a default missed call notification handling
);
}
```

## iOS and Apple Push Notification Service (APNs)

For APNs the standard push notifications have to be handled separately of VoIP notifications. When APN push provider is registered for iOS, both VoIP and standard push notifications are send using APN by Stream Video SDK.

### Registering APN device token

First you need to register APN device token as it is separate from the VoIP token (registered out-of-the-box by the Stream Video SDK). To do this just set `registerApnDeviceToken` to true when initializing `StreamVideo` instance:

```dart
StreamVideo(
apiKey,
user: user,
pushNotificationManagerProvider: StreamVideoPushNotificationManager.create(
iosPushProvider: const StreamVideoPushProvider.apn(
name: 'flutter-apn',
),
androidPushProvider: const StreamVideoPushProvider.firebase(
name: 'flutter-firebase',
),
pushParams: const StreamVideoPushParams(
appName: kAppName,
ios: StreamIOSParams(iconName: 'IconMask'),
),
registerApnDeviceToken: true, // <--- Add this line
),
);
```

### Handling standard push notifications

Next, you need to handle the push notifications in your app.

To do this, you need to add the following code to your `AppDelegate.swift` file:

```swift
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)

// Register for push notifications.
StreamVideoPKDelegateManager.shared.registerForPushNotifications() // <--- Add will only handle VoIP notifications
UNUserNotificationCenter.current().delegate = self // <--- Add this line to handle standard push notifications

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// This method will be called when notification is received
override func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let streamDict = notification.request.content.userInfo["stream"] as? [String: Any]
if(streamDict?["sender"] as? String != "stream.video") {
return completionHandler([])
}

if #available(iOS 14.0, *) {
completionHandler([.list, .banner, .sound])
} else {
completionHandler([.alert])
}
}
}
```

If you want to handle the notification tap event, for example to navigate to the call screen when you `notify` about it, you can add the following code to your `AppDelegate.swift` file:

```swift
// This method will be called when notification is tapped
override func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {

let streamDict = response.notification.request.content.userInfo["stream"] as? [String: Any]
if(streamDict?["sender"] as? String != "stream.video") {
return;
}

if(streamDict?["type"] as? String == "call.notification") {
let callCid = streamDict?["call_cid"] as? String
print("Call notification received with call cid: \(callCid)")
//Navigate to call, for example implementing method channel
}

completionHandler()
}
```

### Push notification permission

Remember, that in order to receive push notifications, you need to ask the user for relevant permission. One way of doing it is using [permission_handler](https://pub.dev/packages/permission_handler) plugin.

```dart
Permission.notification.request();
```
12 changes: 12 additions & 0 deletions dogfooding/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,16 @@ post_install do |installer|
end
end
end

installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_CAMERA=1',
'PERMISSION_MICROPHONE=1',
'PERMISSION_NOTIFICATIONS=1',
]

end
end
end
19 changes: 19 additions & 0 deletions dogfooding/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,26 @@ import stream_video_push_notification

// Register for push notifications.
StreamVideoPKDelegateManager.shared.registerForPushNotifications()
UNUserNotificationCenter.current().delegate = self

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// This method will be called when notification is received
override func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let streamDict = notification.request.content.userInfo["stream"] as? [String: Any]
if(streamDict?["sender"] as? String != "stream.video") {
return completionHandler([])
}

if #available(iOS 14.0, *) {
completionHandler([.list, .banner, .sound])
} else {
completionHandler([.alert])
}
}


}
2 changes: 2 additions & 0 deletions dogfooding/lib/di/injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Future<void> _backgroundVoipCallHandler() async {
appName: kAppName,
ios: IOSParams(iconName: 'IconMask'),
),
registerApnDeviceToken: true,
),
);
}
Expand Down Expand Up @@ -207,6 +208,7 @@ StreamVideo _initStreamVideo(
ios: IOSParams(iconName: 'IconMask'),
),
backgroundVoipCallHandler: _backgroundVoipCallHandler,
registerApnDeviceToken: true,
),
);

Expand Down
8 changes: 8 additions & 0 deletions packages/stream_video/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 0.5.4

🐞 Fixed
* Fixed an issue where active call foreground service was recreated after being stopped when ringing call was declined and in-app incoming screen was displayed.

🚧 Breaking changes
* The regular push notification handling has been removed from iOS, providing more control over the implementation. VoIP push notifications will continue to be handled as before. For more details, refer to the documentation.

## 0.5.3

🐞 Fixed
Expand Down
7 changes: 5 additions & 2 deletions packages/stream_video/lib/src/stream_video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,10 @@ class StreamVideo extends Disposable {
/// Handle incoming VoIP push notifications.
///
/// Returns `true` if the notification was handled, `false` otherwise.
Future<bool> handleVoipPushNotification(Map<String, dynamic> payload) async {
Future<bool> handleVoipPushNotification(
Map<String, dynamic> payload, {
bool handleMissedCall = true,
}) async {
_logger.d(() => '[handleVoipPushNotification] payload: $payload');
final manager = pushNotificationManager;
if (manager == null) {
Expand Down Expand Up @@ -716,7 +719,7 @@ class StreamVideo extends Disposable {
final hasVideo = payload['video'] as String?;

final type = payload['type'] as String?;
if (type == 'call.missed') {
if (handleMissedCall && type == 'call.missed') {
unawaited(
manager.showMissedCall(
uuid: callUUID,
Expand Down
Loading

0 comments on commit 00cb2ba

Please sign in to comment.