In my Android application I want to play sequentially some sound that was divided to parts before. Each part is a .wave file with 2-3 seconds length.
I do perform that successfully, but I have a noticeable delay between those parts.
My code looks now like that -
localMediaPlayer = new MediaPlayer[3];
localMediaPlayer[0] = MediaPlayer.create(this, R.raw.sound_1);
localMediaPlayer[1] = MediaPlayer.create(this, R.raw.sound_2);
localMediaPlayer[2] = MediaPlayer.create(this, R.raw.sound_3);
public void onClick_localBtn(View v){
Toast.makeText(this, "Play Local Sound", Toast.LENGTH_LONG).show();
localMediaPlayer[0].start();
localMediaPlayer[0].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
localMediaPlayer[1].start();
}
});
localMediaPlayer[1].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
localMediaPlayer[2].start();
}
});
}
How can I improve my code that those parts will play smooth and with no delay, like if it were a 1 file sound?
Thanks.
When you start playing your (N)th media player, call prepareAsync() on your (N+1)th media player:
localMediaPlayer[0].start();
localMediaPlayer[1].prepareAsync();
localMediaPlayer[0].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
localMediaPlayer[1].start();
localMediaPlayer[2].prepareAsync();
}
});
localMediaPlayer[1].setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
localMediaPlayer[2].start();
}
});
Edit
Based on your update and your comment, perhaps a better way would to be time the playing of the next media player according to the duration of the previous player minus some delta:
private static final int DURATION_DELTA = 1000;
private Handler mHandler = new Handler();
public void playMediaPlayer(final int index) {
if (index >= localMediaPlayer.length || localMediaPlayer[index] == null)
return;
localMediaPlayer[index].start();
final int duration = localMediaPlayer[index].getDuration();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
playMediaPlayer(index + 1);
}
}, duration - DURATION_DELTA);
}
This code will basically play a media player, then schedule playing the next media player approx 1 second before the next media player ends. It's a bit "hacky", but you can play around with it (the value for DURATION_DELTA) until you get the best results.
Related
i want to make a special alarm app and the user should have the possibility to be woken up with music getting louder e.g. for 60 seconds.
I could not find a way to do this, that's why I need your help.
Thank you for your help and sorry for my bad English
final AudioManager am=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
oldvolume=am.getStreamVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,100,0);
if (increase<=0) mediaPlayer.setVolume(volume,volume);
mediaPlayer.start();
if (increase>0){
mediaPlayer.setVolume(0,0);
final double hohe=volume/increase;
new CountDownTimer((increase*1000),1000) {
#Override
public void onTick(long millisUntilFinished) {
mediaPlayer.pause();
mediaPlayer.setVolume((float) hohe*millisUntilFinished,(float) hohe*(increase*1000-millisUntilFinished));
mediaPlayer.start();
}
#Override
public void onFinish() {
mediaPlayer.pause();
mediaPlayer.setVolume( volume,volume);
mediaPlayer.start();
}
}.start();
That's what i got until now.
increase= increasing time in seconds
volume= max volume alarm should have
Solution, works for me is:
private Handler mHandler = new Handler();
private Runnable mVolumeRunnable = new Runnable() {
#Override
public void run() {
if (mediaPlayer != null&¤tvolume<endvolume) {
currentvolume += volumeincrease;
mediaPlayer.setVolume(currentvolume/100f, currentvolume/100f);
Toast.makeText(AlertActivity.this,String.valueOf(currentvolume),Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mVolumeRunnable, 1000);
}
else mHandler.removeCallbacks(mVolumeRunnable);
}
};
The audio file (.mp3) gets played when I don't use the onPreparedListener, but I get an error after the file tries to replay after some time (because it's not listening for the state obviously). So basically the code is checking the battery state and if it's 10% or below it plays the alarm sound, I also have a button which I can click to stop the sound. Now with the onPreparedListener the alarm sound doesn't get played anymore. What am I doing wrong?
tv_battery = (TextView) findViewById(R.id.tv_battery);
final MediaPlayer mp = MediaPlayer.create(this, R.raw.alarm);
Button b = (Button) findViewById(R.id.stop_alarm);
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 20, 0);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mp.isPlaying()) {
mp.stop();
mp.release();
}
}
});
runnable = new Runnable() {
#Override
public void run() {
int level = (int) batteryLevel();
tv_battery.setText("Battery: " + level + "%");
handler.postDelayed(runnable, 5000);
if(level <= 10) {
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
CountDownTimer count = new CountDownTimer(7000, 1000) {
public void onTick(long millisUntilFinished) {
mp.start();
}
public void onFinish() {
//code fire after finish
mp.stop();
}
};
count.start();
}
I think you have place mp.start(); on wrong place please move it before count.start(); as below :
CountDownTimer count = new CountDownTimer(7000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//code fire after finish
mp.stop();
}
};
mp.start();
count.start();
Also correct below condition if media player already started when battery is under 10 otherwise media player again prepared even after started :
if(level <= 10 && !mp.isPlaying()) {
I have a simple activity which contains one instance of a VideoView and a reference to its' MediaPlayer. My goal was to use the setNextMediaPlayer() api from the MediaPlayer object in order to minimize the switching time between 2 videos.
In the below code, the 1st video plays well. When the 1st video completes, the 2nd video's audio begins to play in the background, but only the last frame of the 1st video is shown.
Do you know what the problem is? Why isn't the 2nd video's video displaying?
private VideoView player1;
private MediaPlayer mediaPlayer1;
public static final String URL_1 = "https://example.com/video1.mp4";
public static final String URL_2 = "https://example.com/video2.mp4";
public static final String TAG = "PrebufferingActivity";
public boolean FIRST_TIME = true;
public int count = 0;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prebuffering);
player1 = (VideoView) findViewById(R.id.videoPlayer1);
player1.setOnPreparedListener(new OnPreparedListener(){
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer1 = mp;
if(FIRST_TIME == true)
{
mediaPlayer1.start();
player1.requestFocus();
FIRST_TIME = false;
}
}
});
player1.setOnInfoListener(new OnInfoListener(){
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra)
{
if(what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START)
{
count++;
if(count % 2 != 0)
{
Log.d(TAG, "Odd count (" + count + ") Prebuffering URL_2");
MediaPlayer myMediaPlayer = MediaPlayer.create(PrebufferingActivity.this, Uri.parse(URL_2));
mp.setNextMediaPlayer(myMediaPlayer);
}
else
{
Log.d(TAG, "Even count (" + count + ") Prebuffering URL_1");
MediaPlayer myMediaPlayer = MediaPlayer.create(PrebufferingActivity.this, Uri.parse(URL_1));
mp.setNextMediaPlayer(myMediaPlayer);
}
}
return false;
}
});
player1.setOnCompletionListener(new OnCompletionListener(){
#Override
public void onCompletion(MediaPlayer mp) {
}
});
// Player 1
player1.setMediaController(new MediaController(this));
player1.setVideoURI(Uri.parse(URL_1));
}
In your example you create new MediaPlayer, but VideoView knows nothing about and can't control it. It wouldn't work properly.
If you need some specific functions probably you need to build your analog of VideoView, that would use MediaPlayer.
Regarding playing 2nd video by using setNextMediaPlayer() you can find some hints here:
https://stackoverflow.com/a/28465846/755313
I have been having this issue for a while now.
I have a simple application that plays a playlist of videos within a videoview with a pause of a few seconds between them.
private final Runnable playNormalVideo = new Runnable() {
public void run() {
try {
final String filepath = ...;
viewVideo.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int extra) {
onEndVideo(false);
return true;
}
});
viewVideo.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
onEndVideo(false);
}
});
viewVideo.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
background.setVisibility(View.INVISIBLE);
viewVideo.start();
}
});
viewVideo.setVideoPath(filepath);
viewVideo.setVisibility(View.VISIBLE);
viewVideo.requestFocus();
} catch (Exception e) {
String error = Utils.getStackTrace(e);
Utils.log(true, error);
}
}
};
and in my onEndVideo() function I make the background visible and check what video to play next and with a Handler i request to play it after x seconds.
My issue is the following :
Within a long run (approx 1 day) the background becomes invisible within a lot of seconds before the video starts. I don't understand why. If someone could help me get rid of this issue.
I also thought I should free memory between video plays but i don't seem to find how to do that.
Note : All the videos are saved on the device.
Thanks for any help.
I want to play back to back mp3 files(of half sec) in my android application.I am able to do that on emulator but on mobile phone they all are overlapping with each other.
I have used OnCompletionListerner and stopped the Mediaplayer.
Following is my code for one mp3 file:
mPlayer = MediaPlayer.create(MainActivity.this, R.raw.a10);
mPlayer.start();
mPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mPlayer) {
// TODO Auto-generated method stub
mPlayer.stop();
}
});
Can anybody suggest any method to stop the overlapping?
Try following example :
MediaPlayer mp1, mp2;
Timer timer;
// Create two different instances of mediaplayer
mp1 = MediaPlayer.create(MainActivity.this, R.raw.a1);
mp2 = MediaPlayer.create(MainActivity.this, R.raw.a2);
// Create the timertask
timer = new Timer("mytimer");
timer.schedule(timertask1, 1000);
onCompletionListeners:
// Completion listener for Audio file 1.
mp1.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(final MediaPlayer cim) {
//On completion of first audio, release the resources of mediaplayer
mp1.release();
mp1 = null;// free up memory
// Start the timertask of 2nd audio file
timer = new Timer("mytimer");
timer.schedule(timertask2, 1000);
}
});
mp2.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(final MediaPlayer cim) {
//On completion of 2nd audio, release the resources of mediaplayer
mp2.release();
mp2 = null;
// Start the timertask of 1st audio file or nxt audio file if you want to play file or simplly you can stop here.
timer = new Timer("mytimer");
timer.schedule(timertask1, 1000);
}
});
Timer tasks:
private TimerTask timertask1 = new TimerTask() {
#Override
public void run() {
mp1.start();
}
};
private TimerTask timertask2 = new TimerTask() {
#Override
public void run() {
mp2.start();
}
};
Note:
Example is given considering two audio files only, hence two specific onCompletionlisteners and timertasks. However I would suggest you to use generalised code for creating the mediaplayer instance, onCompletionlistener and timertask.