GithubHelp home page GithubHelp logo

opentok / callkit Goto Github PK

View Code? Open in Web Editor NEW
110.0 72.0 24.0 655 KB

A sample app to demonstrate how to integrate Apple CallKit into OpenTok iOS SDK

License: MIT License

Swift 41.93% Ruby 0.40% Objective-C 57.68%
swift ios opentok tokbox callkit

callkit's Introduction

logo

Build Status

THIS REPOSITORY HAS BEEN RETIRED

CallKit Integration with OpenTok

A sample app to demonstrate how to integrate the CallKit into OpenTok iOS SDK. This sample app is built based on the SpeakerBox app from WWDC 2016 CallKit Session

Install the project files

Use CocoaPods to install the project files and dependencies.

  1. Install CocoaPods as described in CocoaPods Getting Started.
  2. In Terminal, cd to your project directory and type pod install. (Sometimes, pod update is magical)
  3. Reopen your project in Xcode using the new *.xcworkspace file.

Configure and build the app

Configure the sample app code. Then, build and run the app.

  1. The application requires values for API Key, Session ID, and Token. In the sample, you can get these values at the OpenTok Developer Dashboard. For production deployment, you must generate the Session ID and Token values using one of the OpenTok Server SDKs.

  2. Replace the following empty strings with the corresponding API Key, Session ID, and Token values in AppDelegate.swift:

      let apiKey = ""
      let sessionId = ""
      let token = ""
  3. Use Xcode to build and run the app on an iOS simulator or device.

Exploring the sample app

demo

  1. Make a call:

The iOS system boosts the call priority of the app. Then, the app starts publishing to OpenTok platform. You won't notice any differences until you go to the home screen. Two ways to verify:

  • A badge in home screen indicating an ongoing VoIP call.
  • An incoming native phone call will not interrupt the current VoIP call, instead it shows the option menu.

You will need a device to test the followings

  1. Simulate an incoming call

The native incoming call screen appears. Upon acceptance, the iOS system opens the app and boosts the call priority. Then, the app starts publishing to OpenTok platform.

unlock1 ---> unlock2

  1. Simulate an incoming call after 3s(Background) (After clicking the button, please lock your cell phone to test this scenario.)

The system wakes up your cell phone by making a native calling screen appear. Upon acceptance (a slider is shown instead of two buttons for the locked screen), the phone stays locked and boosts the call priority. Then, the app (which runs in the background during that time) starts publishing to OpenTok platform.

lock1 ---> lock2

  1. Without simulation, use a push server or NWPusher to call

This requires a few more steps to test:

- create your certificate
- configure your push notification backend or NWPusher
- locate your device token for testing (launch the app and get it from the console)
- send a remote notification from your backend or NWPusher

Notice: You might want to use OpenTok.js Sample App to test the sample app together.

Exploring the codes

A CXProvider object is responsible for reporting out-of-band notifications that occur to the system. To create one, you first need to initialize a CXProviderConfiguration object, which encapsulates the behaviors and capabilities of calls, to pass on to the CXProvider initializer. In order to receive telephony events of the provider, the provider needs to specify an object conforming to the CXProviderDelegate protocol.

// create a provider configuration
let localizedName = NSLocalizedString("CallKitDemo", comment: "Name of application")
let providerConfiguration = CXProviderConfiguration(localizedName: localizedName)
providerConfiguration.supportsVideo = false
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.phoneNumber]
providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(#imageLiteral(resourceName: "IconMask"))
providerConfiguration.ringtoneSound = "Ringtone.caf"

// set up a provider
provider = CXProvider(configuration: providerConfiguration)
provider.setDelegate(self, queue: nil)

The CXProviderDelegate protocol defines events of the telephony provider (CXProvider) such as the call starting, the call being put on hold, or the provider’s audio session is activated.

// MARK: CXProviderDelegate
func providerDidReset(_ provider: CXProvider) {
    print("Provider did reset")
}

func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
    print("Provider performs the start call action")

    /*
      Configure the audio session, but do not start call audio here, since it must be done once
      the audio session has been activated by the system after having its priority elevated.
    */
}

func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
    print("Provider performs the answer call action")

    /*
      Configure the audio session, but do not start call audio here, since it must be done once
      the audio session has been activated by the system after having its priority elevated.
    */
}

func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
    print("Provider performs the end call action")

    // Trigger the call to be ended via the underlying network service.
}

func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
    print("Provider performs the hold call action")
}

func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
    print("Provider performs the mute call action")
}

The following methods indicate whether your VoIP call has been successfully priority boosted or recovered.

func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
    print("Timed out \(#function)")
    // React to the action timeout if necessary, such as showing an error UI.
}

