@capgo/capacitor-twilio-voice

中文文档
8.2.28发布于 2026/11/02MPL-2.0TypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 8.2万

Integrates the Twilio Voice SDK into Capacitor

原始使用文档
文档目录59 节
  1. Capacitor Twilio Voice Plugin
  2. ➡️ Get started for free
  3. Key features
  4. Documentation
  5. Compatibility
  6. Installation
  7. iOS Setup
  8. 1. Install the plugin
  9. 2. Setup CustomCapacitorViewController.swift
  10. 3. Edit Main.storyboard
  11. 4. Setup Info.plist
  12. Android Setup
  13. 1. Firebase Setup
  14. Twilio Setup
  15. Caller Name Display (CapacitorTwilioCallerName)
  16. Backend Setup
  17. How It Works
  18. Usage
  19. Authentication
  20. Event Listeners
  21. JWT Token Management
  22. Token Format
  23. Token Validation
  24. Backend Integration
  25. Testing Requirements
  26. iOS Simulator Limitations
  27. Android Emulator
  28. Error Handling
  29. Security Notes
  30. Platform Support
  31. API
  32. login(...)
  33. logout()
  34. isLoggedIn()
  35. makeCall(...)
  36. acceptCall(...)
  37. rejectCall(...)
  38. endCall(...)
  39. muteCall(...)
  40. setSpeaker(...)
  41. getCallStatus()
  42. checkMicrophonePermission()
  43. requestMicrophonePermission()
  44. addListener('callInviteReceived', ...)
  45. addListener('callConnected', ...)
  46. addListener('callInviteCancelled', ...)
  47. addListener('outgoingCallInitiated', ...)
  48. addListener('outgoingCallFailed', ...)
  49. addListener('callDisconnected', ...)
  50. addListener('callRinging', ...)
  51. addListener('callReconnecting', ...)
  52. addListener('callReconnected', ...)
  53. addListener('callQualityWarningsChanged', ...)
  54. addListener('registrationSuccess', ...)
  55. addListener('registrationFailure', ...)
  56. removeAllListeners()
  57. getPluginVersion()
  58. Interfaces
  59. Type Aliases

Capacitor Twilio Voice Plugin

Make and receive phone calls in your Capacitor app with the Twilio Voice SDK, using CallKit on iOS and native call notifications on Android.

Capgo - Build Capacitor apps with AI, ship updates instantly

Capgo: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and roll back in one click.

➡️ Get started for free

14-day unlimited free trial. No credit card required

🤖 Building with an AI coding agent? Install Capgo skills so Claude Code, Codex, Cursor, Copilot, or Gemini CLI know how to install and use @capgo/capacitor-twilio-voice in your Capacitor app: npx skills add Cap-go/capgo-skills. Then ask your agent: "Add @capgo/capacitor-twilio-voice to my Capacitor app and wire it up." Agent setup guides · Hosted MCP

@capgo/capacitor-twilio-voice for Capacitor apps

Key features

  • Calls: makeCall(), acceptCall(), rejectCall() and endCall().
  • In-call controls: muteCall(), setSpeaker() and getCallStatus().
  • Incoming calls: push-based call invites with PushKit and CallKit on iOS and Firebase Messaging on Android.
  • Events: invite, ringing, connected, disconnected, reconnecting and call quality warnings.
  • Session: login() with a Twilio access token, isLoggedIn() and logout().
  • Platforms: iOS and Android. Not available on web. login(), isLoggedIn() and getCallStatus() throw on web.

Documentation

The most complete doc is available here: https://capgo.app/docs/plugins/twilio-voice/

Compatibility

Plugin versionCapacitor compatibilityMaintained
v8.*.*v8.*.*✅
v7.*.*v7.*.*On demand
v6.*.*v6.*.*❌
v5.*.*v5.*.*❌

Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.

Installation

You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:

npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins

