doneservices / flutter_callkeep

iOS CallKit and Android ConnectionService bindings for Flutter
58 stars 41 forks source link

Incoming call does not show in background state in ios #53

Closed kyawthet-wam closed 4 months ago

kyawthet-wam commented 1 year ago

I followed the steps for iOS that mentions in readme. What's wrong with me or do i need to do some extra for that issue. Please help me.

Ayman-Barghout commented 1 year ago

If you have allowed the needed background modes correctly (you can follow this SO answer but also allow VoIP and fetch) and updated AppDelegate.swift to call SwiftCallKeepPlugin.sharedInstance?.displayIncomingCall(data, fromPushKit: true) with correct data then it should work for iOS in the background.

kyawthet-wam commented 1 year ago
In my info.plist -

       <key>UIBackgroundModes</key>
    <array>
        <string>fetch</string>
        <string>processing</string>
        <string>remote-notification</string>
        <string>voip</string>
    </array>

AppDelegate.swift

  import UIKit
  import PushKit
  import Flutter
  import flutter_callkeep

  @UIApplicationMain
  @objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
      override func application(
          _ application: UIApplication,
          didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        if #available(iOS 10.0, *) {
    UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
  }
          GeneratedPluginRegistrant.register(with: self)

          //Setup VOIP
          let mainQueue = DispatchQueue.main
          let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue)
          voipRegistry.delegate = self
          voipRegistry.desiredPushTypes = [PKPushType.voIP]

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

      // Handle updated push credentials
      func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
          let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined()
          //Save deviceToken to your server
          SwiftCallKeepPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken)
      }

      func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
          SwiftCallKeepPlugin.sharedInstance?.setDevicePushTokenVoIP("")
      }

      // Handle incoming pushes
      func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: 
        PKPushType, completion: @escaping () -> Void) {
          guard type == .voIP else { return }

          let id = payload.dictionaryPayload["id"] as? String ?? ""
          let callerName = payload.dictionaryPayload["callerName"] as? String ?? ""
          let userId = payload.dictionaryPayload["callerId"] as? String ?? ""
          let handle = payload.dictionaryPayload["handle"] as? String ?? ""
          let isVideo = payload.dictionaryPayload["isVideo"] as? Bool ?? false
          let extra = payload.dictionaryPayload["extra"] as? NSDictionary ?? [:]
          let data = flutter_callkeep.Data(id: id, callerName: callerName, handle: handle, hasVideo: isVideo)
          //set more data
          data.extra = extra
          data.appName = "YC Fitness"
          //data.iconName = ...
          //data.....
          SwiftCallKeepPlugin.sharedInstance?.displayIncomingCall(data, fromPushKit: true)

      }   
  }

And I have another issue that CallKeep.instance.endAllCalls() does not close the current call screen in ios foreground. Please help me. Thank you for your reply.

kyawthet-wam commented 1 year ago

hello, do you have any idea?

Ayman-Barghout commented 1 year ago

It'd be hard for me to debug why the background CallKit isn't working for you without more information like which devices you have tried it on and if you set data properly, maybe you can insert swift logs and use MacOS console to debug for yourself and see at which step showing CallKit fails, as for endAllCalls(), this would end the CallKit native call but if you have another call ongoing like Agora or WebRTC you have to specifically listen for the callEnded CallKeepEvent and end the ongoing call yourself.

Ayman-Barghout commented 4 months ago

The issue can't be resolved without further information provided, feel free to re-open if it still presists.