TwilioDevEd / client-quickstart-js-deprecated

Twilio Client Quickstart for Web/Javascript
MIT License
46 stars 48 forks source link

Cannot Answer Inbound Call #10

Open 6Hat opened 5 years ago

6Hat commented 5 years ago

In Google Chrome the inbound call only "rings" on occasions... but usually it just Answers automatically! In both Chrome and Edge there is no way to "Answer" the call? Outbound calls work great!

forrestedw commented 5 years ago

Can you say how to repeat this issue? I have started using the repo and don't have this issue. This is what I trimmed quickstart.js down to:

$(function () {

  var device;

  console.log('requesting capability token...');

  $.getJSON('twilio/token')

    .then(function (data) {
      console.log('capability token success')

      device = new Twilio.Device(data.token);

      device.on('ready',function (device) {
        console.log('device.on ready')
        $('#call-controls, #button-call').show();
      });

      device.on('error', function (error) {
        console.log('device.on error: ' + error.message);
      });

      device.on('connect', function (conn) {
        console.log('device.on connect');

        var twilio_call_sid = conn.parameters.CallSid;
        $('#call-id').val(twilio_call_sid);

        log_call_to_database(twilio_call_sid, 'connect');

        $('#button-call').hide();
        $('#button-hangup, #button-hold, #button-record-start').show();

        // volumeIndicators.style.display = 'block';
        // bindVolumeIndicators(conn);
      });

      device.on('disconnect', function (conn) {
        console.log('device.on disconnect');

        $('#call-id').val(conn.parameters.CallSid);

        $('#button-call').show();
        $('#button-hangup, [id*="button-record-"]').hide();

        //volumeIndicators.style.display = 'none';
      });

      device.on('incoming', function (conn) {
        console.log('device.on incoming');

        var twilio_call_sid = conn.parameters.CallSid;
        $('#call-id').val(twilio_call_sid);

        $('#button-call').hide();
        $('#button-answer').show();

        var blocked_number = '+12345678910';

        if (conn.parameters.From === blocked_number) {

          // conn.reject();
          // save_call(twilio_call_sid,'auto-rejected');

          // console.log('Blocked number. Call rejected.');     

        } else {

          conn.on('accept', function() {
            console.log('device.on accept');

            $('#button-answer').hide();
            $('#button-hangup, #button-hold, #button-record-start').show();

            log_call_to_database(twilio_call_sid, 'accepted');

          });

          $('#button-answer').on('click', function () {
            conn.accept();    
          });          

        }
      });

     //...
    // etc
6Hat commented 5 years ago

I will sift through your code and look for any changes that may resolve this issue... I am really hopefully as I am developing an app for our corporate office and I really need this to be solid. For now here is my quickstart which is really not altered:

$(function () {
  var speakerDevices = document.getElementById('speaker-devices');
  var ringtoneDevices = document.getElementById('ringtone-devices');
  var outputVolumeBar = document.getElementById('output-volume');
  var inputVolumeBar = document.getElementById('input-volume');
  var volumeIndicators = document.getElementById('volume-indicators');

  var device;

  log('Requesting Capability Token...');
    $.getJSON('/Comm/TwilioToken')
    .then(function (data) {
      log('Got a token.');
      console.log('Token: ' + data.token);

      // Setup Twilio.Device
      device = new Twilio.Device(data.token);

      device.on('ready',function (device) {
        log('Twilio.Device Ready!');
        document.getElementById('call-controls').style.display = 'block';
      });

      device.on('error', function (error) {
        log('Twilio.Device Error: ' + error.message);
      });

      device.on('connect', function (conn) {
        log('Successfully established call!');
        document.getElementById('button-call').style.display = 'none';
        document.getElementById('button-hangup').style.display = 'inline';
        volumeIndicators.style.display = 'block';
        bindVolumeIndicators(conn);
      });

      device.on('disconnect', function (conn) {
        log('Call ended.');
        document.getElementById('button-call').style.display = 'inline';
        document.getElementById('button-hangup').style.display = 'none';
        volumeIndicators.style.display = 'none';
      });

      device.on('incoming', function (conn) {
        log('Incoming connection from ' + conn.parameters.From);
        var archEnemyPhoneNumber = '+12093373517';

        if (conn.parameters.From === archEnemyPhoneNumber) {
          conn.reject();
          log('It\'s your nemesis. Rejected call.');
        } else {
          // accept the incoming connection and start two-way audio
            log('Incoming connection from ' + conn.parameters.From);

          conn.accept();
        }
      });

      setClientNameUI(data.identity);
      device.audio.on('deviceChange', updateAllDevices.bind(device));

      // Show audio selection UI if it is supported by the browser.
      if (device.audio.isOutputSelectionSupported) {
        document.getElementById('output-selection').style.display = 'block';
      }
    })
    .catch(function (err) {
      console.log(err);
      log('Could not get a token from server!');
    });

  // Bind button to make call
  document.getElementById('button-call').onclick = function () {
    // get the phone number to connect the call to
    var params = {
      To: document.getElementById('phone-number').value
    };

    console.log('Calling ' + params.To + '...');
    if (device) {
      device.connect(params);
    }
  };

  // Bind button to hangup call
  document.getElementById('button-hangup').onclick = function () {
    log('Hanging up...');
    if (device) {
      device.disconnectAll();
    }
  };

    document.getElementById('get-devices').onclick = function () {
        navigator.mediaDevices.getUserMedia({ audio: true })
            .then(updateAllDevices.bind(device));
    };

  speakerDevices.addEventListener('change', function() {
    var selectedDevices = [].slice.call(speakerDevices.children)
      .filter(function(node) { return node.selected; })
      .map(function(node) { return node.getAttribute('data-id'); });

    device.audio.speakerDevices.set(selectedDevices);
  });

  ringtoneDevices.addEventListener('change', function() {
    var selectedDevices = [].slice.call(ringtoneDevices.children)
      .filter(function(node) { return node.selected; })
      .map(function(node) { return node.getAttribute('data-id'); });

    device.audio.ringtoneDevices.set(selectedDevices);
  });

  function bindVolumeIndicators(connection) {
    connection.on('volume', function(inputVolume, outputVolume) {
      var inputColor = 'red';
      if (inputVolume < .50) {
        inputColor = 'green';
      } else if (inputVolume < .75) {
        inputColor = 'yellow';
      }

      inputVolumeBar.style.width = Math.floor(inputVolume * 300) + 'px';
      inputVolumeBar.style.background = inputColor;

      var outputColor = 'red';
      if (outputVolume < .50) {
        outputColor = 'green';
      } else if (outputVolume < .75) {
        outputColor = 'yellow';
      }

      outputVolumeBar.style.width = Math.floor(outputVolume * 300) + 'px';
      outputVolumeBar.style.background = outputColor;
    });
  }

  function updateAllDevices() {
    updateDevices(speakerDevices, device.audio.speakerDevices.get());
    updateDevices(ringtoneDevices, device.audio.ringtoneDevices.get());

    // updateDevices(speakerDevices, );
    // updateDevices(ringtoneDevices, device);
  }

  // Update the available ringtone and speaker devices
  function updateDevices(selectEl, selectedDevices) {
    selectEl.innerHTML = '';

    device.audio.availableOutputDevices.forEach(function(device, id) {
      var isActive = (selectedDevices.size === 0 && id === 'default');
      selectedDevices.forEach(function(device) {
        if (device.deviceId === id) { isActive = true; }
      });

      var option = document.createElement('option');
      option.label = device.label;
      option.setAttribute('data-id', id);
      if (isActive) {
        option.setAttribute('selected', 'selected');
      }
      selectEl.appendChild(option);
    });
  }

  // Activity log
  function log(message) {
    var logDiv = document.getElementById('log');
    logDiv.innerHTML += '<p>&gt;&nbsp;' + message + '</p>';
    logDiv.scrollTop = logDiv.scrollHeight;
  }

  // Set the client name in the UI
  function setClientNameUI(clientName) {
    var div = document.getElementById('client-name');
    div.innerHTML = 'Your client name: <strong>' + clientName +
      '</strong>';
  }
});
forrestedw commented 5 years ago

Here's the difference:

Under device.on('incoming', function (conn) { ... you directly have conn.accept(); which accepts the call automatically when an incoming call is detected.

I have this as conn.on('accept', function() { ... to trigger some actions when conn.accept(); is called, like so...:

    conn.on('accept', function() {
        console.log('device.on accept');

        $('#button-answer').hide();
        $('#button-hangup, #button-hold, #button-record-start').show();

        log_call_to_database(twilio_call_sid, 'accepted');

      });

... and then, most importantly for you, have conn.accept(); wrapped in a jQuery on click function so that it only gets called when the user clicks the answer button, like so:

      $('#button-answer').on('click', function () {
        conn.accept();    
      });          
6Hat commented 5 years ago

Cannot thank you enough! I was thinking I had to switch from Client to Desktop... this really saved me. Appreciate your time!!!

juliofihdeldev commented 4 years ago

Please can you share your code . @6Hat ?

HamzaNasim commented 4 years ago

Is there any event to find out if the user attend the call . I want to start a timer (call duration) when user pick a call.

forrestedw commented 4 years ago

Try something like this?

  $('#button-answer').on('click', function () {
    conn.accept();  
    functionThatStartsATimer()
  });  
HamzaNasim commented 4 years ago

@forrestedw yeah but this is for incoming calls. I'm talking about outbound calls.

chiangky commented 4 years ago

@forrestedw yeah but this is for incoming calls. I'm talking about outbound calls.

device.on('connect', function (conn) { log('Successfully established call!'); functionThatStartsATimer(); });