I have used the following code:
mp = MediaPlayer.create(this, Uri.parse("file://"+filePath));
mp.start();
This works fine. Then I wanted to play music from a folder
mp.setDataSource(this, Uri.parse("file://"+filePath));
mp.prepareAsync();
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
Are there any performance differences between the two method?
You can check MediaPlayer create() source code to see the difference:
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder,
AudioAttributes audioAttributes, int audioSessionId) {
try {
MediaPlayer mp = new MediaPlayer();
final AudioAttributes aa = audioAttributes != null ? audioAttributes :
new AudioAttributes.Builder().build();
mp.setAudioAttributes(aa);
mp.setAudioSessionId(audioSessionId);
mp.setDataSource(context, uri);
if (holder != null) {
mp.setDisplay(holder);
}
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
}
Basically create() call is synchronous (it internally calls prepare()) and prepareAsync() is asynchronous.
The first approach ties up whatever thread you are on, long enough for MediaPlayer to read in the metadata of the media and prepare some buffers. If this is the main application thread, it means that your UI will be frozen while this is going on.
Sure, create method inits object in main thread. So code lines below it should wait for create.
On the other hand, prepare asynchronous opens a new thread to init object then notify you to run next operations while main thread run other lines.
Edit: As #CommonWares mentioned in the comment, mp.create() is a convenient method of calling mp.setDataSoucer() + mp.prepare() at the same time
Related
I have a Service that starts a thread, where I need to create a MediaPlayer:
Inside onStartCommand I call the main function that runs a thread.
public int onStartCommand(Context context, Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
doTask(context);
return START_STICKY;
}
void doTask(Context context) {
isActive = true;
thread = new Thread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void run() {
try {
threadLoop(context);
}
catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
Log.e(TAG, "Thread started");
}
After this, inside threadLoop I am trying to create a MediaPlayer
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer = MediaPlayer.create(context, AudioData);
but I can't do anything with the 1st context parameter. I tried to send context and get the base one, but it doesn't work.
Maybe I should use another service for MediaPlayer?
Thank you in advance
Update
Error:
Cannot resolve method 'create(android.content.Context, short[])'.
You're passing in the wrong data to the second parameter. The first parameter is fine. The second is a resource id or a Uri, not a short[]. If the short array is supposed to be audio data (like the raw .wav data), write it to a file and pass it the URI of that file.
Also, passing context to a Thread like that is dangerous and can lead to memory leaks. You need to make sure the thread is ended when the service is ended to prevent it.
Your code should be like this
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer = MediaPlayer.create(this, uri);
I am trying to play an audio file in Eclipse using MediaPlayer in Android programming.
I need to run the audio file (.wav or .mp3) which is saved on computer hard-drive. I have tried many things. I also tried copying the file in res folder of my project, but nothing worked. Below is my code.
As you can see I have tried many ways and commented some. I was first getting IOException earlier. But after using MediaPlayer.create(), I am getting IllegalStateException.
Any help would be very appreciated.
public void playSound(MainActivity mainActivity){
System.out.println("in playsound");
MediaPlayer mp = null;
FileInputStream fis = null;
try {
//fis = new FileInputStream("C:\\Users\\Anupam-PC\\Downloads\\trailsoundfilerecordings\\jagmeet.wav");
//mp.setDataSource(fis.getFD());
System.out.println("inside try");
//mp.setDataSource("/res/raw/hai.wav");
//mp.setDataSource("C:\\Users\\Anupam-PC\\Downloads\\trailsoundfilerecordings\\jagmeet.wav");
//mp.setDataSource("android.resource://com.example.texttospeech/agreji.mp3");
//mp.setDataSource("agreji.mp3");
mp = MediaPlayer.create(mainActivity, R.raw.hai);
System.out.println("after DS");
mp.prepare();
System.out.println("after prepare");
mp.start();
// fis.close();
} catch (Exception e) {
System.out.println(e);
} finally{
try{
fis.close();
} catch (Exception e){
}
}
You don't need to implement mp.prepare();, you have create(/**/)
This is my example that works like a charm:
class Vulcan implements MediaPlayer.OnPreparedListener{
MediaPlayer mediaPlayer = null;
...
boolean isPrepearedToPlayAudio = false;
mediaPlayer=MediaPlayer.create(context,R.raw.mini_vulcan_gun_1);
mediaPlayer.setOnPreparedListener(this);
public void stop(){
mediaPlayer.pause();
}
public void start(){
if(isPrepearedToPlayAudio){
mediaPlayer.start();
mediaPlayer.setLooping( true );
}
}
#Override
public void onPrepared(MediaPlayer mp) {
isPrepearedToPlayAudio = true;
}
Your invocation of MediaPlayer.create(...) already calls prepare(), and multiple calls to prepare() will cause an ISE. All you need to do is remove:
mp.prepare();
Javadoc:
Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.
When done with the MediaPlayer, you should call release(), to free the resources. If not released, too many MediaPlayer instances will result in an exception.
I got error code with 1,-4 number in android media player
I use this code for playing music in my service
public void playNextSong(/* String manualUrl */) {
mState = State.Stopped;
relaxResources(true); // release everything except MediaPlayer
AudioFile file = playList.nextFile();
if (file == null) {
say("Tidak ada lagu di playlist");
return;
}
try {
// set the source of the media player a a content URI
createMediaPlayerIfNeeded();
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(getApplicationContext(), file.getUri());
mState = State.Preparing;
// MUST call this!
setUpAsForeground(file.getTitle() + " (loading)");
// starts preparing the media player in the background. When it's
// done, it will call
// our OnPreparedListener (that is, the onPrepared() method on this
// class, since we set
// the listener to 'this').
//
// Until the media player is prepared, we *cannot* call start() on
// it!
mPlayer.prepareAsync();
} catch (IOException ex) {
Log.e("MusicService",
"IOException playing next song: " + ex.getMessage());
ex.printStackTrace();
}
}
And I use this in the shake listener of my code
mSensorListener
.setOnShakeListener(new ShakeEventListener.OnShakeListener() {
public void onShake() {
musicService.playNextSong();
updateInformation(musicService.playList.getCurrent());
}
});
Anyone can help to handle player not in invalid states exceptions
I need to play sound from sd card. I have method that must do this but it's doesn't work.
When I use this method:
public class AudioPlayService extends Service
{
MediaPlayer mMediaPlayer;
..............
public void soundplay(String adr)
{
mMediaPlayer = new MediaPlayer();
try
{
if (mMediaPlayer.isPlaying())
{
mMediaPlayer.reset();
}
mMediaPlayer.setDataSource(adr);
mMediaPlayer.prepare();
} catch (IOException e)
{
}
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
mp.release();
mp = null;
}
});
}
Where String adr - it's absolute path to file on sd.
Then I call it:
AudioPlayService s = new AudioPlayService();
s.soundplay(iA.getSdDir() + "Files/Numbers/0.mp3");
and I get an err's:
12-09 13:04:13.829: E/MediaPlayer(16997): error (1, -2147483648)
12-09 13:04:13.829: E/MediaPlayer(16997): start called in state 0
12-09 13:04:13.829: E/MediaPlayer(16997): error (-38, 0)
12-09 13:04:13.839: E/MediaPlayer(16997): Error (-38,0)
I myself tried your code:
Mine worked fine when i put just "sdcard/1.mp3"
You ensure that the path is right or not
s.soundplay(iA.getSdDir() + "Files/Numbers/0.mp3");
Note:
If you are trying to make your method soundplay so as to stop previous audio and play the new audio file, then better would be not to perfom this inside that method
mMediaPlayer = new MediaPlayer();
Place this in constructor.
Otherwise each time you invoke s.soundplay(path) you will hear previous audio plus the new audio. ie,Previous one will not be stopped
player.start() put within try,catch block. Because if player not prepare your song ,still you are calling start method.start method is only called after playback is ready,
means prepare is success.Another thing is that you have to release the media player when your player is no longer.Otherwise there is so many player objects are running in back ground.
For some reason, your setDataSource() or Prepare() is failing. So after the exception, start()is giving the error, since the player is not in Prepared state. Add print statements in the catch block to know what is the exception. And move start() into the try catch block.
mMediaPlayer = new MediaPlayer();
try
{
if (mMediaPlayer.isPlaying())
{
mMediaPlayer.reset();
}
mMediaPlayer.setDataSource(adr);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException e)
{
e.printStackTrace();
}
I am trying to play a few music (wav format) files based on button clicks. I am unable to get MediaPlayer to work properly. Every time I try to instantiate an object of MediaPlayer class, it fails on create(). Before I post the code, here is a run-through of what I am doing:
1. A layout file that contains 2 buttons.
2. Those buttons are read and onClickListeners defined for them.
3. Depending on the button clicked, a function called playAudioFile(View) called which creates the MediaPlayer instance and plays the file. The code for playAudioFile(View) is as follows:
public void playAudioFile(View v) {
/*Steps:
* 1. Take in id of the button.
* 2. Using id, identify what file needs to be played.
* 3. Play file.
*/
String path_to_file = null; //this is the path to the file.
if(b01.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button 01 pressed.");
path_to_file = "/sdcard/audio/temp1.wav";
} else if(b02.getId() == ((Button)v).getId()) {
Log.v(this.toString(), "Button02 pressed.");
path_to_file = "/sdcard/audio/temp2.wav";
}
path_to_file = "file://" + path_to_file;
Uri streamUri = Uri.parse(path_to_file);
Log.v(this.toString(), "Path of file = " + path_to_file);
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
}
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
try {
mp.start();
} catch (IllegalStateException e) {
e.printStackTrace();
Log.v(this.toString(), "Illegal state exception thrown in start.");
}
}
});
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
}
I have gone through a lot of posts here on stackoverflow that detail solutions to the above problem. I am encountering this problem after having incorporated all the suggestions made therein. Any help is most welcome.
Thanks,
Sriram
I dont understand why you are trying to do
MediaPlayer mp = MediaPlayer.create(this, streamUri);
This is my implementation of my Player, Hope this will help you in some way:
MediaPlayer mp = new MediaPlayer();
setContentView(R.layout.player);
Intent intent = getIntent();
String path = "";
System.out.println("My Scheme : "+intent.getData().toString().substring(8));
if (intent.getData().getScheme().equals("video")) {
path = intent.getData().toString().substring(8);
System.out.println("Path : "+path);
if(path.endsWith(".mp3")) {
setContentView(R.layout.musicplayer);
setContentView(R.layout.controls);
Log.e("MusicPlayer", "Playing: " + path);
try {
Notification notification = new Notification(
R.drawable.playbackstart, path, System.currentTimeMillis());
nm.notify(NOTIFY_ID, notification);
mp.reset();
mp.setDataSource(path);
mp.prepare();
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
System.out.println("Hi i am at the End");
}
});
}catch {expression}
If I'm not wrong, you can't use onPrepare because mp.prepare() is called inside MediaPlayer.create(). The simpliest code can be something like this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
mp.start();
If you want something more elaborated, you can try this:
MediaPlayer mp = MediaPlayer.create(this, streamUri);
if(mp == null) {
Log.v(this.toString(), "Create() on MediaPlayer failed.");
} else {
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//here you should call the methods to release memory
mp.stop();
mp.release();
}
});
mp.start();
}
Tell me if it helped you.
PD: Is better if you use a device for testing rather than a simulator. Some classes don't work properly there (MediaPlayer can't reproduce video in simulators) and I don't remember if it supports audio.
As far as I understand your problem: You are calling the MediaPlayer.create(...) method, and it returns null, meaning the creation of a MediaPlayer instance failed. According to the accepted answer of this post MediaPlayer.create() always returns null it is due to a corrupted audio file.
I also have an issue, where the sound gets played but on rare occasions the create() method also returns null. I use sounds in a turn based game, after each turn a sound is played. I always call the create method, start the player and release it when it's done. That happens every turn and like once in 300 turns the create method returns null... So in my case it must be something else. In yours it could probably have something to do with the corruption of the mp3 file.