Then use the following prompt:

Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-twilio-voice` plugin in my project.

If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:

npm install @capgo/capacitor-twilio-voice
npx cap sync

iOS Setup

1. Install the plugin

npm install @capgo/capacitor-twilio-voice
npx cap sync

2. Setup CustomCapacitorViewController.swift

Copy the code from example-app/ios/App/App/CustomCapacitorViewController.swift to your ios/App/App/CustomCapacitorViewController.swift file.

  1. Modify AppDelegate.swift

Add the following to AppDelegate.swift:

import UIKit
import Capacitor
+ import PushKit
+ import CapgoCapacitorTwilioVoice

@UIApplicationMain
- class AppDelegate: UIResponder, UIApplicationDelegate {
+ class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate {

    var window: UIWindow?
+     var pushKitEventDelegate: PushKitEventDelegate?
+     var voipRegistry = PKPushRegistry.init(queue: DispatchQueue.main)

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
+         
+         /*
+          * Your app must initialize PKPushRegistry with PushKit push type VoIP at the launch time. As mentioned in the
+          * [PushKit guidelines](https://developer.apple.com/documentation/pushkit/supporting_pushkit_notifications_in_your_app),
+          * the system can't deliver push notifications to your app until you create a PKPushRegistry object for
+          * VoIP push type and set the delegate. If your app delays the initialization of PKPushRegistry, your app may receive outdated
+          * PushKit push notifications, and if your app decides not to report the received outdated push notifications to CallKit, iOS may
+          * terminate your app.
+          */
+         initializePushKit()
+         
+         guard let viewController = UIApplication.shared.windows.first?.rootViewController as? CustomCapacitorViewController else {
+             fatalError("Root view controller is not Capacitor view controller")
+         }
+         
+         viewController.passPushKitEventDelegate = { delegate in
+             self.pushKitEventDelegate = delegate
+         }
+         
+         // self.pushKitEventDelegate = viewController
+         
        return true
    }
+     
+     func initializePushKit() {
+         voipRegistry.delegate = self
+         voipRegistry.desiredPushTypes = Set([PKPushType.voIP])
+     }

    // ... (existing lifecycle methods remain the same) ...

+     // MARK: PKPushRegistryDelegate
+     func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
+         NSLog("pushRegistry:didUpdatePushCredentials:forType:")
+         
+         if let delegate = self.pushKitEventDelegate {
+             delegate.credentialsUpdated(credentials: credentials)
+         }
+     }
+     
+     func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
+         NSLog("pushRegistry:didInvalidatePushTokenForType:")
+         
+         if let delegate = self.pushKitEventDelegate {
+             delegate.credentialsInvalidated()
+         }
+     }
+ 
+     /**
+      * Try using the `pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:` method if
+      * your application is targeting iOS 11. According to the docs, this delegate method is deprecated by Apple.
+      */
+     func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
+         NSLog("pushRegistry:didReceiveIncomingPushWithPayload:forType:")
+         
+         if let delegate = self.pushKitEventDelegate {
+             delegate.incomingPushReceived(payload: payload)
+         }
+     }
+ 
+     /**
+      * This delegate method is available on iOS 11 and above. Call the completion handler once the
+      * notification payload is passed to the `TwilioVoiceSDK.handleNotification()` method.
+      */
+     func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
+         NSLog("pushRegistry:didReceiveIncomingPushWithPayload:forType:completion:")
+ 
+         if let delegate = self.pushKitEventDelegate {
+             delegate.incomingPushReceived(payload: payload, completion: completion)
+         }
+         
+         if let version = Float(UIDevice.current.systemVersion), version >= 13.0 {
+             /**
+              * The Voice SDK processes the call notification and returns the call invite synchronously. Report the incoming call to
+              * CallKit and fulfill the completion before exiting this callback method.
+              */
+             completion()
+         }
+     }

}

3. Edit Main.storyboard

Change the view controller to CustomCapacitorViewController in Main.storyboard.

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14111" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
    </dependencies>
    <scenes>
        <!--Bridge View Controller-->
        <scene sceneID="the-QT-ifu">
            <objects>
-                <viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
+                <viewController id="BYZ-38-t0r" customClass="CustomCapacitorViewController" customModule="App" customModuleProvider="target" sceneMemberID="viewController"/>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>

Look in the example app for more details.

4. Setup Info.plist

Add the following to ios/App/App/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>This app uses the microphone for voice calls</string>

<key>UIBackgroundModes</key>
<array>
    <string>voip</string>
    <string>audio</string>
</array>
  1. Make sure you have the following capabilities enabled in Xcode:
  • Push Notifications
  • Background Modes
  1. Generate the certificate for Push Notifications

In order to generate the certificate for Push Notifications, you need to follow these steps:

  1. Generate the signing certificate for your app.
openssl genrsa -out ALDsigning.key 2048
  1. Generate the signing request.
openssl req -new -key ALDsigning.key -out csr3072ALDSigning.certSigningRequest -subj "/[email protected], CN=Example Name, C=IE"

Then, please upload it to your Apple Developer account here. Search for Create a new VoIP Services Certificate

  1. Download the file provided by Apple.

  2. Extract the .p12 file from the downloaded file.

openssl pkcs12 -export -out voip_services.p12 -inkey ALDsigning.key -in voip_services.cer
  1. Export the cert.pem and key.pem files from the .p12 file.
openssl pkcs12 -in voip_services.p12 -nokeys -out cert.pem -nodes
openssl pkcs12 -in voip_services.p12 -nocerts -out key.pem -nodes
  1. Upload the cert.pem and key.pem files twilio.
npx twilio api:chat:v2:credentials:create --type=apn --sandbox --friendly-name="voice-push-credential (sandbox)" --certificate="$(cat /Users/your_username/Documents/twilio-voip/cert.pem)" --private-key="$(cat /Users/your_username/Documents/twilio-voip/key.pem)"

Android Setup

1. Firebase Setup

Add Firebase to your Android project:

  1. Add google-services.json to android/app/

  2. Add CapacitorApplication.java to android/app/src/main/java/YOUR_APP_PACKAGE/CapacitorApplication.java Copy the content of example-app/android/app/src/main/java/com/example/plugin/CapacitorApplication.java to your android/app/src/main/java/YOUR_APP_PACKAGE/CapacitorApplication.java file.

  3. Import androidx.webkit:webkit in build.gradle (module :app)

dependencies {
+     implementation 'androidx.webkit:$androidxWebkitVersion'
}
  1. Modify MainActivity.java

Add the following to MainActivity.java:

package com.example.plugin;

import android.net.Uri;
import android.os.Bundle;
import android.webkit.ValueCallback;

import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewFeature;

import com.getcapacitor.BridgeActivity;
import com.getcapacitor.JSExport;
import com.getcapacitor.Logger;
import com.getcapacitor.PluginHandle;

+ import java.util.ArrayList;
+ import java.util.Collections;

import ee.forgr.capacitor_twilio_voice.CapacitorTwilioVoicePlugin;

public class MainActivity extends BridgeActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
+         
+         this.bridge.registerPluginInstance(CapacitorTwilioVoicePlugin.getInstance());
+         ArrayList<PluginHandle> pluginHandles = new ArrayList<>();
+         pluginHandles.add(this.bridge.getPlugin("CapacitorTwilioVoice"));
+         String pluginJS = JSExport.getPluginJS(pluginHandles);
+         if (WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) {
+             String allowedOrigin = Uri.parse(this.bridge.getAppUrl()).buildUpon().path(null).fragment(null).clearQuery().build().toString();
+             try {
+                 WebViewCompat.addDocumentStartJavaScript(this.getBridge().getWebView(), pluginJS, Collections.singleton(allowedOrigin));
+             } catch (IllegalArgumentException ex) {
+                 Logger.warn("Invalid url, using fallback");
+             }
+         }
    }
}
  1. Register the plugin in JS
+ import { CapacitorTwilioVoice } from '@capgo/capacitor-twilio-voice';
+ import { Capacitor } from '@capacitor/core';

+ Capacitor.registerPlugin('CapacitorTwilioVoice');
  1. Add android:name="CapacitorApplication" to the application tag in android/app/src/main/AndroidManifest.xml

  2. Add the following to android/app/src/main/AndroidManifest.xml:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.TURN_SCREEN_ON" />
    <uses-permission android:name="android.permission.SHOW_WHEN_LOCKED" />

Keep in mind, this will make it so that you app can be accessed when the screen is locked.

Twilio Setup

Caller Name Display (CapacitorTwilioCallerName)

By default, incoming calls display the caller's phone number or client ID. You can customize this by passing a CapacitorTwilioCallerName parameter from your TwiML backend to display a friendly name instead.

Backend Setup

When generating your TwiML response for the <Client> dial, add the CapacitorTwilioCallerName parameter:

// Java example (see exemple-backend for full implementation)
Parameter 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 example
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const dial = response.dial();
dial.client({
  name: 'CapacitorTwilioCallerName',
  value: 'John Doe'
}, identity);

How It Works

  1. When your backend receives an incoming call, it generates TwiML to route the call
  2. Include the CapacitorTwilioCallerName parameter with the caller's display name
  3. The plugin automatically extracts this parameter and uses it for:
    • iOS CallKit incoming call screen
    • Android incoming call notification
    • The from field in callInviteReceived events
    • The pendingInvites array in getCallStatus()

If CapacitorTwilioCallerName is not provided, the plugin falls back to the caller's phone number or client ID.

Usage

Authentication

login(options: { accessToken: string })

Authenticates with Twilio using a JWT access token:

  • Validates token expiration automatically
  • Stores token securely for app restarts
  • Registers for VoIP push notifications
  • Note: The plugin will reject expired tokens

logout()

Logs out the current user and cleans up all session data:

  • Unregisters from VoIP push notifications
  • Clears stored access tokens
  • Ends any active calls
  • Resets all call state

isLoggedIn()

Checks if user is currently logged in with a valid (non-expired) token. Returns: { isLoggedIn: boolean, hasValidToken: boolean, identity?: string }

The identity field contains the user identity extracted from the JWT token if logged in.

makeCall(options: { to: string })

Initiates an outgoing call. Requires prior authentication via login().

acceptCall(options: { callSid: string })

Accepts an incoming call.

rejectCall(options: { callSid: string })

Rejects an incoming call.

endCall(options?: { callSid?: string })

Ends the active call or a specific call.

muteCall(options: { muted: boolean, callSid?: string })

Mutes or unmutes the microphone.

setSpeaker(options: { enabled: boolean })

Enables or disables the speaker. On Android, uses Twilio AudioSwitch to manage audio routing between earpiece, speaker, and connected devices (headsets, Bluetooth, etc.).

getCallStatus()

Gets the current call status.

checkMicrophonePermission()

Checks if microphone permission is granted.

requestMicrophonePermission()

Requests microphone permission from the user.

Event Listeners

import { CapacitorTwilioVoice } from '@capgo/capacitor-twilio-voice';

// Registration events
CapacitorTwilioVoice.addListener('registrationSuccess', (data) => {
  console.log('Successfully registered:', data);
});

CapacitorTwilioVoice.addListener('registrationFailure', (data) => {
  console.error('Registration failed:', data);
});

// Call events
CapacitorTwilioVoice.addListener('callInviteReceived', (data) => {
  console.log('Incoming call from:', data.from);
});

CapacitorTwilioVoice.addListener('callConnected', (data) => {
  console.log('Call connected:', data);
});

CapacitorTwilioVoice.addListener('callDisconnected', (data) => {
  console.log('Call ended:', data);
});

CapacitorTwilioVoice.addListener('callRinging', (data) => {
  console.log('Call is ringing:', data);
});

CapacitorTwilioVoice.addListener('callReconnecting', (data) => {
  console.log('Call reconnecting:', data);
});

CapacitorTwilioVoice.addListener('callReconnected', (data) => {
  console.log('Call reconnected:', data);
});

CapacitorTwilioVoice.addListener('callQualityWarningsChanged', (data) => {
  console.log('Quality warnings:', data);
});

JWT Token Management

Token Format

The plugin expects Twilio access tokens in JWT format with this structure:

{
  "iss": "your-account-sid",
  "exp": 1234567890,
  "grants": {
    "voice": {
      "outgoing": {
        "application_sid": "your-app-sid"
      },
      "push_credential_sid": "your-push-credential-sid"
    },
    "identity": "user-identity"
  }
}

Token Validation

  • Tokens are automatically validated for expiration
  • Invalid or expired tokens will be rejected
  • Use isLoggedIn() to check token status

Backend Integration

Fetch access tokens from your backend server:

async function fetchAccessToken(identity: string): Promise<string> {
  const response = await fetch(`/accessToken?identity=${identity}`);
  return response.text();
}

Testing Requirements

iOS Simulator Limitations

  • VoIP push notifications don't work in the iOS Simulator
  • Use a physical iOS device for testing incoming calls
  • Outgoing calls work in both Simulator and device

Android Emulator

  • Requires Google Play Services
  • Firebase messaging works in Android Emulator with Google APIs

Error Handling

The plugin provides detailed error information:

try {
  await CapacitorTwilioVoice.makeCall({ to: '+1234567890' });
} catch (error) {
  console.error('Call failed:', error);
}

Common error scenarios:

  • Invalid token: Check token format and expiration
  • No microphone permission: Call requestMicrophonePermission()
  • Network issues: Verify internet connectivity
  • Invalid phone number: Use E.164 format (+1234567890)

Security Notes

  • Access tokens are stored in secure device storage
  • Tokens are automatically validated before use
  • No sensitive data is logged in production builds
  • Always use HTTPS for token fetching from your backend

Platform Support

PlatformSupportNotes
iOS✅Requires iOS 13.0+
Android✅Requires API level 23+
Web❌Not supported

API

login(...)

login(options: { accessToken: string; }) => Promise<{ success: boolean; }>

Authenticate the user with Twilio Voice using an access token.

The access token should be generated on your backend server using your Twilio credentials. This token is required to make and receive calls through Twilio Voice.

ParamTypeDescription
options{ accessToken: string; }- Configuration object

Returns: Promise<{ success: boolean; }>


logout()

logout() => Promise<{ success: boolean; }>

Log out the current user and unregister from Twilio Voice.

This will disconnect any active calls and stop the device from receiving new incoming call notifications.

Returns: Promise<{ success: boolean; }>


isLoggedIn()

isLoggedIn() => Promise<{ isLoggedIn: boolean; hasValidToken: boolean; identity?: string; }>

Check if the user is currently logged in and has a valid access token.

Returns: Promise<{ isLoggedIn: boolean; hasValidToken: boolean; identity?: string; }>


makeCall(...)

makeCall(options: { to: string; displayName?: string; callerId?: string; }) => Promise<{ success: boolean; callSid?: string; }>

Initiate an outgoing call to a phone number or client.

The user must be logged in before making a call. The call will be routed through your Twilio backend configuration.

ParamTypeDescription
options{ to: string; displayName?: string; callerId?: string; }- Configuration object

Returns: Promise<{ success: boolean; callSid?: string; }>


acceptCall(...)

acceptCall(options: { callSid: string; }) => Promise<{ success: boolean; }>

Accept an incoming call.

This should be called in response to a 'callInviteReceived' event.

ParamTypeDescription
options{ callSid: string; }- Configuration object

Returns: Promise<{ success: boolean; }>


rejectCall(...)

rejectCall(options: { callSid: string; }) => Promise<{ success: boolean; }>

Reject an incoming call.

This should be called in response to a 'callInviteReceived' event. The caller will hear a busy signal or be directed to voicemail.

ParamTypeDescription
options{ callSid: string; }- Configuration object

Returns: Promise<{ success: boolean; }>


endCall(...)

endCall(options: { callSid?: string; }) => Promise<{ success: boolean; }>

End an active call.

If callSid is not provided, this will end the currently active call.

ParamTypeDescription
options{ callSid?: string; }- Configuration object

Returns: Promise<{ success: boolean; }>


muteCall(...)

muteCall(options: { muted: boolean; callSid?: string; }) => Promise<{ success: boolean; }>

Mute or unmute the microphone during an active call.

When muted, the other party will not hear audio from your microphone.

ParamTypeDescription
options{ muted: boolean; callSid?: string; }- Configuration object

Returns: Promise<{ success: boolean; }>


setSpeaker(...)

setSpeaker(options: { enabled: boolean; }) => Promise<{ success: boolean; }>

Enable or disable speakerphone mode.

When enabled, audio will be routed through the device's speaker instead of the earpiece.

ParamTypeDescription
options{ enabled: boolean; }- Configuration object

Returns: Promise<{ success: boolean; }>


getCallStatus()

getCallStatus() => Promise<{ hasActiveCall: boolean; isOnHold: boolean; isMuted: boolean; callSid?: string; callState?: string; pendingInvites: CallInvite[]; activeCallsCount: number; }>

Get the current status of the active call.

This provides real-time information about the call state, mute status, hold status, and call identifiers.

Returns: Promise<{ hasActiveCall: boolean; isOnHold: boolean; isMuted: boolean; callSid?: string; callState?: string; pendingInvites: CallInvite[]; activeCallsCount: number; }>


checkMicrophonePermission()

checkMicrophonePermission() => Promise<{ granted: boolean; }>

Check if microphone permission has been granted.

This does not request permission, only checks the current permission status.

Returns: Promise<{ granted: boolean; }>


requestMicrophonePermission()

requestMicrophonePermission() => Promise<{ granted: boolean; }>

Request microphone permission from the user.

On iOS and Android, this will show the system permission dialog if permission has not been granted yet. If permission was previously denied, the user may need to grant it in system settings.

Returns: Promise<{ granted: boolean; }>


addListener('callInviteReceived', ...)

addListener(eventName: 'callInviteReceived', listenerFunc: (data: CallInvite) => void) => Promise<PluginListenerHandle>

Listen for incoming call invitations.

This event is fired when another user or phone number is calling you. You should call acceptCall() or rejectCall() in response.

ParamTypeDescription
eventName'callInviteReceived'- The event name ('callInviteReceived')
listenerFunc(data: CallInvite) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callConnected', ...)

addListener(eventName: 'callConnected', listenerFunc: (data: { callSid: string; }) => void) => Promise<PluginListenerHandle>

Listen for call connected events.

This event is fired when a call (incoming or outgoing) has been successfully connected and audio can be heard.

ParamTypeDescription
eventName'callConnected'- The event name ('callConnected')
listenerFunc(data: { callSid: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callInviteCancelled', ...)

addListener(eventName: 'callInviteCancelled', listenerFunc: (data: { callSid: string; reason: 'user_declined' | 'remote_cancelled'; }) => void) => Promise<PluginListenerHandle>

Listen for call invite cancellation events.

This event is fired when an incoming call invitation is cancelled before being answered, either by the caller hanging up or by the user declining.

ParamTypeDescription
eventName'callInviteCancelled'- The event name ('callInviteCancelled')
listenerFunc(data: { callSid: string; reason: 'user_declined' | 'remote_cancelled'; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('outgoingCallInitiated', ...)

addListener(eventName: 'outgoingCallInitiated', listenerFunc: (data: { callSid: string; to: string; source: 'app' | 'system'; displayName?: string; }) => void) => Promise<PluginListenerHandle>

Listen for outgoing call initiation events.

This event is fired when an outgoing call is initiated, either from the app or from the system (e.g., CallKit on iOS, Telecom on Android).

ParamTypeDescription
eventName'outgoingCallInitiated'- The event name ('outgoingCallInitiated')
listenerFunc(data: { callSid: string; to: string; source: 'app' | 'system'; displayName?: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('outgoingCallFailed', ...)

addListener(eventName: 'outgoingCallFailed', listenerFunc: (data: { callSid: string; to: string; reason: 'missing_access_token' | 'connection_failed' | 'no_call_details' | 'microphone_permission_denied' | 'invalid_contact' | 'callkit_request_failed' | 'unsupported_intent'; displayName?: string; }) => void) => Promise<PluginListenerHandle>

Listen for outgoing call failure events.

This event is fired when an outgoing call fails to connect due to various reasons such as missing credentials, permission issues, or network problems.

ParamTypeDescription
eventName'outgoingCallFailed'- The event name ('outgoingCallFailed')
listenerFunc(data: { callSid: string; to: string; reason: 'missing_access_token' | 'connection_failed' | 'no_call_details' | 'microphone_permission_denied' | 'invalid_contact' | 'callkit_request_failed' | 'unsupported_intent'; displayName?: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callDisconnected', ...)

addListener(eventName: 'callDisconnected', listenerFunc: (data: { callSid: string; error?: string; }) => void) => Promise<PluginListenerHandle>

Listen for call disconnection events.

This event is fired when a call ends, either normally or due to an error.

ParamTypeDescription
eventName'callDisconnected'- The event name ('callDisconnected')
listenerFunc(data: { callSid: string; error?: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callRinging', ...)

addListener(eventName: 'callRinging', listenerFunc: (data: { callSid: string; }) => void) => Promise<PluginListenerHandle>

Listen for call ringing events.

This event is fired when an outgoing call starts ringing on the other end.

ParamTypeDescription
eventName'callRinging'- The event name ('callRinging')
listenerFunc(data: { callSid: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callReconnecting', ...)

addListener(eventName: 'callReconnecting', listenerFunc: (data: { callSid: string; error?: string; }) => void) => Promise<PluginListenerHandle>

Listen for call reconnecting events.

This event is fired when a call loses connection and Twilio is attempting to reconnect. The call is not disconnected yet but audio may be interrupted.

ParamTypeDescription
eventName'callReconnecting'- The event name ('callReconnecting')
listenerFunc(data: { callSid: string; error?: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callReconnected', ...)

addListener(eventName: 'callReconnected', listenerFunc: (data: { callSid: string; }) => void) => Promise<PluginListenerHandle>

Listen for call reconnected events.

This event is fired when a call successfully reconnects after a connection loss. Audio should resume normally after this event.

ParamTypeDescription
eventName'callReconnected'- The event name ('callReconnected')
listenerFunc(data: { callSid: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('callQualityWarningsChanged', ...)

addListener(eventName: 'callQualityWarningsChanged', listenerFunc: (data: { callSid: string; currentWarnings: string[]; previousWarnings: string[]; }) => void) => Promise<PluginListenerHandle>

Listen for call quality warning events.

This event is fired when the call quality changes, providing warnings about potential issues like high jitter, packet loss, or low audio levels.

ParamTypeDescription
eventName'callQualityWarningsChanged'- The event name ('callQualityWarningsChanged')
listenerFunc(data: { callSid: string; currentWarnings: string[]; previousWarnings: string[]; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('registrationSuccess', ...)

addListener(eventName: 'registrationSuccess', listenerFunc: () => void) => Promise<PluginListenerHandle>

Listen for successful registration events.

This event is fired when the device successfully registers with Twilio Voice and is ready to make and receive calls. This typically occurs after a successful login with a valid access token.

ParamTypeDescription
eventName'registrationSuccess'- The event name ('registrationSuccess')
listenerFunc() => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


addListener('registrationFailure', ...)

addListener(eventName: 'registrationFailure', listenerFunc: (data: { error: string; }) => void) => Promise<PluginListenerHandle>

Listen for registration failure events.

This event is fired when the device fails to register with Twilio Voice, typically due to an invalid or expired access token, network issues, or Twilio service problems.

ParamTypeDescription
eventName'registrationFailure'- The event name ('registrationFailure')
listenerFunc(data: { error: string; }) => void- Callback function to handle the event

Returns: Promise<PluginListenerHandle>


removeAllListeners()

removeAllListeners() => Promise<void>

Remove all registered event listeners.

This is useful for cleanup when your component unmounts or when you want to reset all event handling.


getPluginVersion()

getPluginVersion() => Promise<{ version: string; }>

Get the native Capacitor plugin version

Returns: Promise<{ version: string; }>


Interfaces

CallInvite

Represents a pending incoming call invitation.

This interface describes the data structure for call invitations that have been received but not yet accepted or rejected. The same structure is used both in the callInviteReceived event and in the pendingInvites array returned by getCallStatus().

PropTypeDescription
callSidstringUnique identifier for the incoming call invitation
fromstringPhone number or client identifier of the caller (may include custom caller name)
tostringPhone number or client identifier being called
customParamsRecord<string, string>Custom parameters passed with the call invitation

PluginListenerHandle

PropType
remove() => Promise<void>

Type Aliases

Record

Construct a type with a set of properties K of type T

{ [P in K]: T; }

版本与发布记录

@capgo/capacitor-twilio-voice 共发布 99 个版本,首次发布于 2025/08/07;过去 12 个月发布了 72 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
8.2.28latest2026/11/027 天前
8.2.272026/10/1920 天前
8.2.262026/10/1525 天前
8.2.252026/10/1327 天前
8.2.242026/10/091 个月前
8.2.232026/10/081 个月前

其他发布通道:next → 7.3.0-alpha.1。

关于 @capgo/capacitor-twilio-voice 的常见问题

@capgo/capacitor-twilio-voice 是什么?

Integrates the Twilio Voice SDK into Capacitor

如何安装 @capgo/capacitor-twilio-voice?

在项目目录运行 npm install @capgo/capacitor-twilio-voice,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@capacitor/core(>=8.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@capgo/capacitor-twilio-voice 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@capgo/capacitor-twilio-voice 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@capgo/capacitor-twilio-voice 可以商用吗?

@capgo/capacitor-twilio-voice 使用 MPL-2.0 许可。弱 Copyleft:可以商用,也可以和闭源代码一起使用;但如果分发时修改了 MPL 授权的文件,这些文件的修改需以 MPL 开源。以上为概括,不构成法律意见,请以许可原文为准。

@capgo/capacitor-twilio-voice 的下载量有多少?

根据 npm 官方下载统计,@capgo/capacitor-twilio-voice 在 2026/10/09 – 2026/11/07 这 30 天内被下载 81,531 次,日均约 2,718 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@capgo/capacitor-twilio-voice 还在维护吗?

最新版本 8.2.28 发布于 2026/11/02(7 天前);至今共发布 99 个版本,其中过去 12 个月发布了 72 个;首次发布于 2025/08/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。