How to play a sound a set number of times? - android

I'm developing an application to do the following:
When you pressed a button, the application plays a sound lasting two seconds, five times. After playing the sound for the fifth time the application sleeps for thirty seconds. After sleeping, the cycle is repeated two more times.
My problem is that I can not stop the sound after it plays for the fifth time. I think I need to use the for loop or a while loop, but I cannot program them correctly.
The loop:
for(i=0; i==5; ) {
sound.start();
if(sound.isPlaying()) {
if(false) {
sound.stop();
i++;
}
}
}
sound.stop();
well, now I built this code, but his only fault is the 'for' not working properly ... he is not repeat the code that is inside of him twice.
someone can tell me why?
for( counter=0; counter<2; ++counter){
new CountDownTimer(20000, 2000) {
public void onTick(long millisUntilFinished) {
//call to my UI thread every 2 seconds
sound.start();
}
public void onFinish() {
//final call to my UI thread after 10 seconds
chrono2.setBase(SystemClock.elapsedRealtime());
chrono2.start();
chrono2.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
public void onChronometerTick(Chronometer chronometer) {
// TODO Auto-generated method stub
long elapsedTime = SystemClock.elapsedRealtime()-chronometer.getBase();
Log.i(this.getClass().getName(), "" + elapsedTime);
if (elapsedTime > 10000){
chrono2.stop();
chrono2.setBase(SystemClock.elapsedRealtime());
Toast.makeText(getApplicationContext(), "" , Toast.LENGTH_SHORT).show();
}
}
});
} // end onFinish
}.start(); // end count down
}

for(i=0; i==5; ) {
sound.start();
if(sound.isPlaying()) {
if(false) {
sound.stop();
i++;
}
}
}
sound.stop();
The second part of the for loop header is a condition which has to hold for the body to be entered. i=0 and i == 5 don't match, so the condition is wrong from the start and never entered.
You want to experess
for(i=0; i!=5; ) {
or
for(i=0; i<5; ) {
instead.
But where is i incremented or somehow else changed? In a block which is always false, in other words: Never.
Maybe you want to express that, if the statement before is false, do ...
You do so by negating the statement:
if (! sound.isPlaying ()) {
sound.stop();
i++;
}
Without knowing whether sound-playing is blocking or not it is hard to know how to control it.
Let's read the requirements and do it from scratch:
When you pressed a button, the application plays a sound lasting two
seconds, five times. After playing the sound for the fifth time the
application sleeps for thirty seconds. After sleeping, the cycle is
repeated two more times.
You have an outer loop of 3 times, and an inner loop of 5 times.
for (int i=0; i < 3; ++i) {
for (int j=0; j < 5; ++j) {
sound.start();
sleep (2); // seconds of sound
}
sleep (30); // seconds of silence
}

Just keep a counter variable that will tell the application to sleep when it has reached 5, in your while loop. Pseudo code is something like this :
final int REPEAT_RATE = 5;
int counter = 0;
while(counter < 3 * REPEAT_RATE)
{
if(counter == REPEAT_RATE)
{
//Sleep for thirty seconds
}
//Here Play the sound for 2 seconds
}

That is easy all you need is to use a count down timer:
new CountDownTimer(10000, 2000) {
public void onTick(long millisUntilFinished) {
//call to my UI thread every 2 seconds
playSound();
}
public void onFinish() {
//final call to my UI thread after 10 seconds
}
}.start();
And use a simple timer to sleep 30 seconds:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//do after 30 seconds
}
}, 30000);
By adjusting and combining these two you can make your effect...
EDIT: a solution (untested)
int repeatAlarm = 3; //above onCreate
....
playSoundFiveTimes(); //in onCreate
.......
private void playSoundFiveTimes(){
new CountDownTimer(10000, 2000) {
public void onTick(long millisUntilFinished) {
sound.stop();
sound.start();
}
public void onFinish() {
repeatAlarm--;
if(repeatAlarm > 0) wait30seconds();
}
}.start();
}
private void wait30seconds(){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
playSoundFiveTimes();
}
}, 30000);
}

this is my solution:
you can use seekTo(0) function
then mp start again!
private void startCountDownTimer() {
cdTimer = new CountDownTimer(total, 1000) {
public void onTick(long l) {
mp.seekTo(0);
mp.start();
}
public void onFinish() {
mp.stop();
MediaPlayer doneMp = MediaPlayer.create(getApplicationContext(), R.raw.finished_challenge);
doneMp.start();
}
}.start();
}

Related

Running backgound thread every X seconds (Android Studio)

