Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to Make Outgoing Calls Using Twilio Voice React Native SDK in Expo Managed Workflow #437

Open
ihorMarynichZazmic opened this issue Oct 16, 2024 · 18 comments

Comments

@ihorMarynichZazmic
Copy link

Description
I'm unable to make outgoing calls using Twilio Voice React Native SDK in Expo Managed Workflow. The following error appears when attempting to make a call:

Error: Failed to initialize PushKit device token
I'm currently focusing on outgoing calls only, but I plan to add support for incoming calls later.

Reproduction Steps
Generate Twilio Access Token using generateTwillioVoiceAccessToken.
Attempt to make an outgoing call using voice.connect().
The error message related to PushKit appears.
Expected Behavior
I expect outgoing calls to work without requiring PushKit initialization.

Actual Behavior
Outgoing calls fail due to PushKit initialization errors, despite not needing incoming calls functionality.

Reproduction Frequency
Occurs 100% of the time.

Software and Device Information
Device: iPhone 12
OS: iOS 16
React version: 18.2.0
React Native version: 0.74.3
Node version: 18.20.4
npm version: 9.6.7

Additional Context
I'm currently using the SDK only for outgoing calls. However, I plan to add incoming calls support in the future. How can I bypass PushKit initialization for now to enable outgoing calls only?

@bobiechen-twilio
Copy link
Collaborator

Hi @ihorMarynichZazmic

Thanks for reaching out.
The PushKit error message is only printed/returned when using the Voice.register() (or unregister()) method which should not block the app from making outbound calls using the Voice.connect() method.

@ihorMarynichZazmic
Copy link
Author

Hi @bobiechen-twilio
Thank you for the clarification! I’m currently using the Expo Managed Workflow, focusing solely on outbound calls for now, but I plan to integrate incoming call functionality in the future. I understand that the PushKit error shouldn't affect making outbound calls. However, after calling voice.connect(), the call is not initiated, and there are no errors shown in the console. Could there be additional steps or configurations needed specifically for Expo? Thanks again for your help!

@bobiechen-twilio
Copy link
Collaborator

Did you see any exception or did the promise not returning any error?
Also are you able to run the app using the Xcode debugger and see if there are additional debug messages?

@ihorMarynichZazmic
Copy link
Author

ihorMarynichZazmic commented Oct 16, 2024

@bobiechen-twilio
Thank you for the response!

I don’t see any exceptions, and the promise isn’t returning any errors. Here's the code I'm using for making the outbound call:

`const makeCall = async () => {
try {
console.log('Checking for Twilio token');
if (!twilioToken) {
console.error('Twilio token is missing');
return;
}

console.log('Starting call with number:', '**********');
const call = await voice.connect(twilioToken, {
  params: { To: '**********' },
});

console.log('Call connected, call state:', call);
setCallStatus('Call connected');

call.on(Voice.Event.Disconnected, () => {
  console.log('Call disconnected');
  setCallStatus('Call disconnected');
});

} catch (error) {
console.error('Error making the call', error);
}
};`

I reach the state where the log prints console.log('Starting call with number:', '**********'); but after that, nothing happens, and no errors are returned.

@bobiechen-twilio
Copy link
Collaborator

Hi @ihorMarynichZazmic

Are you able to run the app from the Xcode debugger? At this point we might need the debug messages from the native ObjC layer in case something went wrong here.

@DiazIgnacio
Copy link

@bobiechen-twilio Thank you for the response!

I don’t see any exceptions, and the promise isn’t returning any errors. Here's the code I'm using for making the outbound call:

`const makeCall = async () => { try { console.log('Checking for Twilio token'); if (!twilioToken) { console.error('Twilio token is missing'); return; }

console.log('Starting call with number:', '**********');
const call = await voice.connect(twilioToken, {
  params: { To: '**********' },
});

console.log('Call connected, call state:', call);
setCallStatus('Call connected');

call.on(Voice.Event.Disconnected, () => {
  console.log('Call disconnected');
  setCallStatus('Call disconnected');
});

} catch (error) { console.error('Error making the call', error); } };`

