Add audio injection to Appium script Audio injection provides deterministic audio input during automated test sessions on iOS and Android devices. Use it to validate application behavior involving calls, voice input, or audio routing without manual device interaction. Audio injection simulates incoming audio only. It does not capture microphone input from the test environment. Supported platforms iOS (XCUITest automation engine) Android (UiAutomator2 automation engine) Prerequisites kobiton:bluetooth capability enabled on the session Audio file hosted at a direct download URL the device can reach at runtime Device in a valid state to receive audio: call or audio-receiving state active if applicable, unmuted, not in airplane mode Audio file requirements Requirement Value Container WAV (16-bit), MP3, or OGG Sample rate 8 kHz Channels mono Max file size 30 MB Use reliable, publicly accessible hosting so the runtime download does not delay test execution. Enable Bluetooth Add the kobiton:bluetooth capability to your test configuration. This capability enables Bluetooth on the device during the session and is required for all audio injection commands. capabilities: { 'platformName': 'iOS', 'kobiton:bluetooth': true, 'appium:deviceName': 'iPhone 15', 'appium:app': 'kobiton-store:v1' } Audio injection commands Control audio injection through the driver.execute() method with Kobiton-specific command keys. Command Description Parameters kobiton:startAudioInjection Begins playback of the specified audio file. url: direct download URL for the audio file. kobiton:pollAudioInjection Returns the current playback status. None. kobiton:stopAudioInjection Terminates audio playback and releases resources. None. Example: full audio injection workflow A full workflow enables Bluetooth at session start, performs a test action, then starts, polls, and stops injection. // Enable Bluetooth in capabilities const capabilities = { 'platformName': 'iOS', 'kobiton:bluetooth': true, 'appium:deviceName': 'iPhone 15', 'appium:app': 'kobiton-store:v1' }; // Initialize driver const driver = await wdio.remote({ protocol: 'https', hostname: 'api.kobiton.com', port: 443, path: '/wd/hub', capabilities }); // Perform test actions (for example, initiate a call) await driver.$('~Keypad').click(); // Start audio injection await driver.execute('kobiton:startAudioInjection', { url: 'https://example.com/audio.mp3' }); // Optional: poll playback status const status = await driver.execute('kobiton:pollAudioInjection'); // Stop audio injection await driver.execute('kobiton:stopAudioInjection'); // Cleanup await driver.deleteSession(); Playback begins immediately and runs asynchronously while the test continues. Best practices Poll for playback completion Fixed waits based on audio length work but can drift out of sync with actual playback. Poll kobiton:pollAudioInjection to detect completion dynamically. Fixed wait await new Promise((resolve) => setTimeout(resolve, audioLength * 1000)); Poll for completion const startTime = Date.now(); while (Date.now() - startTime < maxWaitTime) { const status = await driver.execute('kobiton:pollAudioInjection'); if (status == null || !String(status).includes('playing')) { break; } await new Promise((resolve) => setTimeout(resolve, 1000)); } Clean up resources on failure Stop audio injection and close the session in a finally block so failed tests do not leave audio routing active. try { // ... test code ... } finally { try { await driver.execute('kobiton:stopAudioInjection'); } catch (err) { // Ignore errors during cleanup } if (driver) { await driver.deleteSession(); } } Related documentation Inject audio during a manual session Video demo Audio injection code samples on GitHub