I have a code that plays 5 sounds with 1 second delay between the sounds and I want this part of code to be executed every 5 seconds (so it will run in a row so far as a boolean variable is true, and when it becomes false the tread run stopped - I have a button to both start and stop this executions). Everything works perfectly, but the issue is that I can't get rid of the 5 seconds delay in the first time I click the button, so when I first click, the sounds beggins only after 5 seconds. How can I make it start right away and only after the first time start taking the delays?
Here is the button onClick code:
public void clickHandlerStartTempo(final View view) {
if (!tempoOn) {
Toast toast = Toast.makeText(getApplicationContext(), "Start Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = true;
final Handler handler = new Handler();
final int delay = 5000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (tempoOn) {
runCode(view);
handler.postDelayed(this, delay);
}
}
}, delay);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "Stop Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = false;
}
}
And here is the runCode method:
public void runCode(View view) {
Runnable runnable = new Runnable() {
#Override
public void run() {
playSound(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 4; i++) {
if (tempoOn) {
playSound(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
return;
}
}
}
};
Thread thread = new Thread(runnable);
Log.i(TAG, "runCode: Thread id = " + thread.getId());
thread.start();
}
I'm new to android development and any help would be very much appreciated.
Thanks.
First you need to playsound without thread after that you will execute your reaming 5 second logic stop thread after 4 count.
public void onStartPress(){
playSound();
someMethod();
}
public void someMethod(){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
someMethod();
}
},1000);
}
Don't use actual Threads unless you really want to do something off the Ui thread. Most of the time you do want to keep things on the Ui thread.
For simple repeating tasks, you can easily repurpose the CountDownTimer class. Often with an (almost) infinite run time or Long.MAX_VALUE (292 million years). The fist onTick happens immediately after starting.
private CountDownTimer mTimer;
private void start() {
if (mTimer == null) {
mTimer = new CountDownTimer(Long.MAX_VALUE, 5000) {
#Override
public void onTick(long millisUntilFinished) {
// start a beeping countdown
new CountDownTimer(5000, 1000) {
private int state = 1;
#Override
public void onTick(long millisUntilFinished) {
playSound(state);
state = state + 1 % 2;
}
#Override
public void onFinish() {
playSound(0);
}
}.start();
}
#Override
public void onFinish() { /* ignore, never happens */ }
};
mTimer.start();
}
}
private void stop() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}

CountDownTimer fire twice?

I have a method to detect is the amplitude below a threshold.
public boolean amplitude_Detection(double ampA) {
//Thresholds for amplitude acceleration
double acceAmplitudeTH = 3.0;
//Compare value with threshold
if (ampA < acceAmplitudeTH) {
return true;
}
return false;
}
Then next in my onSensorChanged, I have if statement if the code above return true, I want to pause my sensor for 5 seconds. After 5 seconds, resume the sensor again. However, during my experiment by throwing phone on bed 10 times in a same position. The timer sometimes will be fired twice and sometimes just one. Anyone know what's happening?
if(algo.amplitude_Detection(ampA))
{
//Pause sensors
pauseSensor();
Toast.makeText(getBaseContext(), "Pause ", Toast.LENGTH_SHORT).show();
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
((TextView)findViewById(R.id.timeCalc)).setText("Time Left: "+millisUntilFinished/1000+"\n"+ampA);
}
public void onFinish() {
((TextView)findViewById(R.id.timeCalc)).setText("Done");
resumeSensor();
}
}.start();
}
}
public void pauseSensor()
{
senManager.unregisterListener(this, sensorAccelerometer);
}
public void resumeSensor() {senManager.registerListener(this, sensorAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);}

Textview not showing aftert couple of VISIBLE and INVISIBLE set

First, I used animation to hide and show TextView. I saw that using animation costing memory. So I used another way:
SetVisibility(VISIBLE) and SetVisibility(INVISIBLE) with TaskTimer
it works well and it performs better considering the memory.
The main issue is that after a restarting the timer for many times, the TextView disappear.
I need to restart the app to get it back again!
this is the code snippet:
myTimerForAnimation = new Timer();
myTimerForAnimation.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() // run on ui thread
{
public void run() {
counter++;
if (counter < 7) {
if (counter % 2 == 1) {
list_textView[x].setVisibility(View.INVISIBLE);
} else {
list_textView[x].setVisibility(View.VISIBLE);
}
} else {
myTimerForAnimation.cancel();
myTimerForAnimation.purge();
list_textView[x].setVisibility(View.VISIBLE);
}
}
});
}
}, 1000, 600);
Dont use Timer use handler,something like this:
// init the runnables
// the runnable should be members
Handler hanlder = new Handler();//If you arent on the UI thread pass a correct looper
for (int i=1; i<7 ; i++){
long delay = i * 1000;
if (i%2==0)
{
handler.postDelayed(mVisibleRunnable,delay);
}else{
handler.postDelayed(mInVisibleRunnable,delay);
}
}
Whereas the get runnablebs should be memebers because if u choose to cancel the callbacks then call
handler.removeCallbacks(runnable);
Play with it. It should fix your issue.
thanks to #EE66 for the loop idea, I used this code to solve my problem:
private void animateView(final View view){
for (int counter = 0; counter < 7; counter++) {
long delay = counter * 1000;
if (counter % 2 == 0) {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.VISIBLE);
}
;
}, delay);
} else {
view.postDelayed(new Runnable() {
public void run() {
view.setVisibility(View.INVISIBLE);
}
;
}, delay);
}
}
}

