Integracja z zestawem CallKit
W tym dokumencie omówimy sposób integracji biblioteki CallKit z aplikacją systemu iOS.
Wymagania wstępne
- Konto platformy Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
- Wdrożony zasób usług komunikacyjnych. Utwórz zasób usług komunikacyjnych.
- Token dostępu użytkownika umożliwiający włączenie klienta wywołującego. Aby uzyskać więcej informacji, zobacz Tworzenie tokenów dostępu i zarządzanie nimi.
- Opcjonalnie: ukończ przewodnik Szybki start, aby dodać połączenie głosowe do aplikacji
Integracja zestawu CallKit (w zestawie SDK)
Integracja zestawu CallKit w zestawie SDK usług Azure Communication Services dla systemu iOS obsługuje interakcję z zestawem CallKit dla nas. Aby wykonać wszystkie operacje wywołania, takie jak wyciszenie/wyciszenie, blokada/wznawianie, musimy wywołać interfejs API tylko w zestawie SDK usług Azure Communication Services.
Inicjowanie agenta wywołania za pomocą elementu CallKitOptions
Za pomocą skonfigurowanego CallKitOptions
wystąpienia programu możemy utworzyć element CallAgent
z obsługą elementu 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
})
Określanie informacji adresata połączenia dla połączeń wychodzących
Najpierw musimy utworzyć wystąpienie dla połączeń wychodzących StartCallOptions()
lub JoinCallOptions()
wywołania grupy:
let options = StartCallOptions()
lub
let options = JoinCallOptions()
Następnie utwórz wystąpienie klasy CallKitRemoteInfo
options.callKitRemoteInfo = CallKitRemoteInfo()
- Przypisz wartość ,
callKitRemoteInfo.displayNameForCallKit
aby dostosować nazwę wyświetlaną adresatów wywołań i skonfigurowaćCXHandle
wartość. Ta wartość określona w parametrzedisplayNameForCallKit
jest dokładnie taka, jak jest wyświetlana w ostatnim dzienniku połączeń telefonicznych. w ostatnim dzienniku połączeń telefonicznych.
options.callKitRemoteInfo.displayNameForCallKit = "DISPLAY_NAME"
- Przypisz wartość odbieraną przez aplikację
cxHandle
, gdy użytkownik odwołuje się do tego kontaktu
options.callKitRemoteInfo.cxHandle = CXHandle(type: .generic, value: "VALUE_TO_CXHANDLE")
Określanie informacji adresata połączenia dla połączeń przychodzących
Najpierw musimy utworzyć wystąpienie klasy CallKitOptions
:
let callKitOptions = CallKitOptions(with: createProviderConfig())
Skonfiguruj właściwości CallKitOptions
wystąpienia:
Blok przekazywany do zmiennej provideRemoteInfo
będzie wywoływany przez zestaw SDK podczas odbierania wywołania przychodzącego i musimy uzyskać nazwę wyświetlaną dla elementu wywołującego przychodzącego, który musimy przekazać do zestawu 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
}
Konfigurowanie sesji audio
Konfiguracja sesji audio zostanie wywołana przed umieszczeniem lub zaakceptowaniem połączenia przychodzącego i przed wznowieniem połączenia po jego wstrzymaniu.
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
}
UWAGA: W przypadkach, gdy firma Contoso skonfigurowała już sesje audio, nie udostępniaj nil
, ale zwraca nil
błąd w bloku
callKitOptions.configureAudioSession = self.configureAudioSession
public func configureAudioSession() -> Error? {
return nil
}
jeśli nil
zostanie podany dla configureAudioSession
zestawu SDK, zestaw SDK wywołuje domyślną implementację w zestawie SDK.
Obsługa przychodzącego ładunku powiadomień wypychanych
Gdy aplikacja odbiera przychodzący ładunek powiadomień wypychanych, musimy wywołać handlePush
metodę , aby ją przetworzyć. Wywołanie zestawu SDK usług Azure Communication Services spowoduje wywołanie IncomingCall
zdarzenia.
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) {
}
Możemy użyć reportIncomingCall
metody do obsługi powiadomień wypychanych, gdy aplikacja jest zamknięta lub w inny sposób.
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)
}
}
}
Integracja z zestawem CallKit (w aplikacji)
Jeśli chcesz zintegrować zestaw CallKit w aplikacji i nie używać implementacji CallKit w zestawie SDK, zapoznaj się z przykładowym przewodnikiem Szybki start tutaj. Ale jedną z ważnych rzeczy, które należy wziąć pod uwagę, jest rozpoczęcie dźwięku w odpowiednim czasie. Podobnie jak poniżej
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)
Wyciszanie głośnika i mikrofonu gwarantuje, że fizyczne urządzenia audio nie będą używane, dopóki zestaw CallKit nie wywoła elementu didActivateAudioSession
w obiekcie CXProviderDelegate
. W przeciwnym razie połączenie może zostać porzucone lub dźwięk nie będzie działać.
Kiedy didActivateAudioSession
należy uruchomić strumienie 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()
}
Ważne jest również wyciszenie wychodzącego dźwięku przed zatrzymaniem dźwięku w przypadkach, gdy zestaw CallKit nie wywołuje elementu didActivateAudioSession
. Następnie użytkownik może ręcznie cofnąć wyciszenie mikrofonu.
Uwaga
W niektórych przypadkach zestaw CallKit nie wywołuje wywołania didActivateAudioSession
, mimo że aplikacja ma podwyższony poziom uprawnień dźwięku, w takim przypadku dźwięk pozostanie wyciszony do momentu odebrania wywołania zwrotnego. Interfejs użytkownika musi odzwierciedlać stan głośnika i mikrofonu. Zdalny uczestnik/s w wywołaniu zobaczy, że użytkownik również wyciszył dźwięk. W takich przypadkach użytkownik będzie musiał ręcznie cofnąć wyciszenie.