Commencer
Installation
Section titled “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 syncPrérequis
Section titled “Prérequis”Vous aurez besoin d’un compte Twilio et de jetons d’accès pour l’authentification. Inscrivez-vous sur Twilio si vous n’avez pas de compte.
Configuration de plateforme
Section titled “Configuration de plateforme”Ajoutez les permissions requises à votre Info.plist :
<key>NSMicrophoneUsageDescription</key><string>This app needs microphone access for voice calls</string>Pour les appels entrants avec PushKit :
- Activez les notifications push dans les capacités Xcode
- Ajoutez le mode en arrière-plan VoIP
- Configurez le certificat VoIP dans la console Twilio
Android
Section titled “Android”Ajoutez les permissions requises à votre 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" />Configurez Firebase pour les notifications push :
- Ajoutez
google-services.jsonà votre projet Android - Configurez FCM dans la console Twilio
Exemple d’utilisation
Section titled “Exemple d’utilisation”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();Référence API
Section titled “Référence API”login(options)
Section titled “login(options)”login(options: { accessToken: string }) => Promise<void>S’authentifier avec Twilio en utilisant un jeton d’accès.
| Param | Type |
|---|---|
options | { accessToken: string } |
logout()
Section titled “logout()”logout() => Promise<void>Terminer la session utilisateur et effacer l’état de l’appel.
isLoggedIn()
Section titled “isLoggedIn()”isLoggedIn() => Promise<{ loggedIn: boolean }>Vérifier l’état d’authentification actuel.
Retourne : Promise<{ loggedIn: boolean }>
makeCall(options)
Section titled “makeCall(options)”makeCall(options: { to: string; params?: Record<string, string> }) => Promise<{ callSid: string }>Initier un appel sortant vers un numéro spécifié.
| Param | Type |
|---|---|
options | { to: string; params?: Record<string, string> } |
Retourne : Promise<{ callSid: string }>
acceptCall(options)
Section titled “acceptCall(options)”acceptCall(options: { callSid: string }) => Promise<void>Accepter un appel entrant.
| Param | Type |
|---|---|
options | { callSid: string } |
rejectCall(options)
Section titled “rejectCall(options)”rejectCall(options: { callSid: string }) => Promise<void>Rejeter un appel entrant.
| Param | Type |
|---|---|
options | { callSid: string } |
endCall(options?)
Section titled “endCall(options?)”endCall(options?: { callSid?: string }) => Promise<void>Terminer un appel actif.
| Param | Type |
|---|---|
options | { callSid?: string } (optionnel) |
muteCall(options)
Section titled “muteCall(options)”muteCall(options: { muted: boolean; callSid?: string }) => Promise<void>Activer ou désactiver le son de l’appel.
| Param | Type |
|---|---|
options | { muted: boolean; callSid?: string } |
setSpeaker(options)
Section titled “setSpeaker(options)”setSpeaker(options: { enabled: boolean }) => Promise<void>Basculer la sortie haut-parleur.
| Param | Type |
|---|---|
options | { enabled: boolean } |
sendDigits(options)
Section titled “sendDigits(options)”sendDigits(options: { digits: string; callSid?: string }) => Promise<void>Envoyer des tonalités DTMF pendant un appel.
| Param | Type |
|---|---|
options | { digits: string; callSid?: string } |
Écouteurs d’événements
Section titled “Écouteurs d’événements”Événements disponibles
Section titled “Événements disponibles”registered- Enregistré avec succès auprès de Twiliounregistered- Désenregistré de TwilioregistrationFailed- Échec de l’enregistrementincomingCall- Appel entrant reçucallConnected- Appel connecté avec succèscallDisconnected- Appel déconnectécallRinging- L’appel sortant sonnecallReconnecting- L’appel se reconnectecallReconnected- Appel reconnecté après une interruptionqualityWarning- Avertissement de qualité d’appelerror- Une erreur s’est produite
Exemples d’événements
Section titled “Exemples d’événements”// 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();Exemple complet
Section titled “Exemple complet”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();Bonnes pratiques
Section titled “Bonnes pratiques”- Récupérez les jetons d’accès depuis votre serveur backend, ne les intégrez jamais dans l’application
- Implémentez une logique de rafraîchissement des jetons pour les sessions de longue durée
- Gérez les interruptions réseau avec une logique de reconnexion
- Fournissez des retours visuels pour les états d’appel
- Testez sur des appareils réels avec des notifications push
- Implémentez une gestion appropriée des erreurs
- Nettoyez les écouteurs lorsque les composants sont démontés
- Demandez les permissions du microphone avant d’effectuer des appels
Considérations de sécurité
Section titled “Considérations de sécurité”- Ne stockez jamais les identifiants Twilio dans l’application
- Générez les jetons d’accès sur votre backend
- Implémentez l’expiration et le rafraîchissement des jetons
- Utilisez HTTPS pour toutes les requêtes de jetons
- Validez les appels entrants côté serveur
Dépannage
Section titled “Dépannage”Les appels ne se connectent pas
Section titled “Les appels ne se connectent pas”- Vérifiez que le jeton d’accès est valide et n’a pas expiré
- Vérifiez la connectivité réseau
- Assurez-vous que les permissions du microphone sont accordées
- Vérifiez que le compte Twilio est correctement configuré
Les notifications push ne fonctionnent pas
Section titled “Les notifications push ne fonctionnent pas”- Vérifiez que les certificats PushKit/FCM sont configurés dans Twilio
- Vérifiez que l’appareil est enregistré pour les notifications push
- Testez avec des certificats de production
Problèmes audio
Section titled “Problèmes audio”- Vérifiez les permissions du microphone
- Vérifiez les paramètres du haut-parleur/bluetooth
- Testez le routage audio sur des appareils réels
Affichage du nom de l’appelant (CapacitorTwilioCallerName)
Section titled “Affichage du nom de l’appelant (CapacitorTwilioCallerName)”Par défaut, les appels entrants affichent le numéro de téléphone ou l’ID client de l’appelant. Vous pouvez personnaliser cela en passant un paramètre CapacitorTwilioCallerName depuis votre backend TwiML pour afficher un nom convivial à la place.
Configuration du backend
Section titled “Configuration du backend”Lors de la génération de votre réponse TwiML pour le cadran <Client>, ajoutez le paramètre CapacitorTwilioCallerName :
// Java exampleParameter callerNameParam = new Parameter.Builder() .name("CapacitorTwilioCallerName") .value("John Doe") .build();
Client client = new Client.Builder(identity) .parameter(callerNameParam) .build();
Dial dial = new Dial.Builder() .client(client) .build();// Node.js exampleconst VoiceResponse = require('twilio').twiml.VoiceResponse;
const response = new VoiceResponse();const dial = response.dial();dial.client({ name: 'CapacitorTwilioCallerName', value: 'John Doe'}, identity);Comment ça fonctionne
Section titled “Comment ça fonctionne”- Lorsque votre backend reçoit un appel entrant, il génère du TwiML pour acheminer l’appel
- Incluez le paramètre
CapacitorTwilioCallerNameavec le nom d’affichage de l’appelant - Le plugin extrait automatiquement ce paramètre et l’utilise pour :
- L’écran d’appel entrant iOS CallKit
- La notification d’appel entrant Android
- Le champ
fromdans les événementsincomingCall - Le tableau
pendingInvitesdans l’état de l’appel
Si CapacitorTwilioCallerName n’est pas fourni, le plugin revient au numéro de téléphone ou à l’ID client de l’appelant.