Condividi tramite


Eseguire l'integrazione con CallKit

In questo documento verrà illustrato come integrare CallKit con l'applicazione iOS.

Prerequisiti

Integrazione callkit (all'interno dell'SDK)

L'integrazione di CallKit nel Servizi di comunicazione di Azure iOS SDK gestisce l'interazione con CallKit. Per eseguire qualsiasi operazione di chiamata, ad esempio disattivazione/disattivazione, blocco/ripresa, è sufficiente chiamare l'API nell'SDK di Servizi di comunicazione di Azure.

Inizializzare l'agente di chiamata con CallKitOptions

Con l'istanza configurata di CallKitOptions, è possibile creare con la CallAgent gestione di CallKit.

let options = CallAgentOptions()
let callKitOptions = CallKitOptions(with: createProviderConfig())
options.callKitOptions = callKitOptions

// Configure the properties of `CallKitOptions` instance here

self.callClient!.createCallAgent(userCredential: userCredential,
    options: options,
    completionHandler: { (callAgent, error) in
    // Initialization
})

Specificare le informazioni sul destinatario delle chiamate in uscita

Prima di tutto è necessario creare un'istanza di StartCallOptions() per le chiamate in uscita o JoinCallOptions() per la chiamata di gruppo:

let options = StartCallOptions()

oppure

let options = JoinCallOptions()

Creare quindi un'istanza di CallKitRemoteInfo

options.callKitRemoteInfo = CallKitRemoteInfo()
  1. Assegnare il valore per callKitRemoteInfo.displayNameForCallKit per personalizzare il nome visualizzato per i destinatari delle chiamate e configurare CXHandle il valore. Questo valore specificato in displayNameForCallKit è esattamente come viene visualizzato nell'ultimo log chiamate composto. nell'ultimo registro chiamate composto.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
  1. Assegnare il cxHandle valore è ciò che l'applicazione riceve quando l'utente richiama il contatto
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")

Specificare le informazioni sul destinatario delle chiamate in arrivo

Prima di tutto è necessario creare un'istanza di CallKitOptions:

let callKitOptions = CallKitOptions(with: createProviderConfig())

Configurare le proprietà dell'istanza CallKitOptions :

Il blocco passato alla variabile provideRemoteInfo verrà chiamato dall'SDK quando si riceve una chiamata in arrivo ed è necessario ottenere un nome visualizzato per il chiamante in ingresso, che è necessario passare al CallKit.

callKitOptions.provideRemoteInfo = self.provideCallKitRemoteInfo

func provideCallKitRemoteInfo(callerInfo: CallerInfo) -> CallKitRemoteInfo
{
    let callKitRemoteInfo = CallKitRemoteInfo()
    callKitRemoteInfo.displayName = "CALL_TO_PHONENUMBER_BY_APP"      
    callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
    return callKitRemoteInfo
}

Configurare la sessione audio

Configurare la sessione audio verrà chiamata prima di effettuare o accettare la chiamata in arrivo e prima di riprendere la chiamata dopo che è stata messa in attesa.

callKitOptions.configureAudioSession = self.configureAudioSession

public func configureAudioSession() -> Error? {
    let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
    var configError: Error?
    do {
        try audioSession.setCategory(.playAndRecord)
    } catch {
        configError = error
    }
    return configError
}

NOTA: nei casi in cui Contoso ha già configurato sessioni audio NON fornire nil ma restituire nil un errore nel blocco

callKitOptions.configureAudioSession = self.configureAudioSession

public func configureAudioSession() -> Error? {
    return nil
}

se nil viene fornito per configureAudioSession , SDK chiama l'implementazione predefinita nell'SDK.

Gestire il payload di notifica push in ingresso

Quando l'app riceve il payload di notifica push in ingresso, è necessario chiamare handlePush per elaborarlo. Servizi di comunicazione di Azure Calling SDK genererà l'evento IncomingCall .

public func handlePushNotification(_ pushPayload: PKPushPayload)
{
    let callNotification = PushNotificationInfo.fromDictionary(pushPayload.dictionaryPayload)
    if let agent = self.callAgent {
        agent.handlePush(notification: callNotification) { (error) in }
    }
}

