This document summarizes the implementation of the audioRouteChange event in the Cordova CallKit plugin, providing comprehensive audio route detection across both Android and iOS platforms.
- Android: Uses
TelecomManager/CallAudioStatewith modernAudioManager.getDevices()API (API 23+) for enhanced device detection - iOS: Leverages
AVAudioSessionRouteChangeNotificationwith Apple's system constants - Detection Scope: Both physical changes (device connect/disconnect) and programmatic changes (via
setAudioRoute()) - Concurrent Calls: Properly handles multiple active calls with shared audio route monitoring
- Modern Android API: Uses
AudioManager.getDevices()withAudioDeviceInfofor reliable detection (API 23+) - USB-C & USB-A Support: Detects USB headsets that older methods miss
- Wired Headset Types: Comprehensive detection including
TYPE_WIRED_HEADSET,TYPE_WIRED_HEADPHONES,TYPE_USB_HEADSET - Backward Compatibility: Falls back to deprecated methods for Android < API 23
- Multiple Call Support: Audio route monitoring scales with active call count
Both platforms return identical route constants:
CordovaCall.AudioRoute = {
EARPIECE: 'earpiece', // Phone earpiece/receiver
BLUETOOTH: 'bluetooth', // Bluetooth headset/device
SPEAKER: 'speaker', // Built-in speaker
WIRED_HEADSET: 'wired_headset', // Wired headphones/headset
UNKNOWN: 'unknown' // Other or unrecognized routes
}CordovaCall.AudioRouteChangeType = {
DEVICE_CHANGED: 'deviceChanged', // Physical device connect/disconnect
PROGRAMMATIC_CHANGE: 'programmaticChange', // Via setAudioRoute() method
ROUTE_CHANGED: 'routeChanged' // General route change
}CordovaCall.on('audioRouteChange', function(data) {
console.log('Audio route changed to:', data.route);
console.log('Change type:', data.changeType);
// Handle route changes
switch(data.route) {
case CordovaCall.AudioRoute.BLUETOOTH:
console.log('Switched to Bluetooth headset');
break;
case CordovaCall.AudioRoute.SPEAKER:
console.log('Switched to speaker phone');
break;
case CordovaCall.AudioRoute.EARPIECE:
console.log('Switched to earpiece');
break;
case CordovaCall.AudioRoute.WIRED_HEADSET:
console.log('Switched to wired headset');
break;
}
});// These will trigger audioRouteChange events
CordovaCall.speakerOn(); // -> route: "speaker"
CordovaCall.speakerOff(); // -> route: "earpiece" (typically)// Get the current audio route without triggering events
CordovaCall.getAudioRoute(
function(route) {
console.log('Current audio route:', route); // "speaker", "bluetooth", etc.
switch(route) {
case CordovaCall.AudioRoute.SPEAKER:
console.log('Currently using speaker');
break;
case CordovaCall.AudioRoute.BLUETOOTH:
console.log('Currently using Bluetooth');
break;
case CordovaCall.AudioRoute.EARPIECE:
console.log('Currently using earpiece');
break;
case CordovaCall.AudioRoute.WIRED_HEADSET:
console.log('Currently using wired headset');
break;
default:
console.log('Unknown route:', route);
}
},
function(error) {
console.error('Failed to get audio route:', error);
}
);{
"route": "speaker", // Standardized route constant
"changeType": "deviceChanged" // Type of change
}{
"route": "bluetooth",
"changeType": "deviceChanged",
"supportedRoutes": 7, // Integer bitmask from CallAudioState.getSupportedRouteMask()
"isMuted": false
}{
"route": "wired_headset",
"changeType": "routeChanged",
"reason": 2, // Numeric reason code
"reasonString": "NewDeviceAvailable", // Human-readable reason
"currentOutputType": "AVAudioSessionPortHeadphones" // iOS AVAudioSessionPortDescription.portType value
}- File:
src/android/CordovaCall.java - Detection Method: Hybrid approach using:
- Modern
AudioManager.getDevices()API withAudioDeviceInfo(API 23+) BroadcastReceiverfor physical device changes (headset plug, Bluetooth, USB)Connection.onCallAudioStateChanged()for programmatic changes- Fallback to deprecated
isWiredHeadsetOn()for older Android versions
- Modern
- USB Support: Enhanced detection for USB-C headsets, USB-A adapters, and USB audio devices
- Concurrent Calls: Active call counting ensures monitoring starts/stops appropriately
- Integration: Works with
MyConnectionService.javafor complete coverage
- File:
src/ios/CordovaCall.m - Detection Method:
AVAudioSessionRouteChangeNotification - System Constants: Uses Apple's official
AVAudioSessionRouteChangeReason*constants - Filtering: Enhanced reason filtering to capture all relevant changes
- Route Mapping: Converts iOS-specific output types to standardized constants
- Optimized Data: Streamlined event data focusing on current route information
- Consistent API: Same constants and event format across platforms
- Modern Android Support: Uses latest APIs for reliable USB-C and USB headset detection
- Comprehensive Detection: Captures all route changes regardless of cause
- Multiple Call Aware: Properly manages audio monitoring across concurrent calls
- Easy Integration: Simple event listener with standardized data
- Reactive & Proactive: Both event-based monitoring and current state queries
- Developer Friendly: JavaScript enum definitions for easy usage
- Performance Optimized: Efficient monitoring that scales with call activity
The implementation has been designed to capture:
- ✅ Physical headphone plug/unplug (3.5mm and USB-C)
- ✅ USB headset and adapter detection (USB-A, USB-C)
- ✅ Bluetooth device connect/disconnect
- ✅ Programmatic route changes via
speakerOn()/speakerOff() - ✅ iOS CallKit route switching
- ✅ System-initiated route changes
- ✅ Multiple concurrent call scenarios
- ✅ Modern Android device compatibility (API 23+)
Implementation updated: March 2026 Supports: Android API 23+ (with fallback to API 21+), iOS 10+ Enhanced: Modern Android API support, USB-C detection, concurrent call handling