diff --git a/packages/stream_video_flutter/CHANGELOG.md b/packages/stream_video_flutter/CHANGELOG.md index e1600a395..960b5285f 100644 --- a/packages/stream_video_flutter/CHANGELOG.md +++ b/packages/stream_video_flutter/CHANGELOG.md @@ -1,3 +1,8 @@ +## Upcoming + +🐞 Fixed +* [iOS/macOS] Fixed crash when VoIP push is received before Flutter fully initializes from the terminated state. + ## 1.2.0 ### ✅ Added diff --git a/packages/stream_video_push_notification/CHANGELOG.md b/packages/stream_video_push_notification/CHANGELOG.md index 9bf7c0963..59435848e 100644 --- a/packages/stream_video_push_notification/CHANGELOG.md +++ b/packages/stream_video_push_notification/CHANGELOG.md @@ -1,3 +1,8 @@ +## Upcoming + +🐞 Fixed +* [iOS/macOS] Fixed crash when VoIP push is received before Flutter fully initializes from the terminated state. + ## 1.2.0 * Sync version with `stream_video_flutter` 1.2.0 diff --git a/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoCallkitManager.swift b/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoCallkitManager.swift index e3641fe65..707e2caec 100644 --- a/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoCallkitManager.swift +++ b/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoCallkitManager.swift @@ -6,9 +6,10 @@ import UIKit @available(iOS 10.0, *) public class StreamVideoCallkitManager: NSObject, CXProviderDelegate { - @objc public private(set) static var sharedInstance: StreamVideoCallkitManager! + @objc public static let shared = StreamVideoCallkitManager() - private var eventHandler: EventCallbackHandler + private var eventHandler: EventCallbackHandler? + private var pendingEvents: [(event: String, body: [String: Any?]?)] = [] private var callController: StreamCallKitCallController @@ -21,25 +22,44 @@ public class StreamVideoCallkitManager: NSObject, CXProviderDelegate { private var isFromPushKit: Bool = false private var silenceEvents: Bool = false - public init( - eventHandler: EventCallbackHandler - ) { - self.eventHandler = eventHandler + private override init() { callController = StreamCallKitCallController() + super.init() + } + + public func setEventHandler(_ handler: EventCallbackHandler) { + self.eventHandler = handler + flushPendingEvents() + } + + private func flushPendingEvents() { + guard let eventHandler = eventHandler else { return } + + for pendingEvent in pendingEvents { + eventHandler.send(pendingEvent.event, pendingEvent.body ?? [:]) + } + + pendingEvents.removeAll() } private func sendEvent(_ event: String, _ body: [String: Any?]?) { if silenceEvents { print(event, " silenced") return - } else { - eventHandler.send(event, body ?? [:]) } + guard let eventHandler = eventHandler else { + pendingEvents.append((event: event, body: body)) + return + } + + eventHandler.send(event, body ?? [:]) } @objc public func sendEventCustom(_ event: String, body: NSDictionary?) { - eventHandler.send(event, body ?? [:]) + // Convert NSDictionary to [String: Any?] for queueing if needed + let bodyDict = body as? [String: Any?] + sendEvent(event, bodyDict) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { diff --git a/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoPushNotificationPlugin.swift b/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoPushNotificationPlugin.swift index 98899b123..1fc967549 100644 --- a/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoPushNotificationPlugin.swift +++ b/packages/stream_video_push_notification/ios/stream_video_push_notification/Sources/stream_video_push_notification/StreamVideoPushNotificationPlugin.swift @@ -2,16 +2,16 @@ import Flutter import UIKit public class StreamVideoPushNotificationPlugin: NSObject, FlutterPlugin { - private let devicePushTokenVoIP = "DevicePushTokenVoIP" + private static let devicePushTokenVoIPKey = "DevicePushTokenVoIP" let persistentState: UserDefaults = UserDefaults.standard - @objc public private(set) static var sharedInstance: StreamVideoPushNotificationPlugin! + @objc public private(set) static var sharedInstance: StreamVideoPushNotificationPlugin? private var callKitManager: StreamVideoCallkitManager - public init(callKitManager: StreamVideoCallkitManager) { - self.callKitManager = callKitManager + private override init() { + self.callKitManager = StreamVideoCallkitManager.shared super.init() } @@ -24,10 +24,10 @@ public class StreamVideoPushNotificationPlugin: NSObject, FlutterPlugin { let eventsHandler = EventCallbackHandler() eventChannel.setStreamHandler(eventsHandler) - let callKitManager = StreamVideoCallkitManager(eventHandler: eventsHandler) - sharedInstance = StreamVideoPushNotificationPlugin(callKitManager: callKitManager) + StreamVideoCallkitManager.shared.setEventHandler(eventsHandler) - registrar.addMethodCallDelegate(sharedInstance, channel: mainChannel) + sharedInstance = StreamVideoPushNotificationPlugin() + registrar.addMethodCallDelegate(sharedInstance!, channel: mainChannel) StreamVideoPKDelegateManager.shared.initChannel(mainChannel: mainChannel) } @@ -59,35 +59,34 @@ public class StreamVideoPushNotificationPlugin: NSObject, FlutterPlugin { } @objc public static func setDevicePushTokenVoIP(deviceToken: String) { - sharedInstance.setDevicePushTokenVoIP(deviceToken: deviceToken) - //TODO: send event? //ACTION_DID_UPDATE_DEVICE_PUSH_TOKEN_VOIP + sharedInstance?.setDevicePushTokenVoIP(deviceToken: deviceToken) } @objc public static func startOutgoingCall( data: CallData, fromPushKit: Bool ) { - sharedInstance.callKitManager.startCall(data, fromPushKit: fromPushKit) + StreamVideoCallkitManager.shared.startCall(data, fromPushKit: fromPushKit) } @objc public static func showIncomingCall( data: CallData, fromPushKit: Bool ) { - sharedInstance.callKitManager.showIncomingCall( + StreamVideoCallkitManager.shared.showIncomingCall( data, fromPushKit: fromPushKit) } @objc public static func activeCalls() -> [[String: Any]]? { - sharedInstance.callKitManager.activeCalls() + return StreamVideoCallkitManager.shared.activeCalls() } @objc public func setDevicePushTokenVoIP(deviceToken: String) { - persistentState.set(deviceToken, forKey: devicePushTokenVoIP) + persistentState.set(deviceToken, forKey: Self.devicePushTokenVoIPKey) } @objc public func getDevicePushTokenVoIP() -> String { - return persistentState.string(forKey: devicePushTokenVoIP) ?? "" + return persistentState.string(forKey: Self.devicePushTokenVoIPKey) ?? "" } }