// Event raised by the SDK
public func callAgent(_ callAgent: CallAgent, didRecieveIncomingCall incomingcall: IncomingCall) {
}

È possibile usare reportIncomingCall per gestire le notifiche push quando l'app viene chiusa o in altro modo.

if let agent = self.callAgent {
  /* App is not in a killed state */
  agent.handlePush(notification: callNotification) { (error) in }
} else {
  /* App is in a killed state */
  CallClient.reportIncomingCall(with: callNotification, callKitOptions: callKitOptions) { (error) in
      if (error == nil) {
          DispatchQueue.global().async {
              self.callClient = CallClient()
              let options = CallAgentOptions()
              let callKitOptions = CallKitOptions(with: createProviderConfig())
              callKitOptions.provideRemoteInfo = self.provideCallKitRemoteInfo
              callKitOptions.configureAudioSession = self.configureAudioSession
              options.callKitOptions = callKitOptions
              self.callClient!.createCallAgent(userCredential: userCredential,
                  options: options,
                  completionHandler: { (callAgent, error) in
                  if (error == nil) {
                      self.callAgent = callAgent
                      self.callAgent!.handlePush(notification: callNotification) { (error) in }
                  }
              })
          }
      } else {
          os_log("SDK couldn't handle push notification", log:self.log)
      }
  }
}

Integrazione di CallKit (all'interno dell'app)

Se vuoi integrare CallKit all'interno dell'app e non usare l'implementazione callkit nell'SDK, fai riferimento all'esempio di avvio rapido qui. Ma una delle cose importanti di cui occuparsi è avviare l'audio al momento giusto. Come segue

let outgoingAudioOptions = OutgoingAudioOptions()
outgoingAudioOptions.muted = true

let incomingAudioOptions = IncomingAudioOptions()
incomingAudioOptions.muted = true

var copyAcceptCallOptions = AcceptCallOptions()
copyStartCallOptions.outgoingAudioOptions = outgoingAudioOptions
copyStartCallOptions.incomingAudioOptions = incomingAudioOptions

callAgent.startCall(participants: participants,
                    options: copyStartCallOptions,
                    completionHandler: completionBlock)

La disattivazione dell'altoparlante e del microfono garantisce che i dispositivi audio fisici non vengano usati finché il CallKit non chiama su didActivateAudioSession CXProviderDelegate. In caso contrario, la chiamata potrebbe essere eliminata o l'audio non funzionerà. Quando didActivateAudioSession si avviano i flussi audio.

func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
    Task {
        guard let activeCall = await self.callKitHelper.getActiveCall() else {
            print("No active calls found when activating audio session !!")
            return
        }

        try await startAudio(call: activeCall)
    }
}

func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
    Task {
        guard let activeCall = await self.callKitHelper.getActiveCall() else {
            print("No active calls found when deactivating audio session !!")
            return
        }

        try await stopAudio(call: activeCall)
    }
}

private func stopAudio(call: Call) async throws {
    try await self.callKitHelper.muteCall(callId: call.id, isMuted: true)
    try await call.stopAudio(stream: call.activeOutgoingAudioStream)

    try await call.stopAudio(stream: call.activeIncomingAudioStream)
    try await call.muteIncomingAudio()
}

private func startAudio(call: Call) async throws {
    try await call.startAudio(stream: LocalOutgoingAudioStream())
    try await self.callKitHelper.muteCall(callId: call.id, isMuted: false)

    try await call.startAudio(stream: RemoteIncomingAudioStream())
    try await call.unmuteIncomingAudio()
}
    

È importante disattivare anche l'audio in uscita prima di arrestare l'audio nei casi in cui CallKit non richiama didActivateAudioSession. L'utente può quindi annullare manualmente l'attivazione del microfono.

Nota

In alcuni casi CallKit non chiama didActivateAudioSession anche se l'app dispone di autorizzazioni audio elevate, in tal caso l'audio rimarrà disattivato fino alla ricezione del callback. E l'interfaccia utente deve riflettere lo stato dell'altoparlante e del microfono. Il partecipante remoto/s nella chiamata noterà che anche l'utente ha disattivato l'audio. L'utente dovrà annullare manualmente l'audio in questi casi.

Passaggi successivi