Twilio AudioSwitch

repository·master·Indexed 41 days ago

https://github.com/twilio/audioswitch

An Android audio management library for real-time communication (VoIP and Video) apps. It simplifies managing audio focus and switching between input/output devices such as Bluetooth headsets, wired headsets, earpieces, and speakerphones.

Tokens
2K
Snippets
8
Records
10
Agent score
3%

What's inside AudioSwitch

  1. Bluetooth headset management

    master

    AudioSwitch supports multiple connected Bluetooth headsets, but it only tracks the single active headset in availableAudioDevices and selectedAudioDevice.

    • Switching headsets: To switch between multiple connected Bluetooth headsets, the user must switch the active headset via the system Bluetooth settings. AudioSwitch will then propagate the change.
    • Connection failures: If connecting to a Bluetooth headset fails, the library reverts the selected device (typically to the Earpiece).
    • Monitoring: You can provide a BluetoothHeadsetConnectionListener to the AudioSwitch constructor to monitor connection state changes and failures.
  2. Select and activate an audio device

    master

    Using AudioSwitch involves a two-step process:

    1. Select: Choose a device from the available list using selectDevice(device). If no device is selected, the library defaults to the priority: BluetoothHeadset -> WiredHeadset -> Earpiece -> Speakerphone.
    2. Activate: Call activate() to acquire audio focus with USAGE_VOICE_COMMUNICATION and route audio to the selected device.

    To release the audio focus and routing, call deactivate().

    // 1. Select a device (e.g., Speakerphone)
    devices.find { it is AudioDevice.Speakerphone }?.let { audioSwitch.selectDevice(it) }
    
    // 2. Activate the device
    audioSwitch.activate()
    
    // Later, revert the audio state
    audioSwitch.deactivate()
  3. Initialize AudioSwitch

    master

    Instantiate the AudioSwitch class by passing your application context. You can optionally enable logging by setting loggingEnabled = true in the constructor.

    // Standard initialization
    val audioSwitch = AudioSwitch(applicationContext)
    
    // Initialization with logging enabled
    val audioSwitch = AudioSwitch(context, loggingEnabled = true)
  4. Install AudioSwitch via Gradle

    master

    To use AudioSwitch in your Android project, ensure mavenCentral() is in your buildscript repositories. Then, add the dependency to your Gradle file.

    For stable releases:

    implementation 'com.twilio:audioswitch:$version'

    To use snapshot builds (from Maven Central snapshots):

    1. Add the snapshot repository:
    maven {
        url = uri("https://oss.sonatype.org/content/repositories/snapshots")
    }
    1. Add the dependency with the -SNAPSHOT suffix:
    implementation 'com.twilio:audioswitch:$version-SNAPSHOT'
    implementation 'com.twilio:audioswitch:$version'
  5. Manage AudioSwitch lifecycle with start, stop, activate, and deactivate

    master

    The AudioSwitch lifecycle is managed through four primary methods:

    1. start(listener: AudioDeviceChangeListener?): Starts listening for audio device changes. If a listener is provided, it will be notified of changes. You must call stop() when finished to prevent memory leaks.
    2. stop(): Stops listening for device changes. If the library was in an ACTIVATED state, it will also call deactivate().
    3. activate(): Performs audio routing and unmuting on the currently selected device. It also acquires audio focus for your application.
    4. deactivate(): Restores the audio state to what it was before activate() was called and releases audio focus.

    Note: activate() will throw an IllegalStateException if called while the library is in the STOPPED state.

    // 1. Start listening for changes
    audioSwitch.start { availableDevices, selectedDevice -> 
        // Handle changes
    }
    
    // 2. Activate audio routing (e.g., when a call starts)
    audioSwitch.activate()
    
    // 3. Deactivate (e.g., when a call ends)
    audioSwitch.deactivate()
    
    // 4. Stop everything
    audioSwitch.stop()
  6. Initialize AudioSwitch

    master

    To use AudioSwitch, create an instance of the AudioSwitch class. It is strongly recommended to create and access a single instance from a single application thread to avoid synchronization issues.

    Constructor Parameters

    • context: An Android Context.
    • bluetoothHeadsetConnectionListener (optional): A listener for Bluetooth device state changes (connect, disconnect, etc.).
    • loggingEnabled (optional): Boolean to enable/disable logging. Defaults to false.
    • audioFocusChangeListener (optional): A listener invoked when system audio focus is updated. Note that updates are only sent after calling activate().
    • preferredDeviceList (optional): The order in which AudioSwitch automatically selects and activates devices. This is prepended to the default list. If null or empty, the default order is used: [BluetoothHeadset, WiredHeadset, Earpiece, Speakerphone].
    val audioSwitch = AudioSwitch(
        context = context,
        bluetoothHeadsetConnectionListener = myBluetoothListener,
        loggingEnabled = true,
        audioFocusChangeListener = myAudioFocusListener,
        preferredDeviceList = listOf(Speakerphone::class.java, BluetoothHeadset::class.java)
    )
  7. Listen for audio device changes

    master

    To react to real-time changes in available audio devices (like plugging in a headset), call start with a lambda. The lambda provides the list of availableAudioDevices and the currently selectedAudioDevice.

    Important: Call stop() when the listener is no longer needed to prevent memory leaks. stop() will also call deactivate() automatically.

    audioSwitch.start { audioDevices, selectedDevice ->
        // TODO: update UI with audio devices
    }
    
    // To stop listening and prevent memory leaks
    audioSwitch.stop()
  8. Retrieve available and selected devices manually

    master

    You can query the current state of audio devices at any time using these properties:

    • availableAudioDevices: A List<AudioDevice> of currently available devices.
    • selectedAudioDevice: The currently selected AudioDevice? (nullable).
    val devices: List<AudioDevice> = audioSwitch.availableAudioDevices
    val selectedDevice: AudioDevice? = audioSwitch.selectedAudioDevice
  9. Configure Bluetooth permissions

    master

    Bluetooth support requires specific permissions that must be declared in your application's manifest; the library does not add them for you.

    • Android 12 (API 31) and greater: You MUST request the BLUETOOTH_CONNECT permission. Failure to do so will disable Bluetooth functionality in AudioSwitch.
    • Pre-Android 12: No specific user permission requests are required for Bluetooth.
  10. Select an audio device

    master

    Use selectDevice(audioDevice: AudioDevice?) to choose which device audio should be routed to.

    • If you pass a specific AudioDevice (e.g., Speakerphone(), Earpiece(), WiredHeadset(), or a BluetoothHeadset), AudioSwitch will attempt to select it if available.
    • If you pass null, AudioSwitch will automatically select the best available device based on the preferredDeviceList.

    Available devices can be retrieved via the availableAudioDevices property.

    // Select a specific device
    audioSwitch.selectDevice(Speakerphone())
    
    // Or let AudioSwitch pick the best available device
    audioSwitch.selectDevice(null)