Learn Skype Web SDK Day 22 : Receiving an Incoming Audio Call
This is one post in a series of more than 30, devoted to helping you get up to speed quickly with the new Skype Web SDK. Each lesson comes with source code (in GitHub) and a working demo page so you can see what it does. Check out the full list of posts on the Skype Web SDK page.
View Demo
We’ve previously covered how to identify and respond to incoming Instant Message conversations. Doing the same thing for Audio calls is fairly similar – the only real difference is that instead of using chatService
, instead it’s audioService
.
When a new conversation request is received by the Skype for Web API, it is added to the list of conversations managed by the conversationsManager. By monitoring new conversations being added here you can then take actions when they appear.
You can register an event listener for new conversations being added with the event listener:
var client = new Skype.Web.Model.Application; //perform sign in client.conversationsManager.conversations.added(function (newConversation) { //do something with newConversation });
Obviously there is only one conversationsManager
and if you’re starting your own conversations as well then conversations will be being added and removed from this fairly regularly. There are two important things you should check for to know whether this is a incoming conversation you need to act on. You should check that you are able to accept the conversation, and that the conversation is in the right state to be accepted.
The first thing you need to do is check to see whether this is an audio call which you are able to accept, by evaluating:
newConversation.audioService.accept.enabled()
Secondly, you should evaluate the state of the conversation. A conversation moves through various states during its lifetime and checking the current state will make sure you don’t try and accept or reject a conversation that isn’t ready for it. If the conversation state is Notified then it means that the conversation is waiting for an invitation decision to be made: i.e. it’s ready to be accepted or declined:
newConversation.audioService.state() == 'Notified'
Putting the two together gives you:
var client; //instantiate client object and perform sign in client.conversationsManager.conversations.added(function (newConversation) { if (newConversation.audioService.accept.enabled() && newConversation.audioService.state() == 'Notified') { //accept or reject invite } });
Actually accepting or rejecting the conversation invitation is easy:
newConversation.audioService.accept();
or
newConversation.audioService.reject();
Because we’ve already done something pretty similar for Instant Messaging, I though this time it would be more fun to use toastr.js to actually display the incoming alert. This was actually pretty easy:
var msg = '<div>Incoming Call from ' + conversation.participants()[0].name() + '<br/><button id="btnAccept" class="btn btn-success">Accept</button><button id="btnReject" class="btn btn-danger">Reject</button>'; var $toast = toastr["info"](msg, "Accept"); if ($toast.find('#btnAccept').length) { $toast.delegate('#btnAccept', 'click', function () { AcceptConversation(); $toast.remove(); }); } if ($toast.find('#btnReject').length) { $toast.delegate('#btnReject', 'click', function () { RejectConversation(); $toast.remove(); }); }
First I build up the content of toast, containing the name of the caller, and two buttons to accept or reject the call. Then I call toastr and get a handle to the actual toast object. This causes the toast to be displayed. Finally, I add the functions for the button clicks to accept or reject the conversation. Have a look at the example for this post to see this, including the extra initialising stuff to set the style etc.
<div class="form-horizontal"> <div class="form-group"> <label for="username" class="col-sm-2 control-label">Username</label> <div class="col-sm-10"> <input type="email" class="form-control" id="username" placeholder="Email"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">Password</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" placeholder="Password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnLogIn">Log in</button> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-default" id="btnLogOut">Log out</button> </div> </div> </div> <div> <span id="loginStatus"></span> <br/> Audio Status: <span id="lblAudioStatus"></span> </div> <hr/> <div id="footer"></div> <!-- This is not needed for the samples to run, but adds standard headers and footers to the samples, to display title, instructions, about etc. If you're taking this code and using it yourself, you can remove this.--> <script type="text/javascript" src="../../assets/layoutcodesample-min.js"></script> <script type="text/javascript"> <!-- These variables are only needed for laying out the code sample, they are not part of the sample code. --> var pageTitle = 'Receiving a New Audio Conversation'; var blogPostLocation = "http://thoughtstuff.co.uk"; var githubLocation = "http://github.com"; var activeConversation; var client; $(function () { 'use strict'; Skype.initialize({ apiKey: 'SWX-BUILD-SDK', }, function (api) { client = new api.application(); // whenever client.state changes, display its value client.signInManager.state.changed(function (state) { $('#loginStatus').text("Login State: " + state); }); }, function (err) { alert('Error loading Skype Web SDK: ' + err); }); $('#btnLogIn').click(function () { // start signing in client.signInManager.signIn({ username: $('#username').val(), password: $('#password').val() }).then(function () { //log in worked! alert('Logged in!'); }, function (error) { //Something went wrong. alert(error); }); }); $('#btnLogOut').click(function () { // start signing out client.signInManager.signOut() .then(function () { //log out worked! alert('Logged out!'); $('#btnStartConversation').prop('disabled', true); $('#btnSendIM').prop('disabled', true); }, function (error) { //Something went wrong. alert(error); }); }); client.conversationsManager.conversations.added(function (conversation) { if (conversation.audioService.accept.enabled() &amp;&amp; conversation.audioService.state() == 'Notified') { //incoming audio call activeConversation = conversation; //wire up audio state events conversation.selfParticipant.audio.state.changed(function (newState) { $('#lblAudioStatus').text(newState); }); var msg = '<div>Incoming Call from ' + conversation.participants()[0].name() + '<br/><button id="btnAccept" class="btn btn-success">Accept</button><button id="btnReject" class="btn btn-danger">Reject</button>'; var $toast = toastr["info"](msg, "Accept"); if ($toast.find('#btnAccept').length) { $toast.delegate('#btnAccept', 'click', function () { AcceptConversation(); $toast.remove(); }); } if ($toast.find('#btnReject').length) { $toast.delegate('#btnReject', 'click', function () { RejectConversation(); $toast.remove(); }); } } }) }); function InitialiseToastr() { toastr.options = { "closeButton": true, "debug": false, "newestOnTop": false, "progressBar": false, "positionClass": "toast-bottom-right", "preventDuplicates": false, "timeOut": "15000", "extendedTimeOut": "15000", "showEasing": "swing", "hideEasing": "linear", "showMethod": "fadeIn", "hideMethod": "fadeOut", }; } function AcceptConversation() { activeConversation.audioService.accept(); } function RejectConversation() { activeConversation.audioService.reject(); } </script>
Demo Online
You can try this code out against your own Skype for Business environment by going to the demo page. From here you can also download the code from GitHub if you want to host it locally, or take it and use it in your next project.
Good to Know
- Before you can run this code, make sure you've read my post on all the prerequisites you need to have in place.
- You don't have to copy the code from here - it's all on GitHub!
- If you liked this post, there are more! Check out the dedicated Skype for Web SDK Collection page, or signup to the newsletter
- Need a Skype for Web SDK solution, but not in a position to build yourself? Hire me!