I created an Android application that is like a metronome.
Actually I want to play a beep sound every n milliseconds.
I use MediaPlayer and timer for this.
My code is like this:
Soloution 1:
start_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Timer timer = new Timer("MetronomeTimer", true);
TimerTask tone = new TimerTask() {
#Override
public void run() {
//Log
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss:SS");
Date date = new Date();
j++;
Log.i("Beep", df.format(date) + "_____" + j);
//Play sound
music = MediaPlayer.create(MainActivity.this, R.raw.beep);
music.start();
}
};
timer.scheduleAtFixedRate(tone, 500, 500); // every 500 ms
}
});
When I run this code, everything is OK. But after 15 times loop, line of Log works fine, but sound is muted. And occasionally every 15, or 20 Log, sound plays and stop.
Solution 2:
I move this line:
music = MediaPlayer.create(MainActivity.this, R.raw.beep);
out of TimerTask (like this):
start_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
music = MediaPlayer.create(MainActivity.this, R.raw.beep);
Timer timer = new Timer("MetronomeTimer", true);
TimerTask tone = new TimerTask() {
#Override
public void run() {
//Log
DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss:SS");
Date date = new Date();
j++;
Log.i("Beep", df.format(date) + "_____" + j);
//Play sound
music.start();
}
};
timer.scheduleAtFixedRate(tone, 500, 500); // every 500 ms
}
});
This code is OK too until 500 ms for repeating. when period time decrease to 400 or 300 ms, every 2 Log, one sound beeps.
How to repair this code that work fine.
SoundPool is better for playing short sounds that are loaded from memory. I have also had problems implementing MediaPlayer, SoundPool has just been a much easier and lower latency experience.
If you set .setMaxStreams() to a number above 1 you shouldn't get any muted sounds. Try and experiment.
Related
I am developing a Battery Alarm App. and I want to play music using media-player in every one minute using the Timer and also want to repeat music 2 times within one minute.
This works fine for the first time when Timer calls the *8playAlarm() method** but after one minute when Timer again call the playAlarm() method it plays music only once.
#Override
public void onCreate() {
super.onCreate();
mStartTime=preferencesAlert.getInt("alert",0); // 0 == immediately
mInterval=preferencesInterval.getInt("interval",1); // 1==1 minute
mSongUri=preferencesSongUri.getString("uri","android.resource://"+getPackageName()+"/raw/celesta");
timer = new Timer();
TimerTask hourlyTask = new TimerTask() {
#Override
public void run () {
playAlarm();
}
};
// schedule the task to run starting now and then every time interval...
timer.schedule (hourlyTask,60000*mStartTime, 60000*mInterval);
}
playAlarm() method
private void playAlarm(){
playerAlarm=MediaPlayer.create(getApplicationContext(),Uri.parse(mSongUri));
playerAlarm.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
repeatMax=preferencesRepeat.getInt("repeat",2);
if(repeatMin<=repeatMax){
repeatMin++;
if(playerAlarm!=null && !playerAlarm.isPlaying()) {
mp.seekTo(0);
mp.start();
}
}else {
mp.reset();
mp.release();
}
}
});
playerAlarm.start();
}
I want to play music two times in every minute but it plays only once
the first time works because your repeatMin is still at its first value but after you did not set it at 0 again in your code
repeatMin = first int value; // you have to reinitialize your repeatMin somewhere when the sound
has been played for the second time
I guess because you are executing method in onCreate which calls only once. Might be you can make it in some background service and call it every minute
I've been wondering if there's a way with either mp or soundpool to delay a sound and make it start exactly after 10 seconds (I have a countdown and want to add a sound effect saying 3,2,1 go! after 10 seconds.)
maybe with a handler?
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
}
}, 10000);
I am working in an app with chronometer that when an user press the button a sound playing, and when the time at 10:00 other sound playing, but i can't play the last one, Here the code:
btIniciar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (click){
chronometer.setBase(SystemClock.elapsedRealtime() + tempoQuandoParado);
chronometer.start();
Toast.makeText(GerenciaPartida.this, "The match begin!", Toast.LENGTH_LONG).show();
MediaPlayer musica = MediaPlayer.create(GerenciaPartida.this, R.raw.apito);
musica.start();
}
***Here i want play another sound at 10:00, when the time's over***
}
});
You can try to use timer.
Timer myTimer = new Timer();
When you start chronometer start the timer like in example below. 600000 - is 10 minutes in milliseconds.
myTimer.schedule(new TimerTask() {
#Override
public void run() {
//play sound
}
}, 600000);
I want to increase the sound by one level up in each and every 5 seconds meanwhile the sound clip plays.Below is my code:-
MediaPlayer player;
player=MediaPlayer.create(this, R.raw.alarm);
player.setLooping(true);
Is there any method in which i can track each and every 5 minutes when over.How can i achieve this?
I think you can achieve this with java TimerTask, this is an example code, not tested but should work with no big modifications :
Basically you start a task every 5 seconds, in the run() function of the TimerTask you level up your sound level, and when you reach the maxSoundLevel you call cancel() to stop the task.
//Put this in global
int REFRESH_INTERVAL = 5 * 1000; //5 seconds
int maxSoundLevel = 10; // Number of loop to get to max level
int curSoundLevel = 0; //Start at 0 volume level
//Put this after you started the sound
Timer timer = new Timer();
timer.scheduleAtFixedRate(new MyTimerTask(), 0, REFRESH_INTERVAL);
//Put this after your method
private class MyTimerTask extends TimerTask{
public void run() {
if(curSoundLevel < maxSoundLevel)
{
float logLevel = (float)(Math.log(maxSoundLevel-curSoundLevel)/Math.log(maxSoundLevel));
yourMediaPlayer.setVolume(1-logLevel);
curSoundLevel ++;
}
else {
this.cancel();
}
}
}
If you have more questions feel free to ask me.
I have a small app that basically sets up a timer and plays sets of 2 sounds one after another.
I've tried 2 timers, because I wanted both sounds to start exactly at the same time each time. I gave the app 500ms for setting both timers before they start
Calendar cal = Calendar.getInstance();
Date start = new Date(cal.getTime().getTime() + 500);
timerTask1 = new TimerTask() { //1st timer
#Override
public void run() {
soundManager.playSound(1);
}
};
timer1 = new Timer();
timer1.schedule(timerTask1, start, 550);
timerTask2 = new TimerTask() { //2nd timer
#Override
public void run() {
soundManager.playSound(2);
}
};
timer2 = new Timer();
timer2.schedule(timerTask2, start, 550);
}
soundManager is a SoundManager object which is based on this tutorial. Thew only change I've made was decreasing number of avalible streams from 20 to 2 since I play only 2 sounds at the same time.
Now the problem. It's not playing at the equal rate neither on my Motorola RAZR or the emulator. The app slows sometimes, making a longer brake than desired. I can't let that happen. What could be wrong here?
I'm using very short sounds in OGG format
EDIT:
I've made some research. Used 2 aproaches. I was measuring milisecond distances between sound was fired. Refresh rate was 500 ms.
1st aproach was TimerTask - it is a big fail. It started at 300ms, then was constantly growing, and after some time (2 mins) stabilized at 497ms which would be just fine if it started as that.
2nd aproach was while loop on AsyncTask - it was giving me outputs from 475 to 500ms which is better than TimerTask but still inaccurate
At the end none of aproach was playing smoothly. There were always lags
I know it may be a little too much, but you could try a different implementation of SoundPool:
public class Sound {
SoundPool soundPool;
int soundID;
public Sound(SoundPool soundPool, int soundID) {
this.soundPool = soundPool;
this.soundID = soundID;
}
public void play(float volume) {
soundPool.play(soundID, volume, volume, 0, 0, 1);
}
public void dispose() {
soundPool.unload(soundID);
}
}
To use it you can do something like this:
SoundPool soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
AssetFileDescriptor assetFileDescriptor = activity.getAssets().openFd(fileName);
int soundID = soundPool.load(assetFileDescriptor, 0);
Sound sound = new Sound(soundPool, soundID);
And then play:
sound.play(volume);
P.S. If the problem persists even with this code, post a comment and I'll get back to you.
Are you using SoundPool? It is quicker than MediaPlayer. The best chance of getting the two sounds together is when playing them on the same thread.