Search code examples
javascriptjquerycordovaonsen-uionsen-ui2

Cordova - button for Hold to record audio - sometimes stops


Let me explain it thoroughly. I am building a chat app using Cordova, and I want to do a sound recording function just like in Messenger, where you hold a button, it changes it appearance, then after some time you release the button, and the sound file is sent to the server. I tried to do it, sometimes it works, but sometimes it stops unexpectedly, or sometimes the button's appearance changes to unclicked, when you move your finger one pixel.

Now here is my html of the button

<ons-button id="btnRecordSound" modifier="large" disable-auto-styling>Hold to record</ons-button>

And here is the javascript

let soundRecord = '';
let isRecording = false;

function setRecordSoundButton() {
    $('#btnRecordSound').on('touchstart touchend', (event) => {
        if (event.type == 'touchstart') {
            startSoundRecording();
        } else if (event.type == 'touchend') {
            stopSoundRecording();
        }
    });
}

function startSoundRecording() {
    soundRecord = new Media(/*some file path here*/, () => {
        // success function
    });
    soundRecord.startRecord();
    isRecording = true;
    setTimeout(favoChat.stopSoundRecording, 30000);
}

function stopSoundRecording() {
    if (isRecording) {
        isRecording = false;
        soundRecord.stopRecord();
    }
}

As you can see, I rely on touchstart and touchend events to determine when to start and stop it, and there is also a forced setTimeout function that stops the recording at a given time limit.

Is this the best way to visualize the button? I need it to not change appearance when moved just one pixel away from the touch point. If anything, I would like to set some max interval, that when move outside of it, then stop it. And, are the start and stop functions ok? I need the stop function to be exact.


Solution

  • I'd imagine the reason it stops unexpectedly is due to the fact you're not clearing your timeout after setting it.

    If you start recording a 20-second audio clip, stop recording and then instantly start recording again there is still a timeout with 10 seconds left on it because it's not been cleared and will run after the 10 seconds.

    If you change your code to something like this:

    let soundRecord = '';
    let isRecording = false;
    let soundTimeout = null;
    
    function setRecordSoundButton() {
        $('#btnRecordSound').on('touchstart touchend', (event) => {
            if (event.type == 'touchstart') {
                startSoundRecording();
            } else if (event.type == 'touchend') {
                stopSoundRecording();
            }
        });
    }
    
    function startSoundRecording() {
        soundRecord = new Media( /*some file path here*/ , () => {
            // success function
        });
        soundRecord.startRecord();
        isRecording = true;
        soundTimeout = setTimeout(favoChat.stopSoundRecording, 30000);
    }
    
    function stopSoundRecording() {
        if (isRecording) {
            clearTimeout(soundTimeout);
            isRecording = false;
            soundRecord.stopRecord();
        }
    }
    

    It should fix that issue.