Открыть приложение при нажатии на значок приложения в CallKit

Я интегрировал голосовой вызов с помощью SINCH SDK, моя проблема заключается в том, что когда телефон находится на экране блокировки, и я получаю входящий вызов через CallKit, и я отвечаю, все в порядке, но когда я нажимаю значок приложения, приложение открывается в VoiceCallController и вызов снова запускается со звонком звук.

class SINCallKitProvider: NSObject, CXProviderDelegate {

var _client: SINClient!
var _provider: CXProvider!
var _acDelegate: AudioContollerDelegate!
var _calls: [UUID : SINCall]
var _muted: Bool


init(withClient: SINClient) {
    
    _client = withClient
    _muted = false
    _acDelegate = AudioContollerDelegate()
    _client.audioController().delegate = _acDelegate
    _calls = [:]
    
    let config = CXProviderConfiguration(localizedName: "ok")
    config.maximumCallGroups = 2
    config.supportsVideo = false
    config.maximumCallsPerCallGroup = 1
    let callkitIcon = UIImage(named: "ok")
    config.iconTemplateImageData = UIImagePNGRepresentation(callkitIcon!)
    
    _provider = CXProvider(configuration: config)
    
    
    super.init()
    
    _provider.setDelegate(self, queue: nil)
    
    NotificationCenter.default.addObserver(self, selector: #selector(callDidEnd), name: NSNotification.Name(rawValue: "SINCallDidEndNotification"), object: nil)
    
}

func reportNewIncomingCall (call: SINCall) {
    let firstName = currentUser.string(forKey: "firstName")
    let lastName = currentUser.string(forKey: "lastName")
    let fullName = "\(firstName!) \(lastName!)"

    var caller = fullName
    if let call = call.headers["from"] {
        caller = call as! String
    }
    
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(type: .generic, value: caller)

    _provider.reportNewIncomingCall(with: UUID(uuidString: call.callId)!, update: update) { (error) in
        if error != nil {
            print("error call \(error!.localizedDescription)")
            return
        }
        
        self.addNewCall(call: call)
    }
    
}

func addNewCall(call: SINCall) {
    print("Added call \(call.callId)")
    _calls[UUID(uuidString: call.callId)!] = call
}



// Handle cancel/bye event initiated by either caller or callee
@objc func callDidEnd(notification: Notification) {
    
    if let call: SINCall = notification.userInfo![SINCallKey] as? SINCall {
        
        let cause = SINGetCallEndedReason(cause: call.details.endCause)
        
        _provider.reportCall(with: UUID(uuidString: call.callId)!, endedAt: call.details.endedTime, reason: cause)
        
        
        if self.callExist(callId: call.callId) {
            print("CallDidEnd, removing \(call.callId)")
            _calls.removeValue(forKey: UUID(uuidString: call.callId)!)
        }

    } else {
        print("****warning no call was reported")
    }
    
    
}


func callExist (callId: String) -> Bool {
    
    if _calls.count == 0 {
        return false
    }

    for callKitCall in _calls.values {
        if callKitCall.callId == callId {
            return true
        }
    }
    return false
}

func activeCalls() -> [SINCall] {
    return Array(_calls.values)
}

func currentEstablishedCall () -> SINCall? {
    let calls = activeCalls()
    
    if calls.count == 1 && calls[0].state == SINCallState.established {
        return calls[0]
    } else {
        return nil
    }
}


//MARK: CXProvider delegate
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
    print("Did activate")
    _client.call()?.provider(provider, didActivate: audioSession)
}

func callForAction(action: CXCallAction) -> SINCall? {
    
    let call = _calls[action.callUUID]
    if call == nil {
        print("Warning no call found for action \(action.callUUID)")
        return nil
    }
    return call
}

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    print("Answer call action")
    callForAction(action: action)!.answer()
    action.fulfill()
}

func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
    print("end call action")
    callForAction(action: action)!.hangup()
    action.fulfill()
}

func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
    print("mute call action")

    if _acDelegate.muted {
        _client.audioController().unmute()
    } else {
        _client.audioController().mute()
    }
    action.fulfill()
}

func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
    print("did diactivate audio session")
}


func providerDidReset(_ provider: CXProvider) {
    print("did reset")

}


//MARK: Helpers
func SINGetCallEndedReason(cause: SINCallEndCause) -> CXCallEndedReason {
    switch cause {
    case .error:
        return CXCallEndedReason.failed
    case.denied:
        return CXCallEndedReason.remoteEnded
    case .hungUp:
        return CXCallEndedReason.remoteEnded
    case .timeout:
        return CXCallEndedReason.unanswered
    case .canceled:
        return CXCallEndedReason.unanswered
    case .noAnswer:
        return CXCallEndedReason.unanswered
    case .otherDeviceAnswered:
        return CXCallEndedReason.unanswered
    default:
        break
    }
    
    return CXCallEndedReason.failed
}


}

person Ghassan    schedule 08.10.2018    source источник
comment
Можете ли вы помочь мне с общим кодом?   -  person Pratyush Pratik    schedule 29.11.2018
comment
да, вы можете помочь нам, начинающим разработчикам, загрузив пример проекта Swift для sinch. с фоном под названием enable. или могли бы работать вместе   -  person Muhammad Asyraf    schedule 30.05.2021


Ответы (1)


Вы говорите, что ваше приложение не отображает правильный вид при входе в ваше приложение через значок приложения в пользовательском интерфейсе заблокированного экрана CallKit?

Если это ваша проблема, одним из решений может быть: вы должны поддерживать список или переменную в своем поставщике callkit, просто чтобы проверить, есть ли у вас какой-либо подключенный вызов. И ваш делегат приложения должен прослушивать уведомление applicationWillEnterForeground, которое будет запущено, если пользователь щелкнет значок приложения в пользовательском интерфейсе callkit.

Когда вы получаете уведомление applicationWillEnterForeground, вы проверяете, удерживает ли ваш поставщик callkit какой-либо активный вызов, если да, вы представляете представление, которое показывает текущий вызов, в противном случае вы показываете то представление, которое будет отображаться в вашей текущей реализации.

Пример приложения SinchCallKit предоставляет некоторую справочную информацию по реализации для решения этой проблемы (хотя в задаче c). Проверьте AppDelegate.m, CallViewController.m и SINCallKitProvider.m в этом проекте.

person Bo Li    schedule 09.10.2018
comment
случайно у вас есть быстрый полный образец проекта для sinch, который уже опубликован. - person Muhammad Asyraf; 30.05.2021