Integrera med CallKit
I det här dokumentet går vi igenom hur du integrerar CallKit med ditt iOS-program.
Förutsättningar
- Ett Azure-konto med en aktiv prenumeration. Skapa ett konto utan kostnad.
- En distribuerad Communication Services-resurs. Skapa en Communication Services-resurs.
- En användaråtkomsttoken för att aktivera den anropande klienten. Mer information finns i Skapa och hantera åtkomsttoken.
- Valfritt: Slutför snabbstarten för att lägga till röstsamtal i ditt program
CallKit-integrering (inom SDK)
CallKit-integrering i Azure Communication Services iOS SDK hanterar interaktion med CallKit åt oss. För att utföra alla anropsåtgärder som att stänga av/slå på ljudet, hålla/återuppta behöver vi bara anropa API:et i Azure Communication Services SDK.
Initiera samtalsagenten med CallKitOptions
Med konfigurerad instans av CallKitOptions
kan vi skapa CallAgent
med hanteringen av 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
})
Ange information om samtalsmottagare för utgående samtal
Först måste vi skapa en instans av StartCallOptions()
för utgående anrop eller JoinCallOptions()
för gruppsamtal:
let options = StartCallOptions()
eller
let options = JoinCallOptions()
Skapa sedan en instans av CallKitRemoteInfo
options.callKitRemoteInfo = CallKitRemoteInfo()
- Tilldela värde för för
callKitRemoteInfo.displayNameForCallKit
att anpassa visningsnamnet för samtalsmottagare och konfigureraCXHandle
värdet. Det här värdet som anges idisplayNameForCallKit
är exakt hur det visas i den senast uppringda samtalsloggen. i den senast uppringda samtalsloggen.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- Tilldela värdet
cxHandle
är vad programmet tar emot när användaren anropar den kontakten igen
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
Ange information om samtalsmottagare för inkommande samtal
Först måste vi skapa en instans av CallKitOptions
:
let callKitOptions = CallKitOptions(with: createProviderConfig())
Konfigurera egenskaperna CallKitOptions
för instansen:
Blockera som skickas till variabeln provideRemoteInfo
anropas av SDK när vi tar emot ett inkommande samtal och vi måste få ett visningsnamn för den inkommande anroparen, som vi måste skicka till 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
}
Konfigurera ljudsession
Konfigurera ljudsession anropas innan inkommande samtal skickas eller godkänns och innan samtalet återupptas efter att det har spärrats.
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
}
OBS! I de fall där Contoso redan har konfigurerat ljudsessioner ska du INTE ange nil
men returnera nil
fel i blocket
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
return nil
}
om nil
anges för configureAudioSession
anropar SDK standardimplementeringen i SDK.
Hantera nyttolasten för inkommande push-meddelanden
När appen tar emot nyttolasten för inkommande push-meddelanden måste vi anropa handlePush
för att bearbeta den. Azure Communication Services Calling SDK genererar IncomingCall
händelsen.
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) {
}
Vi kan använda reportIncomingCall
för att hantera push-meddelanden när appen stängs eller på annat sätt.
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)
}
}
}
CallKit-integrering (inom appen)
Om du vill integrera CallKit i appen och inte använda CallKit-implementeringen i SDK kan du läsa snabbstartsexemplet här. Men en av de viktiga sakerna att ta hand om är att starta ljudet vid rätt tidpunkt. Som att följa
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)
Genom att stänga av högtalare och mikrofon ser du till att fysiska ljudenheter inte används förrän CallKit anropar på didActivateAudioSession
CXProviderDelegate
. Annars kan samtalet tas bort eller så fungerar inte ljudet.
När didActivateAudioSession
ska ljudströmmarna startas.
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()
}
Det är viktigt att även stänga av det utgående ljudet innan ljudet stoppas i fall då CallKit inte anropar didActivateAudioSession
. Användaren kan sedan slå på mikrofonen manuellt.
Kommentar
I vissa fall anropar didActivateAudioSession
inte CallKit trots att appen har utökade ljudbehörigheter, i så fall förblir ljudet avstängt tills återanropet tas emot. Och användargränssnittet måste återspegla talarens och mikrofonens tillstånd. Fjärrdeltagaren/-deltagarna i anropet ser också att användaren har stängt av ljudet. Användaren måste slå på ljudet manuellt i dessa fall.