Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Dans ce document, nous allons découvrir comment intégrer CallKit à votre application iOS.
Prerequisites
- Un compte Azure avec un abonnement actif. Créez un compte gratuitement.
- Une ressource de services de communication déployée. Créez une ressource Communication Services.
- Un jeton d’accès utilisateur pour activer le client appelant. Pour plus d’informations, consultez Créer et gérer des jetons d’accès.
- Facultatif : Suivez le guide de démarrage rapide pour ajouter des appels vocaux à votre application
Intégration de CallKit (dans le SDK)
L’intégration de CallKit dans le Kit de développement logiciel (SDK) iOS Azure Communication Services gère l’interaction avec CallKit pour nous. Pour effectuer des opérations d’appel telles que couper/rétablir le son, mise en attente/reprise, il suffit d'appeler l’API de l’Azure Communication Services SDK.
Initialiser l’agent d’appel avec CallKitOptions
Avec l’instance configurée de CallKitOptions, nous pouvons créer le CallAgent tout en gérant le 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
})
Spécifier les informations du destinataire d’appel pour les appels sortants
Tout d’abord, nous devons créer une instance d’appels StartCallOptions() sortants ou JoinCallOptions() d’appel de groupe :
let options = StartCallOptions()
or
let options = JoinCallOptions()
Ensuite, créez une instance de CallKitRemoteInfo
options.callKitRemoteInfo = CallKitRemoteInfo()
- Attribuez une valeur à
callKitRemoteInfo.displayNameForCallKitpour personnaliser le nom d'affichage des destinataires d’appel et configurez la valeur deCXHandle. La valeur spécifiée dansdisplayNameForCallKitest exactement telle qu’elle apparaît dans le dernier journal des appels composés. dans le dernier journal des appels composés.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- Attribuez la valeur
cxHandlepour que l’application la reçoive quand l’utilisateur rappelle ce contact
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
Spécifier les informations du destinataire d’appel pour les appels entrants
Tout d’abord, nous devons créer une instance de CallKitOptions:
let callKitOptions = CallKitOptions(with: createProviderConfig())
Configurez les propriétés de l’instance CallKitOptions :
Le bloc passé à la variable provideRemoteInfo sera appelé par le SDK lorsque nous recevrons un appel entrant et que nous devrons obtenir un nom d'affichage pour l'appelant entrant, que nous devons passer à 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
}
Configurer la session audio
La session audio sera configurée avant de placer ou d'accepter un appel entrant et avant de reprendre l'appel après l'avoir mis en attente.
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
}
REMARQUE : Dans les cas où Contoso a déjà configuré des sessions audio, ne fournissez pas nil mais retournez une erreur nil dans le bloc.
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
return nil
}
si nil est fourni pour configureAudioSession, donc le Kit de développement logiciel (SDK), appelle l’implémentation par défaut dans le SDK.
Gérer la charge utile des notifications Push entrantes.
Lorsque l'application reçoit un payload de notification push entrante, nous devons utiliser handlePush pour le traiter. Le SDK d'appel Azure Communication Services déclenchera l'événement 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, didReceiveIncomingCall incomingcall: IncomingCall) {
}
Nous pouvons utiliser reportIncomingCall pour gérer les notifications Push lorsque l’application est fermée ou autrement.
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)
}
}
}
Intégration de CallKit (dans l’application)
Si vous souhaitez intégrer le CallKit dans l’application et ne pas utiliser l’implémentation CallKit dans le Kit de développement logiciel (SDK), reportez-vous à l’exemple de démarrage rapide ici. Mais l’une des choses importantes à prendre en charge est de démarrer l’audio au bon moment. Comme suit :
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)
Désactiver le haut-parleur et le microphone pour garantir que les périphériques audio physiques ne sont pas utilisés jusqu'à ce que CallKit appelle le didActivateAudioSession sur le CXProviderDelegate. Sinon, l’appel peut être supprimé ou l’audio ne fonctionnera pas.
Quand didActivateAudioSession est le moment où les flux audio doivent être démarrés.
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()
}
Il est important de couper également le son sortant avant d'arrêter le son, dans les cas où CallKit ne déclenche pas
Note
Dans certains cas, CallKit n’appelle didActivateAudioSession pas même si l’application dispose d’autorisations audio élevées, dans ce cas, l’audio reste muet jusqu’à ce que le rappel soit reçu. Et l’interface utilisateur doit refléter l’état du haut-parleur et du microphone. Le participant/s distant dans l’appel voit également que l’utilisateur a désactivé l’audio. L’utilisateur devra désactiver manuellement le son dans ces cas.