1

As given in link https://github.com/twilio/voice-quickstart-android#bullet5,

we need to create TwiML application and voice Request url should be set for e.g. https://twiliodev.mycompany.com/makeCall to make call. Then what should be written in makecall function to connect the current call because if we use Dial verb then it make another call.

Note : I am using Twilio programmable voice to connect two Android device using VOIP.

Now the question is what Twiml response should be send in MakeCall function to get call connected, because in following function if I return blank response then call didn't connect.

[HttpPost]
public ActionResult MakeCall()
{
    var response = new VoiceResponse();
    return TwiML(response);
}

Edit @Alan Thanks to reply. As I am using c# at server side. I have used Dial Verb as

var dial = response.Dial(callerId: from);

Which Connect call and Immediately disconnect bcoz client verb is missing. Now how to append Client verb in Dial verb, I am using Client verb as

dial.Append(client);

and Twiml response is

 <Response>
    <Dial callerId="client:21f421792"></Dial>
    <Client>2170561
  </Client>
</Response>

And Its return schema error bcoz I think correct schema is

 <Response>
        <Dial callerId="client:21f421792">
        <Client>2170561
      </Client></Dial>
    </Response>

So can you please help how to add Client verb inside Call Verb.

Thanks.


Edit 2

As Suggested by @philnash this c# link is for Browser to client call and in that it uses new Dial client as

var dial = new Dial();

but I am using Android VOIP SDK to make call between two android devices. For which If I use new Dial object, it will place new Call as child call. Which I don't want to create. And As request by @philnash the complete code for makeCall function is

[HttpPost]
public ActionResult MakeCall()
{
    var response = new VoiceResponse();

    string from,to;

    if (Request.HttpMethod == HttpMethod.Post.Method)
    {
        from = Request.Form["From"];
        to = Request.Form["To"];
    }
    else
    {
        from = Request.QueryString["From"];
        to = Request.QueryString["To"];
    }

    var dial = response.Dial(callerId: from);
    var client = new Client(to);
    dial.Append(client);

    return TwiML(response);
}

Edit 3

<?xml version="1.0" encoding="utf-8"?>
<Response>
    <Dial>
    <Client>2170561
    </Client>
</Dial>
</Response>

As I have Noticed for VOIP call if Client xml tag is inside Dial tag then it successfully connect but it counts two legs for each call and charge for two calls. Is it the default behaviour of Twilio to leg two calls in each call when one device want to call to another device or Am I getting wrong ?

Again please note I am talking about two android device VOIP connection via Twiml request url to our server.

Giru Bhai
  • 14,370
  • 5
  • 46
  • 74
  • Not sure what's going on there, perhaps you could share the whole code rather than snippets? For reference, here's the C# example in the docs: https://www.twilio.com/docs/voice/twiml/client?code-sample=code-dialing-to-a-client-2&code-language=C%23&code-sdk-version=5.x – philnash Mar 19 '20 at 04:12
  • @philnash this link twilio.com/docs/voice/twiml/… is for Dialing web to client and I am using client to client calling (note client means two android devices). Please check edited question, Thanks. – Giru Bhai Mar 19 '20 at 06:02
  • Dialling web to client is the same as client to client (in fact, the only difference you get is if you dial client to phone and then you need a callerId to be a number from your account). If you are `Append`ing the `client` to the `dial` it really should be nested in the XML output. That is weird behaviour. Also, I'm not sure what you mean about child calls, when you have two endpoints (2 clients in this case) there will be two legs to the call and one _will_ be the child. – philnash Mar 19 '20 at 06:58
  • @philnash thanks to reply, then how Twilio charged, if child call status as no-answer. – Giru Bhai Mar 19 '20 at 07:10
  • If there’s no answer on the child leg, I think you get charged for the amount of time it takes to ring. Pricing is not my area of expertise though, you might find it better to [talk to sales about that](https://www.twilio.com/help/sales). – philnash Mar 19 '20 at 07:33
  • @philnash can you please have a look at Edit 3 section of question. – Giru Bhai Mar 19 '20 at 07:38
  • 1
    You do get charged for two call legs, yes. One call leg is from the first device to Twilio and the second call leg is from Twilio to the second device. Check this article for details: https://support.twilio.com/hc/en-us/articles/223180608-How-Does-Twilio-Client-Pricing-Work- – philnash Mar 19 '20 at 07:42

1 Answers1

2

If you are trying to connect to Mobile Programmable Voice SDK powered devices together, you would use the Dial verb with Client noun. The Client noun would be the identity/name of the other client you are trying to call.

TwiML™ Voice:

Twilio has a serverless Function that has the example code below used to place a call and based on the To number your client side POSTs to the makeCall end-point, it determines if it is a PSTN phone call or client-to-client phone call, const attr = isAValidPhoneNumber(event.To) ? 'number' : 'client';. That code is copied below.

exports.handler = function(context, event, callback) {
    let twiml = new Twilio.twiml.VoiceResponse();

    if(event.To) {
      // Wrap the phone number or client name in the appropriate TwiML verb
      // if is a valid phone number
      const attr = isAValidPhoneNumber(event.To) ? 'number' : 'client';

      const dial = twiml.dial({
        callerId: context.CALLER_ID,
      });
      dial[attr]({}, event.To);
    } else {
      twiml.say('Thanks for calling!');
    }

     callback(null, twiml);
};

/**
* Checks if the given value is valid as phone number
* @param {Number|String} number
* @return {Boolean}
*/

function isAValidPhoneNumber(number) {
  return /^[\d\+\-\(\) ]+$/.test(number);
}
Alan
  • 10,465
  • 2
  • 8
  • 9