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.
Related
I was using MediaPlayer to play sounds in my App but from Its start to freeze the App:
Thats the code where I call create method. I moved the code inside an AsyncTask class :
public class BackgroundSound extends AsyncTask<Integer,Void,Void> {
MediaPlayer mpB;
MediaPlayer mpG;
Context ctx;
BackgroundSound(Context appctx)
{
ctx = appctx;
}
#Override
protected Void doInBackground(Integer... Params) {
switch (Params[0]){
case 0:
mpB = MediaPlayer.create(ctx, R.raw.sonidoemocion5sec);
mpB.setLooping(true);
mpB.setVolume(0.75f, 0.75f);
mpB.start();
break;
case 1:
if (mpG != null)
{
mpG.release();
mpG = null;
}
mpG = MediaPlayer.create(ctx, R.raw.ganador);
mpG.setVolume(1, 1);
mpG.start();
break;
case 2:
if (mpG != null){
mpG.release();
mpG = null;
}
mpG = MediaPlayer.create(ctx, R.raw.perder);
mpG.setVolume(1, 1);
mpG.start();
break;
}
return null;
}
}
Debuging I find that the freeze (app still running but dont make anything) occurred in the new line inside the method create from MediaPlayer.java file::
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder,
AudioAttributes audioAttributes, int audioSessionId) {
try {
MediaPlayer mp = new MediaPlayer();
I don't understand what's going on. Any tips?
The warn & Error Log exits:
Instead of using MediaPlayer.create(), use mp.setDataSource() method so that you can call mp.prepareAsync() and then set listener to listen for its completion like this:
mp.setDataSource(this, audioUri);
mp.prepareAsync();
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
Now for this audioUri object of Uri, you can set it to your audio files in the raw folder by having this line of code in your project:
audioUri = Uri.parse("android.resource://com.yourpackagename/" + R.raw.your_audiofile_name);
This method prepares the mp asynchronously and doesn't block the UI
There are two possible solutions for this issue, but it is not sure that it will work properly as I have not tested it.
Solution 1.
Replace below line:
audiojuego = MediaPlayer.create(this, R.raw.sonidoemocion);
with:
audiojuego = MediaPlayer.create(getApplicationContext(), R.raw.sonidoemocion);
//As you are calling from doInBackground() method, this will not work properly.
Solution 2.
Initialize media player by your own way instead of default.
Uri url=Uri.parse("android.resource://"+getPackageName()+"/raw/sonidoemocion");
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();
I am making a simple media player application. It involes a textfield (et) where user just enters the exact name of the song to be played and presses the play button (ib1) to be played. Songs are saved inside sdcard. My code is:
ib1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String value = et.getText().toString();
String full_path = "/mnt/media_rw/sdcard/mymusic/" + value + ".mp3";
et.setText("");
mp = new MediaPlayer();
mp.setDataSource(full_path);
mp.prepare();
mp.start();
} });
But this produces Media Player error (-38.0). So, following Media Player called in state 0, error (-38,0) I tried to replace the mp lines with:
mp.setDataSource(full_path);
mp.setOnPreparedListener(null);
mp.prepareAsync();
mp.start();
But it won't work either, producing error (1, -2147483648). Can someone help me or make some suggestions for the code? Thanks a lot
You need to call mediaPlayer.start() in the onPrepared method by using a listener. You are getting this error because you are calling mp.start() before it has reached the prepared state.
Here is how you can do it :
mp.setDataSource(full_path);
mp.setOnPreparedListener(this);
mp.prepareAsync();
public void onPrepared(MediaPlayer player) {
player.start();
}
I am having an odd issue where my audio file sometimes plays and sometimes does not play. The catch is that when it decides to not play, the DDMS gives me an:
E/MediaPlayer﹕ Should have subtitle controller already set
Because this is one-to-one with the music not playing, I have determined that this is probably the issue...
If the music is not playing and I hit the volume button it begins to play.
If I wait about 30 seconds of no-play, it begins to start again (not looping).
Whats going on here? I am on KitKat using
player = new MediaPlayer();
AssetFileDescriptor afd = null;
try {
afd = getAssets().openFd("Theme.mp3");
} catch (IOException e) {
e.printStackTrace();
}
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IOException e) {
e.printStackTrace();
}
try {
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.setLooping(true); //restart playback end reached
//player.setVolume(1, 1); //Set left and right volumes. Range is from 0.0 to 1.0
player.start(); //start play back
Looking at a previous discussion on StackOverflow, and the referenced Android commit where this was introduced, the code above might not completely initialize the MediaPlayer object.
The KitKat example code for media playback suggests that you should call:
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
immediately after you construct the MediaPlayer, and before you call its setDataSource method.
I had the same issue and I fixed it by adding the following right after instantiating MediaPlayer.
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (mp == mediaPlayer) {
mediaPlayer.start();
}
}
});
Previously I was implementing MediaPlayer.OnPreparedListener and overriding onPrepared() but it didn't work.
I hope this helps!
This should fix your problem (did for me): Replace the line that says "player.start()" following the rest of your code with an async callback like so:
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
This error is just a Log.e, not a real error. It shouldn't cause your player to not play, I'm guessing it's just because the player hadn't finished preparing when you try to call start().
E/MediaPlayer﹕ Should have subtitle controller already set
Its been a long time since I was working on this app. Here is what I ended up doing to get this to work. (Tested on KitKat and Lollipop). I think switching from MediaPlayer to APMediaPlayer was part of the trick.
#Override
public void onDestroy() {
if(player != null) {
player.release();
player = null;
}
super.onDestroy();
}
#Override
public void onStart() {
super.onStart();
if(player != null) {
player.start();
}
else {
player = new APMediaPlayer(this); //create new APMediaPlayer
player.setMediaFile("Theme.mp3"); //set the file (files are in data folder)
player.start(); //start play back
player.setLooping(true); //restart playback end reached
player.setVolume(1, 1); //Set left and right volumes. Range is from 0.0 to 1.0
}
}
#Override
public void onResume() {
super.onResume();
if(player != null) {
player.start();
}
}
set in manifest file may help you
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I am trying to play a looping Ogg file, I tried enabling setLooping(true) but that had no effect so I tried onCompletionListener and that's not working either, could someone clarify what I am doing wrong?
musicPlayer = MediaPlayer.create(mContext, R.raw.overworld);
musicPlayer.setVolume(musicVolume, musicVolume);
// musicPlayer.setLooping(true);
musicPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
musicPlayer.stop();
musicPlayer.seekTo(0);
musicPlayer.start();
Log.d("Sound Manager", "Song Completed");
}
});
Following is my play function,
public void playSong(int id) {
try {
stopSong();
musicPlayer = MediaPlayer.create(mContext, id);
musicPlayer.start();
} catch(Exception e) {
// Ignored
}
}
It's known that MediaPlayer is having problems with ogg files.
You could preferrably switch to another file format.
The other thing is, I would go on trying with setLooping(boolean) as it's most likely using the same scheme and its much more clearly.
Calling seekTo() if the MediaPlayer Object is stopped causes the MediaPlayer to be in an invalid state. You can call pause() instead but I wouldn't call any of these method, why not just seeking? I would guess if you remove the musicPlayer.stop() it will work.
remove ....
musicPlayer.stop();
from
onCompletion(MediaPlayer mp)
onCompletionListener() is not called if your MediaPlayer is set to looping, BUT if you don't have it set to looping, you can always just use a completion listener like so
#Override
public void onCompletion(MediaPlayer mp) {
if(!mp.isPlaying()) {
mp.start();
}
mp.seekTo(0);
}
You also shouldn't call stop() because that stops playback completely, and it doesn't make sense to seek in a video/song that you are not playing.
I have a list of songs that I'm streaming using the MediaPlayer. Some of the songs consistently work and others consistently do not work. I can't see a difference between these files, and they seem to play fine in itunes and such.
When the songs fail it is throwing an IllegalStateException on the mediaPlayer.prepare() line. The IllegalStateException that is thrown has no useful info in it, (detailMessage is null, stackState is null)
Here is my code
try {
mediaPlayer.setDataSource(media.url);
setPlayerState(PlayerState.PREPARING);
mediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
Here is a url to the file that does NOT work:
skdy.bryceb.dev.mediarain.com/song.m4a
Here is one that DOES work:
skdy.bryceb.dev.mediarain.com/song2.m4a
Any ideas why this works on some songs and fails on others?
Thanks MisterSquonk I'm sure that way would work.
In my particular case after beating my head against the wall for a while I realized that on some songs, I was getting to the buffered amount before the player state was getting set to prepared. So I added a check to make sure that the MediaPlayer was in the "PREPARED" state and then it worked great:
// Media prepared listener
mediaPlayer.setOnPreparedListener(
new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
setPlayerState(PlayerState.PREPARED);
}
});
// Media buffer listener
mediaPlayer.setOnBufferingUpdateListener(
new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// Sometimes the song will finish playing before the 100% loaded in has been
// dispatched, which result in the song playing again, so check to see if the
// song has completed first
if(getPlayerState() == PlayerState.COMPLETED)
return;
if(getPlayerState() == PlayerState.PAUSED)
return;
// If the music isn't already playing, and the buffer has been reached
if(!mediaPlayer.isPlaying() && percent > PERCENT_BUFFER) {
if(getPlayerState() == PlayerState.PREPARED)
{
mediaPlayer.start();
setPlayerState(PlayerState.PLAYING);
}
//if it isn't prepared, then we'll wait till the next buffering
//update
return;
}
}
});
OK, I hacked together a minimal Mediaplayer implementation in a 'sandbox' app/activity I always keep spare for testing.
I might be wrong but if you're streaming these songs over the net, you'll need to prefix the url with http://.
I tried the urls with Winamp and Chrome verbatim (no protocol prefix string) and they worked fine although it's likely both of those applications will use some form of intelligence to work out how to connect/stream.
If I tried that in my mediaPlayer code, I get the same exception as you but if I prefix the urls with http:// the songs play fine.
Example...
// Activity scope
Button button;
CheckBox checkBox;
String url = "";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//button declared in my activity
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
if (!checkBox.isChecked())
url = getString(R.string.url_song1);
else
url = getString(R.string.url_song2);
mediaPlayer = new MediaPlayer();
}
#Override
public void onClick(View arg0) {
try {
Log.i(TAG, "onClick() entered...");
mediaPlayer.setDataSource(url);
Log.i(TAG, "Preparing mediaplayer...");
mediaPlayer.prepare();
Log.i(TAG, "Starting mediaplayer...");
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "bad stream");
}
}
If I copy the songs to my SD card both play fine and as long as the internet url strings have an 'http://' prefix then they also work.