I reach the state where the log prints console.log('Starting call with number:', '**********'); but after that, nothing happens, and no errors are returned.

Exactly the same happening to me, I added the contactHandle prop as well since it says that it's required for iOS

@DiazIgnacio
Copy link

I was able to solve this by including this configuration in the app.json or app.config.js file:

"ios": {
          ...your_ios_config,
          "infoPlist": {
            "UIBackgroundModes": [
              "audio",
              "fetch",
              "location",
              "remote-notification",
              "voip"
            ],
            "NSMicrophoneUsageDescription": "This app requires access to the microphone to make voice calls.",
            "com.apple.developer.pushkit.unrestricted-voip": true
          }
        }

@ihorMarynichZazmic
Copy link
Author

@DiazIgnacio are you implementing it for React Native CLI or React Native Expo?
If in Expo, what approach are you using to integrate voice calls (Manager Flow or Bare Flow)?

@ihorMarynichZazmic
Copy link
Author

@DiazIgnacio @bobiechen-twilio

I added the following configuration to my React Native project:

"ios": {
...your_ios_config,
"infoPlist": {
"UIBackgroundModes": [
"audio",
"fetch",
"location",
"remote-notification",
"voip"
],
"NSMicrophoneUsageDescription": "This app requires access to the microphone to make voice calls.",
"com.apple.developer.pushkit.unrestricted-voip": true
}
}

Then I built the project using the command npx expo run:ios --configuration Debugt (Managed Flow).

Issue: I successfully receive the Twilio token, and the call status moves to initiated, but nothing happens after that — the call remains in the connecting state. The logs confirm that the token is received and the call is initiated, but further events like connected or ringing do not trigger.

LOG Starting call with TOKEN: <Encrypted_Token>
LOG Call initiated: {"_customParameters": {}, "_events": {}, "_eventsCount": 0, "_from": undefined, "_state": "connecting", ... }

Code used for initiating the call:
const handleCall = async () => {
if (twilioToken) {
try {
console.log("Starting call with TOKEN:", twilioToken);
setCallStatus("Connecting...");

  const outgoingCall = await voice.connect(twilioToken, {
    params: {
      To: `+1${phoneNumber.replace(/\D/g, '')}`,
      recipientType: "ios",
    },
  });

  setActiveCall(outgoingCall);
  console.log("Call initiated:", outgoingCall);

  outgoingCall.on(Voice.Event.Connected, () => {
    setCallStatus("Connected");
    console.log("Call is now connected");
  });

  outgoingCall.on(Voice.Event.ConnectFailure, (error) => {
    console.error("ConnectFailure:", error);
    setCallStatus("Connection failed");
  });

  outgoingCall.on(Voice.Event.Ringing, () => {
    setCallStatus("Ringing...");
    console.log("Call is ringing on the recipient's device");
  });

  // Other event handlers
} catch (error) {
  console.error("Error making call:", error);
  setCallStatus("Error making call");
}

} else {
console.error("No token available");
setCallStatus("No token available");
}
};

Questions:
What additional configurations might be necessary to transition the call from connecting to connected or ringing on iOS?
Could this issue be related to using the Managed Flow in Expo, and if so, are there any workarounds for fully supporting VoIP calls?
Are there specific settings required to ensure events like Connected, Ringing, and others trigger as expected?

@DiazIgnacio
Copy link

@DiazIgnacio are you implementing it for React Native CLI or React Native Expo? If in Expo, what approach are you using to integrate voice calls (Manager Flow or Bare Flow)?

Expo with a managed flow

@DiazIgnacio
Copy link

@DiazIgnacio @bobiechen-twilio

I added the following configuration to my React Native project:

"ios": { ...your_ios_config, "infoPlist": { "UIBackgroundModes": [ "audio", "fetch", "location", "remote-notification", "voip" ], "NSMicrophoneUsageDescription": "This app requires access to the microphone to make voice calls.", "com.apple.developer.pushkit.unrestricted-voip": true } }

