1対1音声通話
1対1音声通話を実装するサンプルコードです。
前提条件
開始する前に、次の作業が必要です。
- PlanetKitを初期化してください。
- 適切なアクセストークンを取得してください。
- 1対1通話フローにて、APIを使用するための全般的なプロセスを確認してください。
1対1音声通話実装時の考慮事項
受信者側で通話の通知を受けるには、通知用システムを実装するか、APNs(Apple Push Notification service)またはFCM(Firebase Cloud Messaging)といった外部のプッシュ通知システムを連携する必要があります。
また、受信者にどのような情報を伝えるべきかを知っておく必要があります。アプリサーバーの役割でアプリケーションが転送すべきデータであるcc_param
について確認できます。
makeCall()
またはverifyCall()
を呼び出した後は、返却されたPlanetKitCallMakeResult
またはPlanetKitCallVerifyResult
でreason
を確認する必要があります。通話に失敗した場合は、reason
に応じて適切な処理を行う必要があります。
動作する全体のソースコードは、デモアプリのソースコードで確認できます。
共通 - PlanetKitCallDelegate
実装
アプリケーションがコールセットアップ(call setup)中にイベントを受けて処理できるようにPlanetKitCallDelegate
を実装する必要があります。
extension CallDelegateExample : PlanetKitCallDelegate {
func didWaitConnect(_ call: PlanetKitCall) {
// This is called after making a call on the caller side.
// Write your own code here.
}
func didVerify(_ call: PlanetKitCall, peerStartMessage: PlanetKitCallStartMessage?, peerUseResponderPreparation: Bool) {
// This is called after verifying a call on the callee side.
// Write your own code here.
}
func didConnect(_ call: PlanetKitCall, connected: PlanetKitCallConnectedParam) {
// This is called after the call is connected on both sides.
// Write your own code here.
}
func didDisconnect(_ call: PlanetKitCall, disconnected: PlanetKitDisconnectedParam) {
// This is called after the call is disconnected on both sides.
// Write your own code here.
}
...
//
// Also, you should implement other methods defined in the PlanetKitCallDelegate protocol.
//
...
}
発信側 - 通話の作成
通話を作成するための手順は、次のとおりです。
PlanetKitMakeCallSettingBuilder
を通じて設定情報を作成します。PlanetKitCallDelegate
を含めてPlanetKitCallParam
を作成します。PlanetKitManager.shared.makeCall()
を呼び出します。PlanetKitCallMakeResult
を確認してください。
class CallerExample
{
var call: PlanetKitCall?
}
...
extension CallerExample
{
func makeCallExample(myId: String, myServiceId: String, peerId: String, peerServiceId: String, accessToken: String, delegate: PlanetKitCallDelegate) {
let myUserId = PlanetKitUserId(id: myId, serviceId: myServiceId)
let peerUserId = PlanetKitUserId(id: peerId, serviceId: peerServiceId)
let settings = try! PlanetKitMakeCallSettingBuilder().build()
let param = PlanetKitCallParam(myUserId: myUserId, peerUserId: peerUserId, delegate: delegate, accessToken: accessToken)
let result = PlanetKitManager.shared.makeCall(param: param, settings: settings)
if result.reason != PlanetKitStartFailReason.none {
NSLog("Failed reason: result. \(result.reason)")
return
}
// The result.call instance is a call instance for calling other APIs from now on.
// You must keep this instance in your own context.
// In this example, the "call" variable holds the instance.
call = result.call
}
}
受信側 - プッシュ通知の受信
通話を受信した側はプッシュ通知システムを通じて新しい電話がかかってきたことに気づきます。このとき、userInfo
からcc_param
をパーシングする必要があります。
新しい電話がかかってきたことを知らせるプッシュ通知を受け取った後、ユーザーが通話できるようにそのリクエストを受け取る必要があります。
class AppDelegate: UIResponder, UIApplicationDelegate {
...
var callee: CalleeExample
var callDelegate: PlanetKitCallDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
let message = userInfo as NSDictionary as! [String: AnyObject]
let param = message["cc_param"] as! String
let ccParam = PlanetKitCCParam(ccParam: param)
// Now we received a push notification.
// We should write code here to respond to the new call.
// For convenience, we assume this is done in verifyCallExample()
let myUserId = "Callee User ID value"
let myServiceId = "Callee Service ID value"
callee.verifyCallExample(myId: myUserId, myServiceId: myServiceId, ccParam: ccParam, delegate: PlanetKitCallDelegate)
}
...
}
受信側 - 通話の受信
PlanetKitManager.shared.verifyCall()
を呼び出して通話を受信してみましょう。
以下のコードのverifyCallExample()
で通話を受信する方法を見ることができます。この例でmyId
は受信者のユーザーID、myServiceId
は受信者のサービスIDです。
class CalleeExample
{
var verifiedCall: PlanetKitCall?
}
...
extension CalleeExample
{
func verifyCallExample(myId: String, myServiceId: String, ccParam: PlanetKitCCParam, delegate: PlanetKitCallDelegate) {
let settings = try! PlanetKitVerifyCallSettingBuilder().build()
let myUserId = PlanetKitUserId(id: myId, serviceId: myServiceId)
let result = PlanetKitManager.shared.verifyCall(myUserId: myUserId, ccParam: ccParam, delegate: delegate)
if result.reason != PlanetKitStartFailReason.none {
NSLog("Failed reason: result. \(result.reason)")
return
}
// The result.call instance is the verified call instance.
// You have to keep this instance in an application layer to call other APIs provided after call setup.
// This example keeps the verified call instance in the following verifiedCall variable.
verifiedCall = result.call
}
}
受信側 - 通話の応答
一般的に通話を受信した後、通話を受けるかどうかを決める時間が必要です。通話に応答するには、acceptCall()
を呼び出します。
verifiedCall
変数は検証済みのインスタンスです。
extension CalleeExample
{
func acceptCallExample() {
verifiedCall.acceptCall(startMessage: nil, useResponderPreparation: false)
}
}
アプリケーションでApple CallKitを実装
CallKitは、通話インスタンスを提供するAppleのフレームワークの1つです。PlanetKit SDKは、CallKitに対してユーザーCallKit実装の連携、PlanetKit内部実装の連携、連携しないという3つのオプションをサポートします。
基本的にPlanetKit SDKは、CallKit連携なしで通話を作成したり、受信したりします。独自のCallKit実装を連携するには、PlanetKit SDKで通話を作成または受信する際にPlanetKitCallKitSetting
のtype
をuser
に設定する必要があります。
発信側の実装例
-
PlanetKitCallKitSetting
インスタンスを生成し、PlanetKitCallKitSetting
のtype
をuser
に設定します。 -
PlanetKitMakeCallSettingBuilder
のwithCallKitSettingsKey()
にインスタンスを渡し、通話作成設定(makeCallSettings
)を作成します。// Code for Step 1 and Step 2
func createMakeCallSettingsWithUserCallKitExample() -> [String: Any] {
let callKitSetting = PlanetKitCallKitSetting(type: .user, param: nil)
var settingsBuilder = try! PlanetKitMakeCallSettingBuilder().withCallKitSettingsKey(setting: callKitSetting)
let makeCallSettings = settingsBuilder.build()
} -
CXProviderDelegate
のprovider(_:didActivate:)
でPlanetKitCall
のnotifyCallKitAudioActivation()
を呼び出します。// Code for Step 3
extension YourCallKitHandler : CXProviderDelegate {
...
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
// PlanetKitCall instance created from PlanetKitManager.makeCall()
call.notifyCallKitAudioActivation()
}
...
}
受信側の実装例
-
PlanetKitCallKitSetting
インスタンスを生成し、PlanetKitCallKitSetting
のtype
をuser
に設定します。 -
PlanetKitVerifyCallSettingBuilder
のwithCallKitSettingsKey()
にインスタンスを渡し、通話受信設定(verifyCallSettings
)を作成します。// Code for Step 1 and Step 2
func createVerifyCallSettingsWithUserCallKitExample() -> [String: Any] {
let callKitSetting = PlanetKitCallKitSetting(type: .user, param: nil)
var settingsBuilder = try! PlanetKitVerifyCallSettingBuilder().withCallKitSettingsKey(setting: callKitSetting)
let verifyCallSettings = settingsBuilder.build()
} -
CXProviderDelegate
のprovider(_:perform:)
のCXCallAction
をもとにPlanetKitCall
のacceptCall()
およびdeclineCall()
を呼び出します。 -
CallKit動作を処理するためのCallKitハンドラーを実装します。
class YourCallKitHandler {
static let shared = SampleCallKitHandler()
private var provider: CXProvider?
private var callController: CXCallController?
private var call: PlanetKitCall?
...
// Implement initialization and other features to handle CallKit operations.
} -
CXProviderDelegate
のprovider(_:didActivate:)
でPlanetKitCall
のnotifyCallKitAudioActivation()
を呼び出します。// Code for Step 3 and Step 4
extension YourCallKitHandler : CXProviderDelegate {
...
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
call.acceptCall(useResponderPreparation: false, startMessage: nil)
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
call.declineCall()
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
call.muteMyAudio(action.isMuted) { success in }
action.fulfill()
}
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
// PlanetKitCall instance created from PlanetKitManager.makeCall()
call.notifyCallKitAudioActivation()
}
// Implement other delegate functions to handle other CXCallActions
...
} -
CallKitとPlanetKitを同期させるためにCallKitを通じて
PlanetKitCall
のmuteMyAudio()
、hold()
およびunhold()
を呼び出すようにUIコードを修正します。extension YourCallViewController {
@IBAction func muteCall(_ sender: UIButton) {
YourCallKitHandler.shared.muteCall()
}
}
extension YourCallKitHandler {
func muteCall() {
let action = CXSetMutedCallAction(call: call.uuid , muted: true)
callController.requestTransaction(with: action) { error in
NSLog("\(error)")
}
}
}
詳細は、CallKitドキュメントを参照してください。