Handler postDelayed only executes 1 once inside a loop

I'm new in android programming. I have a problem in postDelayed wherein the delay only execute once inside a loop even if the value that I want to call is more than 1.
here is my code
protected void managerOfSound() {
int size = tempq.size();
for (int i = 0; i < tempq.size(); i++) {
String u =tempq.get(i);
//WHOLE
if (u.equals("a4")){
mp = MediaPlayer.create(this, R.raw.a4);
handler.postDelayed(new Runnable(){
#Override
public void run() {
mp.start();
}
},2000);
}else if (u.equals("b4")){
mp = MediaPlayer.create(this, R.raw.b4);
handler.postDelayed(new Runnable(){
#Override
public void run() {
mp.start();
}
},2000);
}
}
}
For example
before playing the mediaplayer, i want a delay of 2 seconds and another 2 seconds so on and so forth depending on how many values i want to call... like for example the values are a4, a4 and a4. i want a delay of 2 seconds everytime the values are called. Is there anyone who can help mo with this? thanks in advance! :)
well your problem is that you are running postDelayedfrom inside a for loop. you do run the handler n times BUT simultaneously. you start all of them at the same time (because it takes less than a milli to finish the foor loop). you should
put a counter on the amount of time. something like
handler.postDelayed(new Runnable(){
#Override
public void run() {
mp.start();
}
},countr += 2000);
Here is a working sample of a runnable with delay timer.
public Runnable timedTask = new Runnable()
{
#Override
public void run()
{
// type code here which will loop with the given delay
//if you want to end the runnable type this in the condition
if(condition) {
handler.removeCallbacks(this);
return;
}
//delay for the runnable
handler.postDelayed(timedTask, 2000);
}
};
and you can call this method from anywhere by typing:
handler.post(timedTask);
hope it helps!

How to stop Runnable on button click in Android?

I have to start runnable on start button click and stop it on pause button click.
My code for start runnable on start button click is
// TODO Auto-generated method stub
//while (running) {
mUpdateTime = new Runnable() {
public void run() {
sec += 1;
if(sec >= 60) {
sec = 0;
min += 1;
if (min >= 60) {
min = 0;
hour += 1;
}
}
Min_txtvw.setText(String.format(mTimeFormat, hour, min, sec));
mHandler.postDelayed(mUpdateTime, 1000);
}
};
mHandler.postDelayed(mUpdateTime, 1000);
//}
now i want to stop that runnable on pause button click
pause_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
play_btn.setVisibility(View.VISIBLE);
pause_btn.setVisibility(View.INVISIBLE);
}
});
How can i stop that runnable on pause button click if anyone knows please help me.
Use
mHandler.removeCallbacksAndMessages(runnable);
in pause button click.
Keep a boolean cancelled flag to store status. Initialize it to false and then modify it to true on click of stop button.
And inside your run() method keep checking for this flag.
Edit
Above approach works usually but still not the most appropriate way to stop a runnable/thread. There could be a situation where task is blocked and not able to check the flag as shown below:
public void run(){
while(!cancelled){
//blocking api call
}
}
Assume that task is making a blocking api call and then cancelled flag is modified. Task will not be able to check the change in status as long as blocking API call is in progress.
Alternative and Safe Approach
Most reliable way to stop a thread or task (Runnable) is to use the interrupt mechanism. Interrupt is a cooperative mechanism to make sure that stopping the thread doesn't leave it in an inconsistent state.
On my blog, I have discussed in detail about interrupt, link.
Complete Code:
iterationCount = 0;
final Handler handler = new Handler();
final int delay = 1000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
//do something
if (iterationCount < 10) {
handler.postDelayed(this, delay);
}
iterationCount++;
Log.e("tag", "after 1 second: " + iterationCount);
}
}, delay);
Use below code :
handler.removeCallbacks(runnable);
Thread thread;
//inside start button
thread=new Thread(new Runnable() {
#Override
public void run() {
sec += 1;
if(sec >= 60) {
sec = 0;
min += 1;
if (min >= 60) {
min = 0;
hour += 1;
}
}
Min_txtvw.setText(String.format(mTimeFormat, hour, min, sec));
mHandler.postDelayed(mUpdateTime, 1000);
});
thread.start();
//inside stop button
mHandler.removeCallbacksAndMessages(runnable);
thread.stop();

Categories

Resources