mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-22 00:32:55 +08:00
Working with Lorin's change
This commit is contained in:
commit
c030770be7
25
framework/src/org/apache/cordova/AudioHandler.java
Executable file → Normal file
25
framework/src/org/apache/cordova/AudioHandler.java
Executable file → Normal file
@ -96,6 +96,12 @@ public class AudioHandler extends Plugin {
|
|||||||
float f = this.getDurationAudio(args.getString(0), args.getString(1));
|
float f = this.getDurationAudio(args.getString(0), args.getString(1));
|
||||||
return new PluginResult(status, f);
|
return new PluginResult(status, f);
|
||||||
}
|
}
|
||||||
|
else if (action.equals("create")) {
|
||||||
|
String id = args.getString(0);
|
||||||
|
String src = args.getString(1);
|
||||||
|
AudioPlayer audio = new AudioPlayer(this, id, src);
|
||||||
|
this.players.put(id, audio);
|
||||||
|
}
|
||||||
else if (action.equals("release")) {
|
else if (action.equals("release")) {
|
||||||
boolean b = this.release(args.getString(0));
|
boolean b = this.release(args.getString(0));
|
||||||
return new PluginResult(status, b);
|
return new PluginResult(status, b);
|
||||||
@ -149,7 +155,7 @@ public class AudioHandler extends Plugin {
|
|||||||
|
|
||||||
// Get all audio players and pause them
|
// Get all audio players and pause them
|
||||||
for (AudioPlayer audio : this.players.values()) {
|
for (AudioPlayer audio : this.players.values()) {
|
||||||
if (audio.getState() == AudioPlayer.MEDIA_RUNNING) {
|
if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
|
||||||
this.pausedForPhone.add(audio);
|
this.pausedForPhone.add(audio);
|
||||||
audio.pausePlaying();
|
audio.pausePlaying();
|
||||||
}
|
}
|
||||||
@ -192,13 +198,12 @@ public class AudioHandler extends Plugin {
|
|||||||
* @param file The name of the file
|
* @param file The name of the file
|
||||||
*/
|
*/
|
||||||
public void startRecordingAudio(String id, String file) {
|
public void startRecordingAudio(String id, String file) {
|
||||||
// If already recording, then just return;
|
AudioPlayer audio = this.players.get(id);
|
||||||
if (this.players.containsKey(id)) {
|
if ( audio == null) {
|
||||||
return;
|
audio = new AudioPlayer(this, id, file);
|
||||||
}
|
this.players.put(id, audio);
|
||||||
AudioPlayer audio = new AudioPlayer(this, id);
|
}
|
||||||
this.players.put(id, audio);
|
audio.startRecording(file);
|
||||||
audio.startRecording(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,7 +226,7 @@ public class AudioHandler extends Plugin {
|
|||||||
public void startPlayingAudio(String id, String file) {
|
public void startPlayingAudio(String id, String file) {
|
||||||
AudioPlayer audio = this.players.get(id);
|
AudioPlayer audio = this.players.get(id);
|
||||||
if (audio == null) {
|
if (audio == null) {
|
||||||
audio = new AudioPlayer(this, id);
|
audio = new AudioPlayer(this, id, file);
|
||||||
this.players.put(id, audio);
|
this.players.put(id, audio);
|
||||||
}
|
}
|
||||||
audio.startPlaying(file);
|
audio.startPlaying(file);
|
||||||
@ -292,7 +297,7 @@ public class AudioHandler extends Plugin {
|
|||||||
|
|
||||||
// If not already open, then open the file
|
// If not already open, then open the file
|
||||||
else {
|
else {
|
||||||
audio = new AudioPlayer(this, id);
|
audio = new AudioPlayer(this, id, file);
|
||||||
this.players.put(id, audio);
|
this.players.put(id, audio);
|
||||||
return (audio.getDuration(file));
|
return (audio.getDuration(file));
|
||||||
}
|
}
|
||||||
|
400
framework/src/org/apache/cordova/AudioPlayer.java
Executable file → Normal file
400
framework/src/org/apache/cordova/AudioPlayer.java
Executable file → Normal file
@ -31,6 +31,8 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.cordova.AudioPlayer.MODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements the audio playback and recording capabilities used by Cordova.
|
* This class implements the audio playback and recording capabilities used by Cordova.
|
||||||
* It is called by the AudioHandler Cordova class.
|
* It is called by the AudioHandler Cordova class.
|
||||||
@ -41,15 +43,20 @@ import java.io.IOException;
|
|||||||
* sdcard: file name is just sound.mp3
|
* sdcard: file name is just sound.mp3
|
||||||
*/
|
*/
|
||||||
public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener {
|
public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener {
|
||||||
|
|
||||||
private static final String LOG_TAG = "AudioPlayer";
|
// AudioPlayer modes
|
||||||
|
public enum MODE { NONE, PLAY, RECORD };
|
||||||
|
|
||||||
// AudioPlayer states
|
// AudioPlayer states
|
||||||
public static int MEDIA_NONE = 0;
|
public enum STATE { MEDIA_NONE,
|
||||||
public static int MEDIA_STARTING = 1;
|
MEDIA_LOADING,
|
||||||
public static int MEDIA_RUNNING = 2;
|
MEDIA_STARTING,
|
||||||
public static int MEDIA_PAUSED = 3;
|
MEDIA_RUNNING,
|
||||||
public static int MEDIA_STOPPED = 4;
|
MEDIA_PAUSED,
|
||||||
|
MEDIA_STOPPED
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "AudioPlayer";
|
||||||
|
|
||||||
// AudioPlayer message ids
|
// AudioPlayer message ids
|
||||||
private static int MEDIA_STATE = 1;
|
private static int MEDIA_STATE = 1;
|
||||||
@ -64,17 +71,20 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
private static int MEDIA_ERR_DECODE = 3;
|
private static int MEDIA_ERR_DECODE = 3;
|
||||||
private static int MEDIA_ERR_NONE_SUPPORTED = 4;
|
private static int MEDIA_ERR_NONE_SUPPORTED = 4;
|
||||||
|
|
||||||
private AudioHandler handler; // The AudioHandler object
|
private AudioHandler handler; // The AudioHandler object
|
||||||
private String id; // The id of this player (used to identify Media object in JavaScript)
|
private String id; // The id of this player (used to identify Media object in JavaScript)
|
||||||
private int state = MEDIA_NONE; // State of recording or playback
|
private MODE mode = MODE.NONE; // Playback or Recording mode
|
||||||
private String audioFile = null; // File name to play or record to
|
private STATE state = STATE.MEDIA_NONE; // State of recording or playback
|
||||||
private float duration = -1; // Duration of audio
|
|
||||||
|
|
||||||
private MediaRecorder recorder = null; // Audio recording object
|
private String audioFile = null; // File name to play or record to
|
||||||
private String tempFile = null; // Temporary recording file name
|
private float duration = -1; // Duration of audio
|
||||||
|
|
||||||
|
private MediaRecorder recorder = null; // Audio recording object
|
||||||
|
private String tempFile = null; // Temporary recording file name
|
||||||
|
|
||||||
private MediaPlayer mPlayer = null; // Audio player object
|
private MediaPlayer player = null; // Audio player object
|
||||||
private boolean prepareOnly = false;
|
private boolean prepareOnly = true; // playback after file prepare flag
|
||||||
|
private int seekOnPrepared = 0; // seek to this location once media is prepared
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -82,14 +92,17 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* @param handler The audio handler object
|
* @param handler The audio handler object
|
||||||
* @param id The id of this audio player
|
* @param id The id of this audio player
|
||||||
*/
|
*/
|
||||||
public AudioPlayer(AudioHandler handler, String id) {
|
public AudioPlayer(AudioHandler handler, String id, String file) {
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.audioFile = file;
|
||||||
|
|
||||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||||
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
|
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
|
||||||
} else {
|
} else {
|
||||||
this.tempFile = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/tmprecording.mp3";
|
this.tempFile = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/tmprecording.mp3";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,13 +110,13 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
*/
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
// Stop any play or record
|
// Stop any play or record
|
||||||
if (this.mPlayer != null) {
|
if (this.player != null) {
|
||||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
|
||||||
this.mPlayer.stop();
|
this.player.stop();
|
||||||
this.setState(MEDIA_STOPPED);
|
this.setState(STATE.MEDIA_STOPPED);
|
||||||
}
|
}
|
||||||
this.mPlayer.release();
|
this.player.release();
|
||||||
this.mPlayer = null;
|
this.player = null;
|
||||||
}
|
}
|
||||||
if (this.recorder != null) {
|
if (this.recorder != null) {
|
||||||
this.stopRecording();
|
this.stopRecording();
|
||||||
@ -118,31 +131,34 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* @param file The name of the file
|
* @param file The name of the file
|
||||||
*/
|
*/
|
||||||
public void startRecording(String file) {
|
public void startRecording(String file) {
|
||||||
if (this.mPlayer != null) {
|
switch (this.mode) {
|
||||||
|
case PLAY:
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
|
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||||
}
|
break;
|
||||||
// Make sure we're not already recording
|
case NONE:
|
||||||
else if (this.recorder == null) {
|
// Make sure we're not already recording
|
||||||
this.audioFile = file;
|
if (this.recorder == null) {
|
||||||
this.recorder = new MediaRecorder();
|
this.audioFile = file;
|
||||||
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
|
this.recorder = new MediaRecorder();
|
||||||
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
|
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
|
||||||
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
|
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
|
||||||
this.recorder.setOutputFile(this.tempFile);
|
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
|
||||||
try {
|
this.recorder.setOutputFile(this.tempFile);
|
||||||
this.recorder.prepare();
|
try {
|
||||||
this.recorder.start();
|
this.recorder.prepare();
|
||||||
this.setState(MEDIA_RUNNING);
|
this.recorder.start();
|
||||||
return;
|
this.setState(STATE.MEDIA_RUNNING);
|
||||||
} catch (IllegalStateException e) {
|
return;
|
||||||
e.printStackTrace();
|
} catch (IllegalStateException e) {
|
||||||
} catch (IOException e) {
|
e.printStackTrace();
|
||||||
e.printStackTrace();
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||||
}
|
}
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
break;
|
||||||
}
|
case RECORD:
|
||||||
else {
|
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
|
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
|
||||||
}
|
}
|
||||||
@ -171,9 +187,9 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
public void stopRecording() {
|
public void stopRecording() {
|
||||||
if (this.recorder != null) {
|
if (this.recorder != null) {
|
||||||
try{
|
try{
|
||||||
if (this.state == MEDIA_RUNNING) {
|
if (this.state == STATE.MEDIA_RUNNING) {
|
||||||
this.recorder.stop();
|
this.recorder.stop();
|
||||||
this.setState(MEDIA_STOPPED);
|
this.setState(STATE.MEDIA_STOPPED);
|
||||||
}
|
}
|
||||||
this.moveFile(this.audioFile);
|
this.moveFile(this.audioFile);
|
||||||
}
|
}
|
||||||
@ -183,81 +199,22 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
// Playback
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start or resume playing audio file.
|
* Start or resume playing audio file.
|
||||||
*
|
*
|
||||||
* @param file The name of the audio file.
|
* @param file The name of the audio file.
|
||||||
*/
|
*/
|
||||||
public void startPlaying(String file) {
|
public void startPlaying(String file) {
|
||||||
if (this.recorder != null) {
|
if (this.readyPlayer(file)) {
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
|
this.player.start();
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
this.setState(STATE.MEDIA_RUNNING);
|
||||||
}
|
} else {
|
||||||
|
//
|
||||||
// If this is a new request to play audio, or stopped
|
this.prepareOnly = false;
|
||||||
else if ((this.mPlayer == null) || (this.state == MEDIA_STOPPED)) {
|
|
||||||
try {
|
|
||||||
// If stopped, then reset player
|
|
||||||
if (this.mPlayer != null) {
|
|
||||||
this.mPlayer.reset();
|
|
||||||
}
|
|
||||||
// Otherwise, create a new one
|
|
||||||
else {
|
|
||||||
this.mPlayer = new MediaPlayer();
|
|
||||||
}
|
|
||||||
this.audioFile = file;
|
|
||||||
|
|
||||||
// If streaming file
|
|
||||||
if (this.isStreaming(file)) {
|
|
||||||
this.mPlayer.setDataSource(file);
|
|
||||||
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
|
||||||
this.setState(MEDIA_STARTING);
|
|
||||||
this.mPlayer.setOnPreparedListener(this);
|
|
||||||
this.mPlayer.prepareAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If local file
|
|
||||||
else {
|
|
||||||
if (file.startsWith("/android_asset/")) {
|
|
||||||
String f = file.substring(15);
|
|
||||||
android.content.res.AssetFileDescriptor fd = this.handler.cordova.getActivity().getAssets().openFd(f);
|
|
||||||
this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
File fp = new File(file);
|
|
||||||
if (fp.exists()) {
|
|
||||||
FileInputStream fileInputStream = new FileInputStream(file);
|
|
||||||
this.mPlayer.setDataSource(fileInputStream.getFD());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.mPlayer.setDataSource("/sdcard/" + file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setState(MEDIA_STARTING);
|
|
||||||
this.mPlayer.setOnPreparedListener(this);
|
|
||||||
this.mPlayer.prepare();
|
|
||||||
|
|
||||||
// Get duration
|
|
||||||
this.duration = getDurationInSeconds();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have already have created an audio player
|
|
||||||
else {
|
|
||||||
|
|
||||||
// If player has been paused, then resume playback
|
|
||||||
if ((this.state == MEDIA_PAUSED) || (this.state == MEDIA_STARTING)) {
|
|
||||||
this.mPlayer.start();
|
|
||||||
this.setState(MEDIA_RUNNING);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state);
|
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,11 +222,14 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* Seek or jump to a new time in the track.
|
* Seek or jump to a new time in the track.
|
||||||
*/
|
*/
|
||||||
public void seekToPlaying(int milliseconds) {
|
public void seekToPlaying(int milliseconds) {
|
||||||
if (this.mPlayer != null) {
|
if (this.readyPlayer(this.audioFile)) {
|
||||||
this.mPlayer.seekTo(milliseconds);
|
this.player.seekTo(milliseconds);
|
||||||
Log.d(LOG_TAG, "Send a onStatus update for the new seek");
|
Log.d(LOG_TAG, "Send a onStatus update for the new seek");
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + milliseconds / 1000.0f + ");");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + milliseconds / 1000.0f + ");");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.seekOnPrepared = milliseconds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,12 +238,12 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
public void pausePlaying() {
|
public void pausePlaying() {
|
||||||
|
|
||||||
// If playing, then pause
|
// If playing, then pause
|
||||||
if (this.state == MEDIA_RUNNING) {
|
if (this.state == STATE.MEDIA_RUNNING) {
|
||||||
this.mPlayer.pause();
|
this.player.pause();
|
||||||
this.setState(MEDIA_PAUSED);
|
this.setState(STATE.MEDIA_PAUSED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state);
|
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state.ordinal());
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,12 +252,12 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* Stop playing the audio file.
|
* Stop playing the audio file.
|
||||||
*/
|
*/
|
||||||
public void stopPlaying() {
|
public void stopPlaying() {
|
||||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
|
||||||
this.mPlayer.stop();
|
this.player.stop();
|
||||||
this.setState(MEDIA_STOPPED);
|
this.setState(STATE.MEDIA_STOPPED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state);
|
Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state.ordinal());
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,10 +265,10 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
/**
|
/**
|
||||||
* Callback to be invoked when playback of a media source has completed.
|
* Callback to be invoked when playback of a media source has completed.
|
||||||
*
|
*
|
||||||
* @param mPlayer The MediaPlayer that reached the end of the file
|
* @param player The MediaPlayer that reached the end of the file
|
||||||
*/
|
*/
|
||||||
public void onCompletion(MediaPlayer mPlayer) {
|
public void onCompletion(MediaPlayer player) {
|
||||||
this.setState(MEDIA_STOPPED);
|
this.setState(STATE.MEDIA_STOPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,8 +277,8 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* @return position in msec or -1 if not playing
|
* @return position in msec or -1 if not playing
|
||||||
*/
|
*/
|
||||||
public long getCurrentPosition() {
|
public long getCurrentPosition() {
|
||||||
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
|
if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
|
||||||
int curPos = this.mPlayer.getCurrentPosition();
|
int curPos = this.player.getCurrentPosition();
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + curPos / 1000.0f + ");");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + curPos / 1000.0f + ");");
|
||||||
return curPos;
|
return curPos;
|
||||||
}
|
}
|
||||||
@ -359,7 +319,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If audio file already loaded and started, then return duration
|
// If audio file already loaded and started, then return duration
|
||||||
if (this.mPlayer != null) {
|
if (this.player != null) {
|
||||||
return this.duration;
|
return this.duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,29 +337,28 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
/**
|
/**
|
||||||
* Callback to be invoked when the media source is ready for playback.
|
* Callback to be invoked when the media source is ready for playback.
|
||||||
*
|
*
|
||||||
* @param mPlayer The MediaPlayer that is ready for playback
|
* @param player The MediaPlayer that is ready for playback
|
||||||
*/
|
*/
|
||||||
public void onPrepared(MediaPlayer mPlayer) {
|
public void onPrepared(MediaPlayer player) {
|
||||||
// Listen for playback completion
|
// Listen for playback completion
|
||||||
this.mPlayer.setOnCompletionListener(this);
|
this.player.setOnCompletionListener(this);
|
||||||
|
|
||||||
// If start playing after prepared
|
// If start playing after prepared
|
||||||
if (!this.prepareOnly) {
|
if (!this.prepareOnly) {
|
||||||
|
this.player.start();
|
||||||
// Start playing
|
this.setState(STATE.MEDIA_RUNNING);
|
||||||
this.mPlayer.start();
|
} else {
|
||||||
|
this.setState(STATE.MEDIA_STARTING);
|
||||||
// Set player init flag
|
|
||||||
this.setState(MEDIA_RUNNING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save off duration
|
// Save off duration
|
||||||
this.duration = getDurationInSeconds();
|
this.duration = getDurationInSeconds();
|
||||||
this.prepareOnly = false;
|
// reset prepare only flag
|
||||||
|
this.prepareOnly = true;
|
||||||
|
// seek to any location received while not prepared
|
||||||
|
this.seekToPlaying(this.seekOnPrepared);
|
||||||
|
// reset seek location
|
||||||
|
this.seekOnPrepared = 0;
|
||||||
// Send status notification to JavaScript
|
// Send status notification to JavaScript
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_DURATION + "," + this.duration + ");");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_DURATION + "," + this.duration + ");");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -408,23 +367,23 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* @return length of clip in seconds
|
* @return length of clip in seconds
|
||||||
*/
|
*/
|
||||||
private float getDurationInSeconds() {
|
private float getDurationInSeconds() {
|
||||||
return (this.mPlayer.getDuration() / 1000.0f);
|
return (this.player.getDuration() / 1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to be invoked when there has been an error during an asynchronous operation
|
* Callback to be invoked when there has been an error during an asynchronous operation
|
||||||
* (other errors will throw exceptions at method call time).
|
* (other errors will throw exceptions at method call time).
|
||||||
*
|
*
|
||||||
* @param mPlayer the MediaPlayer the error pertains to
|
* @param player the MediaPlayer the error pertains to
|
||||||
* @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
|
* @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
|
||||||
* @param arg2 an extra code, specific to the error.
|
* @param arg2 an extra code, specific to the error.
|
||||||
*/
|
*/
|
||||||
public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) {
|
public boolean onError(MediaPlayer player, int arg1, int arg2) {
|
||||||
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
|
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
|
||||||
|
|
||||||
// TODO: Not sure if this needs to be sent?
|
// TODO: Not sure if this needs to be sent?
|
||||||
this.mPlayer.stop();
|
this.player.stop();
|
||||||
this.mPlayer.release();
|
this.player.release();
|
||||||
|
|
||||||
// Send error notification to JavaScript
|
// Send error notification to JavaScript
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
|
||||||
@ -436,21 +395,33 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
*
|
*
|
||||||
* @param state
|
* @param state
|
||||||
*/
|
*/
|
||||||
private void setState(int state) {
|
private void setState(STATE state) {
|
||||||
if (this.state != state) {
|
if (this.state != state) {
|
||||||
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + state + ");");
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + this.state.ordinal() + ");");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mode and send it to JavaScript.
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
*/
|
||||||
|
private void setMode(MODE mode) {
|
||||||
|
if (this.mode != mode) {
|
||||||
|
//mode is not part of the expected behaviour, so no notification
|
||||||
|
//this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + mode + ");");
|
||||||
|
}
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the audio state.
|
* Get the audio state.
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public int getState() {
|
public int getState() {
|
||||||
return this.state;
|
return this.state.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,6 +430,121 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
|
|||||||
* @param volume
|
* @param volume
|
||||||
*/
|
*/
|
||||||
public void setVolume(float volume) {
|
public void setVolume(float volume) {
|
||||||
this.mPlayer.setVolume(volume, volume);
|
this.player.setVolume(volume, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* attempts to put the player in play mode
|
||||||
|
* @return true if in playmode, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean playMode() {
|
||||||
|
switch(this.mode) {
|
||||||
|
case NONE:
|
||||||
|
this.setMode(MODE.PLAY);
|
||||||
|
break;
|
||||||
|
case PLAY:
|
||||||
|
break;
|
||||||
|
case RECORD:
|
||||||
|
Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
|
||||||
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||||
|
return false; //player is not ready
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* attempts to initialize the media player for playback
|
||||||
|
* @param file the file to play
|
||||||
|
* @return false if player not ready, reports if in wrong mode or state
|
||||||
|
*/
|
||||||
|
private boolean readyPlayer(String file) {
|
||||||
|
if (playMode()) {
|
||||||
|
switch (this.state) {
|
||||||
|
case MEDIA_NONE:
|
||||||
|
if (this.player == null) {
|
||||||
|
this.player = new MediaPlayer();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.loadAudioFile(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MEDIA_LOADING:
|
||||||
|
//cordova js is not aware of MEDIA_LOADING, so we send MEDIA_STARTING insntead
|
||||||
|
Log.d(LOG_TAG, "AudioPlayer Loading: startPlaying() called during media preparation: " + STATE.MEDIA_STARTING.ordinal());
|
||||||
|
this.prepareOnly = false;
|
||||||
|
return false;
|
||||||
|
case MEDIA_STARTING:
|
||||||
|
case MEDIA_RUNNING:
|
||||||
|
case MEDIA_PAUSED:
|
||||||
|
return true;
|
||||||
|
case MEDIA_STOPPED:
|
||||||
|
//if we are readying the same file
|
||||||
|
if (this.audioFile.compareTo(file) == 0) {
|
||||||
|
//reset the audio file
|
||||||
|
player.seekTo(0);
|
||||||
|
player.pause();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
//reset the player
|
||||||
|
this.player.reset();
|
||||||
|
try {
|
||||||
|
this.loadAudioFile(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||||
|
}
|
||||||
|
//if we had to prepare= the file, we won't be in the correct state for playback
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state);
|
||||||
|
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load audio file
|
||||||
|
* @throws IOException
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* @throws SecurityException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
*/
|
||||||
|
private void loadAudioFile(String file) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException {
|
||||||
|
if (this.isStreaming(file)) {
|
||||||
|
this.player.setDataSource(file);
|
||||||
|
this.player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
|
//if it's a streaming file, play mode is implied
|
||||||
|
this.setMode(MODE.PLAY);
|
||||||
|
this.setState(STATE.MEDIA_STARTING);
|
||||||
|
this.player.setOnPreparedListener(this);
|
||||||
|
this.player.prepareAsync();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (file.startsWith("/android_asset/")) {
|
||||||
|
String f = file.substring(15);
|
||||||
|
android.content.res.AssetFileDescriptor fd = this.handler.ctx.getActivity().getAssets().openFd(f);
|
||||||
|
this.player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
File fp = new File(file);
|
||||||
|
if (fp.exists()) {
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
|
this.player.setDataSource(fileInputStream.getFD());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.player.setDataSource("/sdcard/" + file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setState(STATE.MEDIA_STARTING);
|
||||||
|
this.player.setOnPreparedListener(this);
|
||||||
|
this.player.prepare();
|
||||||
|
|
||||||
|
// Get duration
|
||||||
|
this.duration = getDurationInSeconds();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user