I'm new to Android development and I have a question/problem.
I'm playing around with the MediaPlayer class to reproduce some sounds/music. I am playing raw resources (res/raw) and it looks kind of easy.
To play a raw resource, the MediaPlayer has to be initialized like this:
MediaPlayer mp = MediaPlayer.create(appContext, R.raw.song);
mp.start();
Until here there is no problem. The sound is played, and everything works fine. My problem appears when I want to add more options to my application. Specifically when I add the "Stop" button/option.
Basically, what I want to do is...when I press "Stop", the music stops. And when I press "Start", the song/sound starts over. (pretty basic!)
To stop the media player, you only have to call stop(). But to play the sound again, the media player has to be reseted and prepared.
mp.reset();
mp.setDataSource(params);
mp.prepare();
The problem is that the method setDataSource() only accepts as params a file path, Content Provider URI, streaming media URL path, or File Descriptor.
So, since this method doesn't accept a resource identifier, I don't know how to set the data source in order to call prepare(). In addition, I don't understand why you can't use a Resouce identifier to set the data source, but you can use a resource identifier when initializing the MediaPlayer.
I guess I'm missing something. I wonder if I am mixing concepts, and the method stop() doesn't have to be called in the "Stop" button. Any help?
Thanks in advance!!!
Here is what I did to load multiple resources with a single MediaPlayer:
/**
* Play a sample with the Android MediaPLayer.
*
* #param resid Resource ID if the sample to play.
*/
private void playSample(int resid)
{
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
try
{
mediaPlayer.reset();
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
mediaPlayer.prepare();
mediaPlayer.start();
afd.close();
}
catch (IllegalArgumentException e)
{
Log.e(TAG, "Unable to play audio queue do to exception: " + e.getMessage(), e);
}
catch (IllegalStateException e)
{
Log.e(TAG, "Unable to play audio queue do to exception: " + e.getMessage(), e);
}
catch (IOException e)
{
Log.e(TAG, "Unable to play audio queue do to exception: " + e.getMessage(), e);
}
mediaPlay is a member variable that get created and released at other points in the class. This may not be the best way (I am new to Android myself), but it seems to work. Just note that the code will probably fall trough to the bottom of the method before the mediaPlayer is done playing. If you need to play a series of resources, you will still need to handle this case.
this is how MediaPlayer.create method works to open a raw file:
public static MediaPlayer create(Context context, int resid) {
try {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
if (afd == null) return null;
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
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;
}
Or, you could access the resource in this way:
mediaPlayer.setDataSource(context, Uri.parse("android.resource://com.package.name/raw/song"));
where com.package.name is the name of your application package
You can use
mp.pause();
mp.seekTo(0);
to stop music player.
Finally, the way it works for me:
public class MainStart extends Activity {
ImageButton buttonImage;
MediaPlayer mp;
Boolean playing = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonImage = (ImageButton)findViewById(R.id.ButtonID);
buttonImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(playing){
mp.stop();
playing = false;
}else{
mp = MediaPlayer.create(getApplicationContext(), R.raw.sound_u_want);
mp.start();
playing = true;
}
}
});
}
}
MR. Rectangle, this message maybe too late for it, but I proudly write these codes to your idea: I have mp for mediaplayer and sescal9 is a button.
....
if(btnClicked.getId() == sescal9_ornek_muzik.getId())
{
mp.start();
mp.seekTo(380);
mp2.start();
mp2.seekTo(360);
mp3.start();
mp3.seekTo(340);
...
}
Recheck your passing parameters not null
Possible reasons
Context may be null
Your media file may be corrupted
Related
I have a list of song objects that I want to iterate through using a MediaPlayer. It works, but the first time I launch the app, it races through the first song (sometimes several seconds, sometimes the whole song). If I completely close and reopen the app, it is fine in subsequent runs. Why is it doing this, and how can I avoid it?
My SoundPlayerMedia class is:
private MediaPlayer _soundPlayer;
public SoundPlayerMedia(Context applicationContext) {
super();
_soundPlayer = MediaPlayer.create(applicationContext, R.raw.ringtone_cesium);
}
private void initializeMedia(Context context, int soundID, boolean startPlaying) {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(soundID);
try {
if (_soundPlayer == null)
return;
_soundPlayer.reset();
_soundPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
_soundPlayer.setVolume(1f, 1f); // Forces MAX volume
_soundPlayer.prepare();
if (startPlaying)
_soundPlayer.start();
afd.close();
} catch (Exception e) {
Log.e("DEBUG", "Unable to switch sound due to exception: " + e.getMessage(), e);
}
}
I use this in a fragment. In the onViewCreated, I have:
_fSoundPlayer = new SoundPlayerMedia(getContext().getApplicationContext());
_fSoundPlayer.setLooping(false);
_soundPlayer.initializeSound(getContext(), currSongId, startPlaying);
Outrageous number of similar questions exist here, sadly none did help me.
I am trying to play 3 Audio files simultaneously, one is .wav , the other is .3gp and the other is .mp3 . Since the size exceeds more than 1MB , I cannot use Android SoundPool here. So far, everything works well without any error. Here is my code :
MediaPlayer mp = new MediaPlayer();
MediaPlayer songPlayer = new MediaPlayer();
MediaPlayer voicePlayer = new MediaPlayer();
private String song,voice,text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time__date);
String temp;
SharedPreferences preferences1 = getSharedPreferences("musicList", MODE_PRIVATE);
song = preferences1.getString("MUSICONE", "");
SharedPreferences preferences2 = getSharedPreferences("recordList",MODE_PRIVATE);
temp = preferences2.getString("VOICEONE","");
voice = Environment.getExternalStorageDirectory()+"/myAppCache2/"+temp;
SharedPreferences preferences3 = getSharedPreferences("TextList",MODE_PRIVATE);
temp=preferences3.getString("ALARMONE","");
text=Environment.getExternalStorageDirectory()+"/myAppCache/"+temp;
try {
mp.setDataSource(text);
mp.prepare();
mp.setLooping(true);
songPlayer.setDataSource(song);
songPlayer.prepare();
songPlayer.setLooping(true);
voicePlayer.setDataSource(voice);
voicePlayer.prepare();
voicePlayer.setLooping(true);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mp.start();
songPlayer.start();
voicePlayer.start();
}
Now, my query is how do I add a delay to one ore more Audio files, Say If I want to add a delay of 5000 for voicePlayer before it loops again?
Now, my query is how do I add a delay to one ore more Audio files, Say If I want to add a delay of 5000 for voicePlayer before it loops again?
You could remove setLooping and use an OnCompletionListener instead. When you get the onCompletion callback, use postDelayed to post a Runnable that starts the player again.
I am trying to implement a playlist of videos so they have a smooth transition from one video to the next. The mediaPlayer object has a prepareasync() method that would seem to prebuffer the video so it's ready to play. How do I invoke the prepareasync method from the VideoView object? The examples I found for mediaPlayer either don't use VideoView and seem to create the surface from scratch. Or the examples use mediaPlayer as return parameter on videoview eventlisteners which seem to occur only after the videoview.play(). I would like have access to videoview's mediaplayer before invoking the play method so I can invoke the prepareasync() and then later the the play().
Just as user1023110 mentioned, VideoView is a wrapper around MediaPlayer. Diving into the source code (since the docs aren't useful at all) I confirmed that it internally calls prepareAsync() in its private method openVideo():
private void openVideo() {
if (mUri == null || mSurfaceHolder == null) {
// not ready for playback just yet, will try again later
return;
}
// Tell the music playback service to pause
// TODO: these constants need to be published somewhere in the framework.
Intent i = new Intent("com.android.music.musicservicecommand");
i.putExtra("command", "pause");
mContext.sendBroadcast(i);
// we shouldn't clear the target state, because somebody might have
// called start() previously
release(false);
try {
mMediaPlayer = new MediaPlayer();
if (mAudioSession != 0) {
mMediaPlayer.setAudioSessionId(mAudioSession);
} else {
mAudioSession = mMediaPlayer.getAudioSessionId();
}
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mOnInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
// we don't set the target state here either, but preserve the
// target state that was there before.
mCurrentState = STATE_PREPARING;
attachMediaController();
} catch (IOException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} catch (IllegalArgumentException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
}
}
VideoView is a wrapper around MediaPlayer and SurfaceView so you don't have to do it yourself. I believe the wrapper does the prepare when you call setVideoURI.
Its possible to get hold of the mediaplayer inside the VideoView through the onPrepared eventhandler, and once you've got it, I guess you can call prepare yourself after the first time, but I gather the internals are tricky and not well documented so things might not work as expected.
I want to make simple audio streaming application but my this code is throwing exception.
Can anybody tell me whats wrong?
***public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String url = "128.downloadming1.com/bollywood%20mp3/Ekk%20Deewana%20Tha%20(2012)/01%20-%20Kya%20Hai%20Mohabbat.mp3";
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(url);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.prepare();
mp.start();
} catch (Exception e){
Log.i("Exception", "Exception in streaming mediaplayer e = " + e);
}
}***
Just adding to Anton's answer. prepare() function on Mediaplayer is synchronous which will block your UI thread. So its better to use setonpreparelistner and start your media player on onpreparelistner().
You code is ok, but i think, that you must add to url "http://". This must work.
UPD: if this don't work - write you exception.
My media player is in a service object of it's own. Here's the create code.
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = new MediaPlayer();
try {
player.setDataSource(path);
player.prepare();
} catch (Exception e) {
}
player.setLooping(false); // Set looping
}
It is streaming from online. However, it's pretty choppy 3 minutes later. I want to double buffer this to help remove that. Any ideas on how I should do this?
Have you looked at the android Double Buffer class?