Then I built the project using the command npx expo run:ios --configuration Debugt (Managed Flow).

Issue: I successfully receive the Twilio token, and the call status moves to initiated, but nothing happens after that — the call remains in the connecting state. The logs confirm that the token is received and the call is initiated, but further events like connected or ringing do not trigger.

LOG Starting call with TOKEN: <Encrypted_Token> LOG Call initiated: {"_customParameters": {}, "_events": {}, "_eventsCount": 0, "_from": undefined, "_state": "connecting", ... }

Code used for initiating the call: const handleCall = async () => { if (twilioToken) { try { console.log("Starting call with TOKEN:", twilioToken); setCallStatus("Connecting...");

  const outgoingCall = await voice.connect(twilioToken, {
    params: {
      To: `+1${phoneNumber.replace(/\D/g, '')}`,
      recipientType: "ios",
    },
  });

  setActiveCall(outgoingCall);
  console.log("Call initiated:", outgoingCall);

  outgoingCall.on(Voice.Event.Connected, () => {
    setCallStatus("Connected");
    console.log("Call is now connected");
  });

  outgoingCall.on(Voice.Event.ConnectFailure, (error) => {
    console.error("ConnectFailure:", error);
    setCallStatus("Connection failed");
  });

  outgoingCall.on(Voice.Event.Ringing, () => {
    setCallStatus("Ringing...");
    console.log("Call is ringing on the recipient's device");
  });

  // Other event handlers
} catch (error) {
  console.error("Error making call:", error);
  setCallStatus("Error making call");
}

} else { console.error("No token available"); setCallStatus("No token available"); } };

Questions: What additional configurations might be necessary to transition the call from connecting to connected or ringing on iOS? Could this issue be related to using the Managed Flow in Expo, and if so, are there any workarounds for fully supporting VoIP calls? Are there specific settings required to ensure events like Connected, Ringing, and others trigger as expected?

Are you running it in the simulator? Note that the twilio sdk doesn't work in the simulator.

@ihorMarynichZazmic
Copy link
Author

I have made build Expo with a managed flow
And I used real phone (Iphone 13)

@DiazIgnacio
Copy link

Did you initialize the push registry from your voice instance?

const voice = new Voice();
await voice.initializePushRegistry();

Or are you managing the PushKit on your own?

@ihorMarynichZazmic
Copy link
Author

ihorMarynichZazmic commented Oct 25, 2024

I’ve tried both with voice.initializePushRegistry() and without it, but the result is the same. Here’s the method I’m using to fetch the Twilio token:

const fetchTwilioToken = async () => {
try {
console.log('Fetching Twilio token...');
const payload = { teamId, identity: identity.substring(0, 12) };
const response = await generateTwillioVoiceAccessToken(payload);
const newToken = response.data.token;
setTwilioToken(newToken);
console.log('Twilio token fetched:', newToken);

  await voice.register(newToken);
  await voice.initializePushRegistry();
  console.log('Voice client registered with token');
} catch (error) {
  console.error('Error fetching Twilio token:', error);
}

};
To start, I’m focusing on implementing only outgoing calls without receiving incoming calls. So, if I understand correctly, PushKit shouldn’t be necessary in this case, right?

@DiazIgnacio
Copy link

You may be right about the push registry, so for implementing only for outgoing calls I'd remove this two lines since they're not necessary:

  await voice.register(newToken);
  await voice.initializePushRegistry();

@ihorMarynichZazmic
Copy link
Author

ihorMarynichZazmic commented Oct 25, 2024

@DiazIgnacio
I removed, but nothing changes
I am still in the status of ‘Call initiated’.

Maybe you have instructions on how to set up a React Native Expo App with the Twilio Voice SDK?
Or do you have an example of a simple component to make a call under these conditions?

@mhuynh5757
Copy link
Collaborator

Hi @ihorMarynichZazmic is this related to the new issue that you filed #442 ?

@ihorMarynichZazmic
Copy link
Author

I describe what problems I have on the frontend part of the application at this issue, and I describe what problems I have on the backend part of the application at #442.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants