Eseguire l'integrazione con CallKit
In questo documento verrà illustrato come integrare CallKit con l'applicazione iOS.
Prerequisiti
- Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.
- Una risorsa di Servizi di comunicazione distribuita. Creare una risorsa di Servizi di comunicazione.
- Token di accesso utente per abilitare il client chiamante. Per altre informazioni, vedere Creare e gestire i token di accesso.
- Facoltativo: Completare la guida introduttiva per aggiungere chiamate vocali all'applicazione
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()
- Assegnare il valore per
callKitRemoteInfo.displayNameForCallKit
per personalizzare il nome visualizzato per i destinatari delle chiamate e configurareCXHandle
il valore. Questo valore specificato indisplayNameForCallKit
è esattamente come viene visualizzato nell'ultimo log chiamate composto. nell'ultimo registro chiamate composto.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- 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.