Getting Started
Dieser Inhalt ist in Ihrer Sprache noch nicht verfügbar.
Installation
npm install @capgo/capacitor-twilio-voicenpx cap syncyarn add @capgo/capacitor-twilio-voicenpx cap syncpnpm add @capgo/capacitor-twilio-voicenpx cap syncbun add @capgo/capacitor-twilio-voicenpx cap syncPrerequisites
You’ll need a Twilio account and access tokens for authentication. Sign up at Twilio if you don’t have an account.
Platform Configuration
iOS
Add required permissions to your Info.plist:
<key>NSMicrophoneUsageDescription</key><string>This app needs microphone access for voice calls</string>For incoming calls with PushKit:
- Enable Push Notifications in Xcode capabilities
- Add VoIP background mode
- Configure VoIP certificate in Twilio console
Android
Add required permissions to your AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />Configure Firebase for push notifications:
- Add
google-services.jsonto your Android project - Configure FCM in Twilio console
Usage Example
import { TwilioVoice } from '@capgo/capacitor-twilio-voice';
// Authenticate with Twilioawait TwilioVoice.login({ accessToken: 'your-twilio-access-token'});
// Make a callawait TwilioVoice.makeCall({ to: '+1234567890'});
// Listen for call eventsTwilioVoice.addListener('callConnected', (data) => { console.log('Call connected:', data.callSid);});
TwilioVoice.addListener('callDisconnected', (data) => { console.log('Call disconnected:', data.callSid);});
TwilioVoice.addListener('incomingCall', (data) => { console.log('Incoming call from:', data.from);
// Accept the call TwilioVoice.acceptCall({ callSid: data.callSid });
// Or reject it // TwilioVoice.rejectCall({ callSid: data.callSid });});
// Mute/unmute callawait TwilioVoice.muteCall({ muted: true, callSid: 'current-call-sid'});
// Toggle speakerawait TwilioVoice.setSpeaker({ enabled: true});
// End callawait TwilioVoice.endCall({ callSid: 'current-call-sid'});
// Logoutawait TwilioVoice.logout();API Reference
login(options)
login(options: { accessToken: string }) => Promise<void>Authenticate with Twilio using an access token.
| Param | Type |
|---|---|
options | { accessToken: string } |
logout()
logout() => Promise<void>End user session and clear call state.
isLoggedIn()
isLoggedIn() => Promise<{ loggedIn: boolean }>Check current authentication status.
Returns: Promise<{ loggedIn: boolean }>
makeCall(options)
makeCall(options: { to: string; params?: Record<string, string> }) => Promise<{ callSid: string }>Initiate an outgoing call to a specified number.
| Param | Type |
|---|---|
options | { to: string; params?: Record<string, string> } |
Returns: Promise<{ callSid: string }>
acceptCall(options)
acceptCall(options: { callSid: string }) => Promise<void>Accept an incoming call.
| Param | Type |
|---|---|
options | { callSid: string } |
rejectCall(options)
rejectCall(options: { callSid: string }) => Promise<void>Reject an incoming call.
| Param | Type |
|---|---|
options | { callSid: string } |
endCall(options?)
endCall(options?: { callSid?: string }) => Promise<void>Terminate an active call.
| Param | Type |
|---|---|
options | { callSid?: string } (optional) |
muteCall(options)
muteCall(options: { muted: boolean; callSid?: string }) => Promise<void>Mute or unmute call audio.
| Param | Type |
|---|---|
options | { muted: boolean; callSid?: string } |
setSpeaker(options)
setSpeaker(options: { enabled: boolean }) => Promise<void>Toggle speaker output.
| Param | Type |
|---|---|
options | { enabled: boolean } |
sendDigits(options)
sendDigits(options: { digits: string; callSid?: string }) => Promise<void>Send DTMF tones during a call.
| Param | Type |
|---|---|
options | { digits: string; callSid?: string } |
Event Listeners
Available Events
registered- Successfully registered with Twiliounregistered- Unregistered from TwilioregistrationFailed- Registration failedincomingCall- Incoming call receivedcallConnected- Call successfully connectedcallDisconnected- Call disconnectedcallRinging- Outgoing call is ringingcallReconnecting- Call is reconnectingcallReconnected- Call reconnected after interruptionqualityWarning- Call quality warningerror- An error occurred
Event Examples
// Handle incoming callsTwilioVoice.addListener('incomingCall', (data) => { console.log('Incoming call from:', data.from); console.log('Call SID:', data.callSid);
// Show incoming call UI showIncomingCallScreen({ from: data.from, callSid: data.callSid });});
// Handle call state changesTwilioVoice.addListener('callConnected', (data) => { console.log('Call connected:', data.callSid); startCallTimer();});
TwilioVoice.addListener('callDisconnected', (data) => { console.log('Call ended:', data.callSid); stopCallTimer(); hideCallScreen();});
// Handle quality warningsTwilioVoice.addListener('qualityWarning', (data) => { console.warn('Call quality warning:', data.warning); showQualityWarning(data.warning);});
// Handle errorsTwilioVoice.addListener('error', (error) => { console.error('Twilio error:', error.message); handleError(error);});
// Remove listeners when doneconst listener = await TwilioVoice.addListener('callConnected', (data) => { console.log('Connected');});
// Later...listener.remove();Complete Example
import { TwilioVoice } from '@capgo/capacitor-twilio-voice';
class VoiceCallService { private currentCallSid: string | null = null; private isMuted = false; private isSpeakerOn = false;
async initialize(accessToken: string) { try { // Login to Twilio await TwilioVoice.login({ accessToken });
// Check login status const { loggedIn } = await TwilioVoice.isLoggedIn(); console.log('Login status:', loggedIn);
// Setup event listeners this.setupEventListeners();
} catch (error) { console.error('Failed to initialize:', error); } }
setupEventListeners() { // Registration events TwilioVoice.addListener('registered', () => { console.log('Successfully registered with Twilio'); });
TwilioVoice.addListener('registrationFailed', (error) => { console.error('Registration failed:', error); });
// Incoming call TwilioVoice.addListener('incomingCall', async (data) => { console.log('Incoming call from:', data.from);
const accepted = await this.showIncomingCallDialog(data.from);
if (accepted) { await TwilioVoice.acceptCall({ callSid: data.callSid }); this.currentCallSid = data.callSid; } else { await TwilioVoice.rejectCall({ callSid: data.callSid }); } });
// Call events TwilioVoice.addListener('callConnected', (data) => { console.log('Call connected'); this.currentCallSid = data.callSid; this.showCallScreen(); });
TwilioVoice.addListener('callDisconnected', () => { console.log('Call disconnected'); this.currentCallSid = null; this.hideCallScreen(); });
TwilioVoice.addListener('callRinging', () => { console.log('Call ringing...'); });
// Quality warnings TwilioVoice.addListener('qualityWarning', (data) => { console.warn('Call quality warning:', data.warning); this.showQualityIndicator(data.warning); }); }
async makeCall(phoneNumber: string) { try { const result = await TwilioVoice.makeCall({ to: phoneNumber, params: { // Optional custom parameters customerId: 'customer-123' } });
this.currentCallSid = result.callSid; console.log('Call initiated:', result.callSid); } catch (error) { console.error('Failed to make call:', error); } }
async endCall() { if (this.currentCallSid) { await TwilioVoice.endCall({ callSid: this.currentCallSid }); this.currentCallSid = null; } }
async toggleMute() { this.isMuted = !this.isMuted; await TwilioVoice.muteCall({ muted: this.isMuted, callSid: this.currentCallSid || undefined }); }
async toggleSpeaker() { this.isSpeakerOn = !this.isSpeakerOn; await TwilioVoice.setSpeaker({ enabled: this.isSpeakerOn }); }
async sendDTMF(digits: string) { if (this.currentCallSid) { await TwilioVoice.sendDigits({ digits, callSid: this.currentCallSid }); } }
async logout() { await TwilioVoice.logout(); }
private async showIncomingCallDialog(from: string): Promise<boolean> { // Show native dialog or custom UI return confirm(`Incoming call from ${from}`); }
private showCallScreen() { // Show call UI console.log('Showing call screen'); }
private hideCallScreen() { // Hide call UI console.log('Hiding call screen'); }
private showQualityIndicator(warning: string) { // Show quality warning console.log('Quality warning:', warning); }}
// Usageconst voiceService = new VoiceCallService();
// Initialize with access token from your backendconst token = await fetchTwilioToken();await voiceService.initialize(token);
// Make a callawait voiceService.makeCall('+1234567890');
// Control callawait voiceService.toggleMute();await voiceService.toggleSpeaker();await voiceService.sendDTMF('1');
// End callawait voiceService.endCall();
// Logoutawait voiceService.logout();Best Practices
- Fetch access tokens from your backend server, never embed them in the app
- Implement token refresh logic for long-running sessions
- Handle network interruptions with reconnection logic
- Provide visual feedback for call states
- Test on actual devices with push notifications
- Implement proper error handling
- Clean up listeners when components unmount
- Request microphone permissions before making calls
Security Considerations
- Never store Twilio credentials in the app
- Generate access tokens on your backend
- Implement token expiration and refresh
- Use HTTPS for all token requests
- Validate incoming calls server-side
Troubleshooting
Calls Not Connecting
- Verify access token is valid and not expired
- Check network connectivity
- Ensure microphone permissions are granted
- Verify Twilio account is properly configured
Push Notifications Not Working
- Verify PushKit/FCM certificates are configured in Twilio
- Check device is registered for push notifications
- Test with production certificates
Audio Issues
- Check microphone permissions
- Verify speaker/bluetooth settings
- Test audio routing on actual devices