Loading...
Loading...
Build cross-platform VoIP calling apps with React Native using Telnyx Voice SDK. High-level reactive API with automatic lifecycle management, CallKit/ConnectionService integration, and push notifications. Use for mobile VoIP apps with minimal setup.
npx skill4agent add team-telnyx/skills telnyx-webrtc-client-react-native@telnyx/react-voice-commons-sdkPrerequisites: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See theskill in your server language plugin (e.g.,telnyx-webrtc-*,telnyx-python).telnyx-javascript
npm install @telnyx/react-voice-commons-sdkimport { TelnyxVoiceApp, createTelnyxVoipClient } from '@telnyx/react-voice-commons-sdk';
// Create VoIP client instance
const voipClient = createTelnyxVoipClient({
enableAppStateManagement: true, // Auto background/foreground handling
debug: true, // Enable logging
});
export default function App() {
return (
<TelnyxVoiceApp
voipClient={voipClient}
enableAutoReconnect={false}
debug={true}
>
<YourAppContent />
</TelnyxVoiceApp>
);
}import { createCredentialConfig } from '@telnyx/react-voice-commons-sdk';
const config = createCredentialConfig('sip_username', 'sip_password', {
debug: true,
pushNotificationDeviceToken: 'your_device_token',
});
await voipClient.login(config);import { createTokenConfig } from '@telnyx/react-voice-commons-sdk';
const config = createTokenConfig('your_jwt_token', {
debug: true,
pushNotificationDeviceToken: 'your_device_token',
});
await voipClient.loginWithToken(config);// Automatically reconnects using stored credentials
const success = await voipClient.loginFromStoredConfig();
if (!success) {
// No stored auth, show login UI
}import { useEffect, useState } from 'react';
function CallScreen() {
const [connectionState, setConnectionState] = useState(null);
const [calls, setCalls] = useState([]);
useEffect(() => {
// Subscribe to connection state
const connSub = voipClient.connectionState$.subscribe((state) => {
setConnectionState(state);
});
// Subscribe to active calls
const callsSub = voipClient.calls$.subscribe((activeCalls) => {
setCalls(activeCalls);
});
return () => {
connSub.unsubscribe();
callsSub.unsubscribe();
};
}, []);
return (/* UI */);
}useEffect(() => {
if (call) {
const sub = call.callState$.subscribe((state) => {
console.log('Call state:', state);
});
return () => sub.unsubscribe();
}
}, [call]);const call = await voipClient.newCall('+18004377950');TelnyxVoiceApp// Answer incoming call
await call.answer();
// Mute/Unmute
await call.mute();
await call.unmute();
// Hold/Unhold
await call.hold();
await call.unhold();
// End call
await call.hangup();
// Send DTMF
await call.dtmf('1');google-services.json// MainActivity.kt
import com.telnyx.react_voice_commons.TelnyxMainActivity
class MainActivity : TelnyxMainActivity() {
override fun onHandleIntent(intent: Intent) {
super.onHandleIntent(intent)
// Additional intent processing
}
}// index.js or App.tsx
import messaging from '@react-native-firebase/messaging';
import { TelnyxVoiceApp } from '@telnyx/react-voice-commons-sdk';
messaging().setBackgroundMessageHandler(async (remoteMessage) => {
await TelnyxVoiceApp.handleBackgroundPush(remoteMessage.data);
});// AppDelegate.swift
import PushKit
import TelnyxVoiceCommons
@UIApplicationMain
public class AppDelegate: ExpoAppDelegate, PKPushRegistryDelegate {
public override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
// Initialize VoIP push registration
TelnyxVoipPushHandler.initializeVoipRegistration()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// VoIP Push Token Update
public func pushRegistry(_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType) {
TelnyxVoipPushHandler.shared.handleVoipTokenUpdate(pushCredentials, type: type)
}
// VoIP Push Received
public func pushRegistry(_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void) {
TelnyxVoipPushHandler.shared.handleVoipPush(payload, type: type, completion: completion)
}
}Note: CallKit integration is automatically handled by the internal CallBridge component.
| Option | Type | Default | Description |
|---|---|---|---|
| boolean | true | Auto background/foreground handling |
| boolean | false | Enable debug logging |
| Prop | Type | Description |
|---|---|---|
| TelnyxVoipClient | The VoIP client instance |
| boolean | Auto-reconnect on disconnect |
| boolean | Enable debug logging |
@telnyx_username@telnyx_password@credential_token@push_tokenYou don't need to manage these manually.
| Issue | Solution |
|---|---|
| Double login | Don't call |
| Background disconnect | Check |
| Android push not working | Verify |
| iOS push not working | Ensure AppDelegate implements |
| Memory leaks | Unsubscribe from RxJS observables in useEffect cleanup |
| Audio issues | iOS audio handled by CallBridge; Android check ConnectionService |
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.multiRemove([
'@telnyx_username',
'@telnyx_password',
'@credential_token',
'@push_token',
]);login():config<Promise>void
CredentialConfigloginWithToken():config<Promise>void
TokenConfiglogout():<Promise>void
loginFromStoredConfig():<Promise>boolean
newCall(,destination,callerName?,callerNumber?):customHeaders?<Promise>Call
handlePushNotification():payload<Promise>void
disablePushNotifications():void
setCallConnecting():callIdvoid
findCallByTelnyxCall():telnyxCallCall
CallqueueAnswerFromCallKit():customHeadersvoid
queueEndFromCallKit():void
dispose():void
answer():customHeaders?<Promise>void
hangup():customHeaders?<Promise>void
hold():<Promise>void
resume():<Promise>void
mute():<Promise>void
unmute():<Promise>void
toggleMute():<Promise>void
setConnecting():void
dispose():void
RINGING:"RINGING"
CONNECTING:"CONNECTING"
ACTIVE:"ACTIVE"
HELD:"HELD"
ENDED:"ENDED"
FAILED:"FAILED"
DROPPED:"DROPPED"
DISCONNECTED:"DISCONNECTED"
CONNECTING:"CONNECTING"
CONNECTED:"CONNECTED"
RECONNECTING:"RECONNECTING"
<!-- END AUTO-GENERATED API REFERENCE -->ERROR:"ERROR"