Loading...
Loading...
Compare original and translation side by side
@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
@telnyx/react-voice-commons-sdk前提条件:创建WebRTC凭证,并使用Telnyx服务端SDK生成登录令牌。请参考对应服务端语言插件中的skill(例如telnyx-webrtc-*、telnyx-python)。telnyx-javascript
npm install @telnyx/react-voice-commons-sdknpm 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 { TelnyxVoiceApp, createTelnyxVoipClient } from '@telnyx/react-voice-commons-sdk';
// 创建VoIP客户端实例
const voipClient = createTelnyxVoipClient({
enableAppStateManagement: true, // 自动处理前后台切换
debug: true, // 开启日志
});
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 { 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);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
}// 使用已存储的凭证自动重连
const success = await voipClient.loginFromStoredConfig();
if (!success) {
// 无已存储的身份信息,展示登录界面
}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 */);
}import { useEffect, useState } from 'react';
function CallScreen() {
const [connectionState, setConnectionState] = useState(null);
const [calls, setCalls] = useState([]);
useEffect(() => {
// 订阅连接状态
const connSub = voipClient.connectionState$.subscribe((state) => {
setConnectionState(state);
});
// 订阅活跃通话
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]);useEffect(() => {
if (call) {
const sub = call.callState$.subscribe((state) => {
console.log('通话状态:', state);
});
return () => sub.unsubscribe();
}
}, [call]);const call = await voipClient.newCall('+18004377950');const call = await voipClient.newCall('+18004377950');TelnyxVoiceAppTelnyxVoiceApp// 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');// 接听来电
await call.answer();
// 静音/取消静音
await call.mute();
await call.unmute();
// 保持/取消保持
await call.hold();
await call.unhold();
// 挂断通话
await call.hangup();
// 发送DTMF信号
await call.dtmf('1');google-services.jsongoogle-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
}
}// MainActivity.kt
import com.telnyx.react_voice_commons.TelnyxMainActivity
class MainActivity : TelnyxMainActivity() {
override fun onHandleIntent(intent: Intent) {
super.onHandleIntent(intent)
// 额外的intent处理逻辑
}
}// 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);
});// index.js 或 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.
// 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 {
// 初始化VoIP推送注册
TelnyxVoipPushHandler.initializeVoipRegistration()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// VoIP推送令牌更新
public func pushRegistry(_ registry: PKPushRegistry,
didUpdate pushCredentials: PKPushCredentials,
for type: PKPushType) {
TelnyxVoipPushHandler.shared.handleVoipTokenUpdate(pushCredentials, type: type)
}
// 收到VoIP推送
public func pushRegistry(_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void) {
TelnyxVoipPushHandler.shared.handleVoipPush(payload, type: type, completion: completion)
}
}注意:CallKit集成由内部CallBridge组件自动处理。
| Option | Type | Default | Description |
|---|---|---|---|
| boolean | true | Auto background/foreground handling |
| boolean | false | Enable debug logging |
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| 布尔值 | true | 自动处理前后台切换 |
| 布尔值 | false | 开启调试日志 |
| Prop | Type | Description |
|---|---|---|
| TelnyxVoipClient | The VoIP client instance |
| boolean | Auto-reconnect on disconnect |
| boolean | Enable debug logging |
| 属性 | 类型 | 说明 |
|---|---|---|
| TelnyxVoipClient | VoIP客户端实例 |
| 布尔值 | 断开连接时自动重连 |
| 布尔值 | 开启调试日志 |
@telnyx_username@telnyx_password@credential_token@push_tokenYou don't need to manage these manually.
@telnyx_username@telnyx_password@credential_token@push_token你无需手动管理这些键。
| 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 |
| 问题 | 解决方案 |
|---|---|
| 重复登录 | 当 |
| 后台断开连接 | 检查 |
| 安卓推送不生效 | 验证 |
| iOS推送不生效 | 确保AppDelegate实现了 |
| 内存泄漏 | 在useEffect清理函数中取消RxJS observable订阅 |
| 音频问题 | iOS音频由CallBridge处理;安卓请检查ConnectionService配置 |
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.multiRemove([
'@telnyx_username',
'@telnyx_password',
'@credential_token',
'@push_token',
]);import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.multiRemove([
'@telnyx_username',
'@telnyx_password',
'@credential_token',
'@push_token',
]);login():config<Promise>void
login():config<Promise>void
CredentialConfigCredentialConfigloginWithToken():config<Promise>void
loginWithToken():config<Promise>void
TokenConfigTokenConfiglogout():<Promise>void
logout():<Promise>void
loginFromStoredConfig():<Promise>boolean
loginFromStoredConfig():<Promise>boolean
newCall(,destination,callerName?,callerNumber?):customHeaders?<Promise>Call
newCall(,destination,callerName?,callerNumber?):customHeaders?<Promise>Call
handlePushNotification():payload<Promise>void
handlePushNotification():payload<Promise>void
disablePushNotifications():void
disablePushNotifications():void
setCallConnecting():callIdvoid
setCallConnecting():callIdvoid
findCallByTelnyxCall():telnyxCallCall
findCallByTelnyxCall():telnyxCallCall
CallCallqueueAnswerFromCallKit():customHeadersvoid
queueAnswerFromCallKit():customHeadersvoid
queueEndFromCallKit():void
queueEndFromCallKit():void
dispose():void
dispose():void
answer():customHeaders?<Promise>void
answer():customHeaders?<Promise>void
hangup():customHeaders?<Promise>void
hangup():customHeaders?<Promise>void
hold():<Promise>void
hold():<Promise>void
resume():<Promise>void
resume():<Promise>void
mute():<Promise>void
mute():<Promise>void
unmute():<Promise>void
unmute():<Promise>void
toggleMute():<Promise>void
toggleMute():<Promise>void
setConnecting():void
setConnecting():void
dispose():void
dispose():void
RINGING:"RINGING"
RINGING:"RINGING"
CONNECTING:"CONNECTING"
CONNECTING:"CONNECTING"
ACTIVE:"ACTIVE"
ACTIVE:"ACTIVE"
HELD:"HELD"
HELD:"HELD"
ENDED:"ENDED"
ENDED:"ENDED"
FAILED:"FAILED"
FAILED:"FAILED"
DROPPED:"DROPPED"
DROPPED:"DROPPED"
DISCONNECTED:"DISCONNECTED"
DISCONNECTED:"DISCONNECTED"
CONNECTING:"CONNECTING"
CONNECTING:"CONNECTING"
CONNECTED:"CONNECTED"
CONNECTED:"CONNECTED"
RECONNECTING:"RECONNECTING"
RECONNECTING:"RECONNECTING"
<!-- END AUTO-GENERATED API REFERENCE -->ERROR:"ERROR"
<!-- END AUTO-GENERATED API REFERENCE -->ERROR:"ERROR"