func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
    // Start call audio media, now that the audio session has been activated after having its priority boosted.
}

func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
    /*
        Restart any non-call related audio now that the app's audio session has been
        de-activated after having its priority restored to normal.
    */
}

Let's explore how to make a call and answer a call on behalf of a user. To do that, we need a CXCallController object to interact with the system.

The CXCallController object takes a CXTransaction object to request a telephony action (which will later trigger delegate methods above if succeed). To specify a telephony action in a transaction, you need to create your desired action object and associate them with the transaction. Each telephony action has a corresponding CXAction class such as CXEndCallAction for ending a call, CXSetHeldCallAction for setting a call on hold.

Once you have it all ready, invoke the request(_:completion:) by passing a ready transaction object. Here's how you start a call:

// create a CXAction
let startCallAction = CXStartCallAction(call: UUID(), handle: CXHandle(type: .phoneNumber, value: handle))

// create a transaction
let transaction = CXTransaction()
transaction.addAction(startCallAction)

// create a label
let action = "startCall"

callController.request(transaction) { error in
    if let error = error {
        print("Error requesting transaction: \(error)")
    } else {
        print("Requested transaction \(action) successfully")
    }
}

As for answering a call, the CallKit framework provides a convenient API to present a native calling UI like the screen-shot below. By invoking reportNewIncomingCall(with:update:completion:) on the provider, you will have the same experience as receiving a native phone call. Often, this piece of code works with VoIP remote notification to make calls to a device/person like WhatsApp, WeChat, and Messenger etc.

// Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)

// Report the incoming call to the system
provider.reportNewIncomingCall(with: uuid, update: update) { error in
    /*
      Only add incoming call to the app's list of calls if the call was allowed (i.e. there was no error)
      since calls may be "denied" for various legitimate reasons. See CXErrorCodeIncomingCallError.
    */
}

call

A glitch

There is a small issue when accepting a call from a locked screen. The underlying audio session does not get activated propertly inside the CallKit framework. Apple's engineers propose a workaround by setting up the audio session as early as possible to make the case work out temporarily:

then a workaround would be to configure your app's audio session (call `configureAudioSession()`) earlier in your app's lifecycle, before the `-provider:performAnswerCallAction:` method is invoked.

callkit's People

Contributors

jvalli avatar lucashuang0802 avatar mheap avatar oludemilade avatar pardel avatar robjperez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

callkit's Issues

Can this be used with video?

Hi,
Someone pointed me to this library. Is it possible to use this with opentok's multiparty video calling feature?
Thanks!

Hold state is not supported

When call is put on hold,
provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) is called,
where you end and remove the call.

This means there is no call to go back to when call is put off hold.

If you supported hold state you would find audio issues with this flow.
TokBox won't fix their issue as long as they can't reproduce it on this sample app.

Please fix the sample app. Thank you

(Adding this code in provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) would let you see the errors:
guard let call = outgoingCall, !call.isOnHold else { return })

basic_streambuf<char, std error

Hello Lucas,

I cloned the repo, attempted to build and received the errors in the attachment.

Running, Xcode: 9.2, Swift 4.

Please let me know what can be done to resolve.. Thanks. -- German

callkit-opentalk-build-errors

Ringtone in app

I'm making function turn on or off ringtone in my app.
I set ringtoneSound = nil for state off. But system ringtone still work. How can I turn off both?

Open Incoming Calling screen into my app

I want to open incoming call screen in my app itself. Right now call screen is shown into background, I have to go to background and select calling screen.

Is there any way that call should be made within my app ui and it does not redirect to background?

Dismissing call banner when source cancels the call.

Hi everyone 👋,

how can I dismiss the banner when the source cancels the call? OpenTok automatically does it when we create an OTSession.
Unfortunately, when using CallKit we cannot create the session until the call is answered.

According to the Apple docs we have to call reportCall(with:endedAt:reason:) with reason CXCallEndedReason.remoteEnded

Is there a way with OpenTok to know when the source hangs out the call before being answered?

Banner

Thank you!

Show custom UI after answer call from locked screen

If a user answers a call from the locked screen, the native iPhone call UI is displaying instead of the custom UI the app displays.

Is there any way to display app UI after a user answers when the phone is locked?

Video stream for multiple subscribers VoIP push issue

Hi, we have a video streaming app and we are using TokBox on our iOS app. I upgraded our iOS app SDK to iOS 13 and I cannot use VoIP notifications right now because apple has substituted something about VoIP push notification structure.

I am inviting my subscribers to the video stream using VoIP push notification.

Regarding Apple and iOS 13, we have to initiate the call from Callkit for VoIP background notifications. We don't want to use normal push notifications because CallKit UI looks nice. Do you have a solution for this? How can we handle this problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.