Integrace s CallKitem
V tomto dokumentu si ukážeme, jak integrovat CallKit s vaší aplikací pro iOS.
Požadavky
- Účet Azure s aktivním předplatným. Vytvoření účtu zdarma
- Nasazený prostředek komunikační služby. Vytvořte prostředek komunikační služby.
- Přístupový token uživatele pro povolení volajícího klienta. Další informace najdete v tématu Vytváření a správa přístupových tokenů.
- Volitelné: Dokončením rychlého startu přidáte do aplikace hlasové hovory.
Integrace CallKitu (v sadě SDK)
Integrace CallKitu v sadě Azure Communication Services sdk pro iOS zpracovává interakci s CallKitem. Abychom mohli provádět jakékoli operace volání, jako je ztlumení nebo zrušení ztlumení, blokování a obnovení, potřebujeme rozhraní API volat pouze v sadě SDK služby Azure Communication Services.
Inicializace agenta volání pomocí CallKitOptions
S nakonfigurovanou instancí CallKitOptions
můžeme vytvořit CallAgent
zpracování 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
})
Zadání informací o příjemci hovorů pro odchozí hovory
Nejprve musíme vytvořit instanci odchozích StartCallOptions()
hovorů nebo JoinCallOptions()
pro skupinové volání:
let options = StartCallOptions()
or
let options = JoinCallOptions()
Pak vytvořte instanci CallKitRemoteInfo
options.callKitRemoteInfo = CallKitRemoteInfo()
- Přiřaďte hodnotu pro
callKitRemoteInfo.displayNameForCallKit
přizpůsobení zobrazovaného jména pro příjemce hovoru a konfiguraciCXHandle
hodnoty. Tato hodnota je přesně způsob, jakýmdisplayNameForCallKit
se zobrazuje v posledním vytáčeném protokolu volání. v posledním vytočení protokolu volání.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- Přiřazení hodnoty je to
cxHandle
, co aplikace obdrží, když uživatel zavolá zpět na tento kontakt.
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
Zadání informací o příjemci hovorů pro příchozí hovory
Nejprve musíme vytvořit instanci CallKitOptions
:
let callKitOptions = CallKitOptions(with: createProviderConfig())
Konfigurace vlastností CallKitOptions
instance:
Blok, který se předá do proměnné provideRemoteInfo
, bude volána sadou SDK, když přijmeme příchozí hovor, a potřebujeme získat zobrazovaný název příchozího volajícího, který potřebujeme předat do CallKitu.
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
}
Konfigurace zvukové relace
Konfigurace zvukové relace bude volána před umístěním nebo přijetím příchozího hovoru a před pokračováním hovoru po jeho blokování.
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
}
POZNÁMKA: V případech, kdy společnost Contoso již nakonfigurovala zvukové relace, neposkytují nil
, ale vrací nil
chybu v bloku.
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
return nil
}
pokud nil
je k dispozici pro configureAudioSession
tuto sadu SDK, volá výchozí implementaci v sadě SDK.
Zpracování příchozí datové části nabízených oznámení
Když aplikace obdrží datovou část příchozího nabízeného oznámení, musíme ji volat handlePush
, abychom ji mohli zpracovat. Událost vyvolá IncomingCall
volání sady SDK služby Azure Communication Services.
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) {
}
Můžeme použít reportIncomingCall
ke zpracování nabízených oznámení, když je aplikace zavřená nebo jinak.
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)
}
}
}
Integrace CallKitu (v aplikaci)
Pokud chcete integrovat CallKit v aplikaci a nepoužívat implementaci CallKitu v sadě SDK, projděte si ukázku rychlého startu zde. Jednou z důležitých věcí, na které je potřeba se postarat, je spustit zvuk ve správný čas. To se mi líbí
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)
Ztlumení reproduktoru a mikrofonu zajistí, aby se fyzická zvuková zařízení nepoužívala, dokud CallKit nezavolá didActivateAudioSession
.CXProviderDelegate
Jinak se hovor může vynechat nebo zvuk nebude fungovat.
Kdy didActivateAudioSession
se mají spustit zvukové streamy.
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()
}
Je také důležité ztlumit odchozí zvuk před zastavením zvuku v případech, kdy CallKit nevyvolá didActivateAudioSession
. Uživatel pak může ztlumení mikrofonu ručně zrušit.
Poznámka:
V některých případech CallKit nevolá didActivateAudioSession
, i když má aplikace zvýšená zvuková oprávnění, v takovém případě zvuk zůstane ztlumený, dokud nebude hovor přijat zpět. Uživatelské rozhraní musí odrážet stav reproduktoru a mikrofonu. Vzdálený účastník/s v hovoru uvidí, že uživatel má ztlumený zvuk. Uživatel bude muset v těchto případech ručně zrušit ztlumení.