Cordova Android端实时麦克风音频捕获异常问题求助
Hey Juan, let's fix your Cordova audio capture issue!
First, let's break down why your web code works in Firefox but not on Android via Cordova:
- Cordova's Android WebView has stricter permission rules (media access requires user interaction, not auto-execution)
- Deprecated APIs like
createScriptProcessorbehave inconsistently across WebViews - AudioContext initialization might be blocked without a user gesture
Solution 1: Fix your existing Web Audio API code for Cordova
Step 1: Update Cordova permissions
Add these lines to your config.xml to ensure audio capture permissions are granted:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Step 2: Replace auto-execution with user-triggered start
Modern WebViews (including Cordova's) block media access unless initiated by a user gesture (like a button click). Modify your code to run on button press instead of immediately:
<button id="startCaptureBtn">Start Audio Monitoring</button> <div id="barra-progreso" style="width:0%; height:20px; background:blue;"></div> <div id="barra-progreso2" style="width:0%; height:20px; background:red; margin-top:10px;"></div> <script> var ventanas = []; var MAX_VENTANAS = 7; var audioContext = null; var gain_node = null, script_processor_node = null, microphone_stream = null; const BUFF_SIZE = 16384; // Trigger audio setup on button click document.getElementById('startCaptureBtn').addEventListener('click', initAudioProcessing); function initAudioProcessing() { try { // Cross-browser AudioContext fallback window.AudioContext = window.AudioContext || window.webkitAudioContext; audioContext = new AudioContext(); alert("Audio system initialized"); // Use modern mediaDevices API with fallback to old getUserMedia if (navigator.mediaDevices?.getUserMedia) { navigator.mediaDevices.getUserMedia({ audio: true }) .then(startMicrophone) .catch(handleAudioError); } else if (navigator.getUserMedia) { navigator.getUserMedia({ audio: true }, startMicrophone, handleAudioError); } else { alert("Audio capture not supported on this device"); } } catch (e) { alert(`Failed to initialize audio: ${e.message}`); } } function handleAudioError(error) { alert(`Audio capture error: ${error.message}`); } function processMicrophoneBuffer(event) { const microphoneBuffer = event.inputBuffer.getChannelData(0); let sum = 0; // Calculate average amplitude for (let i = 0; i < BUFF_SIZE; i++) { sum += Math.abs(microphoneBuffer[i]); } sum /= BUFF_SIZE; // Update progress bars (check if elements exist to avoid errors) const bar1 = document.getElementById("barra-progreso"); if (bar1) bar1.style.width = `${Math.floor(sum * 100)}%`; // Update sliding window average if (ventanas.length >= MAX_VENTANAS) ventanas.shift(); ventanas.push(sum); let windowSum = 0; ventanas.forEach(val => windowSum += val); windowSum = (windowSum / (MAX_VENTANAS * BUFF_SIZE)) * 1000000; const bar2 = document.getElementById("barra-progreso2"); if (bar2) bar2.style.width = `${Math.floor(windowSum)}%`; console.log(`Window average: ${windowSum}`); } function startMicrophone(stream) { gain_node = audioContext.createGain(); microphone_stream = audioContext.createMediaStreamSource(stream); microphone_stream.connect(gain_node); // Fix: Connect script processor to destination (required for some WebViews) script_processor_node = audioContext.createScriptProcessor(BUFF_SIZE, 1, 1); script_processor_node.onaudioprocess = processMicrophoneBuffer; microphone_stream.connect(script_processor_node); script_processor_node.connect(audioContext.destination); alert("Microphone connected successfully!"); } </script>
Step 3: Replace deprecated createScriptProcessor (optional but recommended)
createScriptProcessor is deprecated—use AudioWorklet for better performance and compatibility. Here's a quick snippet to replace it:
// In initAudioProcessing, after creating audioContext: await audioContext.audioWorklet.addModule('audio-processor.js'); const workletNode = new AudioWorkletNode(audioContext, 'microphone-processor'); microphone_stream.connect(workletNode); workletNode.connect(audioContext.destination); // Create audio-processor.js file: class MicrophoneProcessor extends AudioWorkletProcessor { process(inputs) { const buffer = inputs[0][0]; // Your buffer processing logic here (same as processMicrophoneBuffer) // To send data to main thread: this.port.postMessage(buffer); return true; } } registerProcessor('microphone-processor', MicrophoneProcessor);
Solution 2: Use Cordova AudioInput Plugin
If Web Audio API still gives you trouble, the cordova-plugin-audioinput is designed specifically for this use case.
Step 1: Install the plugin
cordova plugin add cordova-plugin-audioinput
Step 2: Sample implementation
<button id="startBtn">Start Monitoring</button> <button id="stopBtn">Stop Monitoring</button> <script> var ventanas = []; var MAX_VENTANAS = 7; const BUFF_SIZE = 16384; document.getElementById('startBtn').addEventListener('click', startAudioCapture); document.getElementById('stopBtn').addEventListener('click', stopAudioCapture); function startAudioCapture() { const config = { sampleRate: 44100, bufferSize: BUFF_SIZE, channels: 1, format: 'float32' // Matches Web Audio's buffer format }; audioInput.start(config, processBuffer, handleError); } function processBuffer(buffer) { // Same processing logic as before—buffer is a Float32Array let sum = 0; for (let i = 0; i < buffer.length; i++) { sum += Math.abs(buffer[i]); } sum /= buffer.length; // Update UI elements... // (copy your existing progress bar update code here) } function handleError(error) { alert(`Audio input error: ${error}`); } function stopAudioCapture() { audioInput.stop(); } </script>
Recommended Learning Resources
- Cordova Core Docs: Focus on the Android platform guide and permission configuration to understand WebView behavior.
- Web Audio API Guide: Learn modern practices like AudioWorklet to avoid deprecated APIs and improve compatibility.
- Cordova Plugin Development: If you want to customize audio handling, learn how plugins bridge native code and web apps.
- Android WebView Permissions: Deep dive into Android's rules for media access in WebViews to avoid permission-related bugs.
内容的提问来源于stack exchange,提问作者Juan Bulla
相关产品推荐
相关产品推荐

