Bob Flavin created CB-1599:
------------------------------
Summary: successCallback not called after stopRecording, duplicate
AudioRecorder objects created
Key: CB-1599
URL: https://issues.apache.org/jira/browse/CB-1599
Project: Apache Cordova
Issue Type: Bug
Components: CordovaJS
Affects Versions: 2.1.0
Environment: Android 2.3?
Reporter: Bob Flavin
Assignee: Filip Maj
Fix For: 2.1.0
A successCallback is not called sometimes after stopRecording() is called.
The problem is that javascript cordova calls to 'new Media()' and
'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads
on the java side and are not synchronized. Thus
org.apache.cordova.AudioHandler.execute for action='create', calls new
AudioPlayer(). Asynchronously, ...AudioHandler.execute for
action='startAudioRecording' calls AudioHandler.startAudioRecording(), which
gets a null from this.players.get(id) which causes the if statement to call new
AudioRecorder which creates a second instance of AudioRecorder for that id.
public void startRecordingAudio(String id, String file) {
AudioPlayer audio = this.players.get(id);
if ( audio == null) {
audio = new AudioPlayer(this, id, file);
this.players.put(id, audio);
}
audio.startRecording(file);
}
One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in
MEDIA_NONE.
When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may
get the instance of AudioPlayer that is in MEDIA_NONE. This prevents
AudioPlayer.stopRecording() from calling this.recorder.stop() and
this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in
STATE MEDIA_NONE. Thus AudioPlayer.setState doesn't call the
handler.sendJavascript to call the javascript Media.onStatus method that would
call the statusCallback and the successCallback.
I think that the AudioHandler should have a synchronized block that prevents
'create' and 'startRecordingAudio from running at the same time and that
'create' should use the same code that startRecodingAudio does:
AudioPlayer audio = this.players.get(id);
if ( audio == null) {
audio = new AudioPlayer(this, id, file);
this.players.put(id, audio);
}
to prevent creating a second AudioPlayer instance if the startRecordingAudio
thread executes before the 'create' thread.
There may be other actions in AudioHandler.execute that need this
synchronization as well.
One effect of this problem is that the javascript successCallback is never
called (after stopRecord)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira