Making a delay between touch events emulated - android

I am making a piano app in which I need to emulate pressing keys in order to show the user the notes of a song. By using a handler, I am able to make a delay pressing up and down a key.
However, I am not able to make a delay between all the keys which have to be touched. I thought something like this, but I only see the last 2 notes get pressed and sound.
final String[] keys = {"1b","2w","9b","10w","11b","12w"};
handler = new Handler(Looper.getMainLooper());
for(int i = 0; i < keys.length - 1; i++) {
final int nextKey = i+1;
//Method in which I used other handler to delay pressing up and down
pressKey(keys[i]);
//Next key i would like to get pressed with a delay
handler.postDelayed(new Runnable() {
#Override
public void run() {
pressKey(keys[nextKey]);
}
},1500);
}

Instead of using for, use a runnable that will keep posting itself with the specified delay:
new Runnable()
{
int nextKey = 0;
#Override
public void run()
{
pressKey(keys[nextKey]);
if (++nextKey < keys.length)
handler.postDelayed(this, 1500);
// else no more keys
}
}.run();

I feel kinda stupid after all the night trying to figure it out. I just had to make a variable with the delay, and increment it in each iteration.

You can do this with a thread if in pressKey method there is no work that needs to be done in the UI thread.
new Thread(
new Runnable(){
#Override
public void run(){
for(int i = 0; i < keys.length - 1; i++) {
pressKey(keys[i]);
Thread.sleep(1500);
}
}
}
).run();

Related

How to set in android background color to several linearlayouts at time in for() loop?

Android. I am trying to set background colour at time to make some sort of trainer. But this loop set background colour for all 4 LivearLayouts at ONE TIME - after the last iteration. And i need to do it one by one with pauses. How can i do it?
private LinearLayout[] lls;
lls = new LinearLayout[4];
lls[0] = findViewById(R.id.ll01);
lls[1] = findViewById(R.id.ll02);
lls[2] = findViewById(R.id.ll03);
lls[3] = findViewById(R.id.ll04);
public void onClick(View view) throws InterruptedException {
for (int i = 0; i < 4; i++) {
Thread.sleep(3000);
lls[i].setBackgroundColor(Color.parseColor("red"));
}
}
Such a code changes colour for all 4 objects at once - after the end of the 4th iteration. Prior to this, the colour of none has changed.
I think you should use a handler instead of for loop. Handlers are more convenient for delaying and doing some stuff. I am putting some edited code for you.
private LinearLayout[] lls;
private Long timeInMillis = 3000L;
private Handler handler;
private Runnable runnable;
private int index = 0;
private void setColors(){
lls = new LinearLayout[4];
lls[0] = findViewById(R.id.ll01);
lls[1] = findViewById(R.id.ll02);
lls[2] = findViewById(R.id.ll03);
lls[3] = findViewById(R.id.ll04);
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
if(index!=lls.length){
lls[index++].setBackgroundColor(Color.parseColor("red"));
handler.postDelayed(runnable,timeInMillis);
}
}
};
handler.postDelayed(runnable,timeInMillis);
}
It was wrong code. You cant change smth in activity in one thread. It was solved by adding thread with loop that sends Broadcast messages for BroadcastReciever in MainActivity.

How to call more than one methods at regular interval using handlers?

I know how to use handler and runnable to call a method at regular intervals of time. But now I want to call more than one method at regular interval of time. Below is the code in one of my classes:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
for(int index = 0; index < count; index++) {
//Do something based on the index value
}
handler.postDelayed(runnable, 500);
}
};
Somewhere in my code I will have the below code to start the execution:
handler.postDelayed(runnable, 0);
So the first method corresponding to index 0 will be called first followed by other methods. And then there will be a 500ms delay to repeat the same.
But I also want a 500ms delay between the method calls. I mean when the for loop is executed. How can I do it using only one handler and runnable? How can I induce a 500ms delay between the method calls?
I would update the value of index across Handler invocations myself, and compare it to yourcount variable just like the for loop
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
private int index = 0;
#Override
public void run() {
//Do something based on the index value
index++;
if (index < count) {
handler.postDelayed(runnable, 500);
} else {
count = 0;
}
}
}
Besides, at the start you don't need to invoke postDelayed() with zero delay, you can directly call post().

How do I delay imageviews from changing

Hello I'm trying to delay imageviews to give a perception that they are being taken out one by one. I've tried
Thread.Sleep
CountDownTimer
Runnable/Handler
But they either only delay once and both imageviews change at the same time or do not delay at all. For some reference I'm trying to do something like
private void delaycard(final int Card) {
newcard(Card); //Delay this before it is called
}
Willing to try/retry anything at this point
Off the top of my head, try something like this:
Handler h = new Handler();
//for the number of images we have
for (int i = 0; i < numImages; i++) {
//we create a runnable for that action
Runnable r = new Runnable() {
#Override
public void run() {
newCard(card);
}
};
//this is the amount of time to delay it by
delay = delay + 500;
//effectively, we're creating a series of runnables at the same time
//but they activate one after the other in .5s intervals
h.postDelayed(r, delay);
}
put this inside your method
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
newCard(Card);
}
}, 100);

Problem getting timer to work after cancelling one iteration and starting another

I am stuck trying to get my timer to work, where I will do one countdown, then go back and do another.
So, on the second call to timer.scheduleAtFixedRate I get an IllegalStateException, but I am cancelling the TimerTask not the Timer.
What I want to do is count down twenty seconds, then ten seconds, then repeat, updating a text box each time, to inform the user what they should be doing.
One issue is that the countdown is faster than once/second.
04-22 01:34:57.118: DEBUG/TestHandler1(404): message called:2:null
04-22 01:34:57.709: DEBUG/TestHandler1(404): message called:3:null
04-22 01:34:57.899: DEBUG/TestHandler1(404): message called:4:null
04-22 01:34:58.198: DEBUG/TestHandler1(404): message called:5:null
Here is my exception:
04-22 01:35:48.529: ERROR/AndroidRuntime(404): java.lang.IllegalStateException: TimerTask is scheduled already
04-22 01:35:48.529: ERROR/AndroidRuntime(404): at java.util.Timer.scheduleImpl(Timer.java:574)
04-22 01:35:48.529: ERROR/AndroidRuntime(404): at java.util.Timer.scheduleAtFixedRate(Timer.java:530)
Here is the code I used for this attempt. When I tried to use a different timertask for each loop it was even worse behavior, as I put the new TimerTask block just before timer.scheduleAtFixedRate, so I went back to this version.
handler = new Handler() {
public void handleMessage(Message msg) {
counterText.setText((new Date()).toString() + " "
+ Integer.toString(cntr));
System.out.println("handleMessage");
}
};
timertask = new TimerTask() {
public void run() {
handler.sendEmptyMessage(0);
cntr++;
if (cntr > maxReps) {
timertask.cancel();
cntr = 0;
}
}
};
doneButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cntr = 0;
for (MyClass mclass : input.getLoop()) {
labelText.setText(mclass.getName());
for (int y = 0; y < 8; y++) {
maxReps = 20;
timer.scheduleAtFixedRate(timertask, 0, 1000);
maxReps = 10;
labelText.setText("Rest");
timer.scheduleAtFixedRate(timertask, 0, 1000);
}
}
}
});
Hopefully someone can point out a simple mistake that I made.
Above is a snippet of my code from the Activity, so I am including just what I think is needed to show where I am having a problem.
Given this article in the dev guide: http://developer.android.com/resources/articles/timed-ui-updates.html and a similar post here: http://cart.kolix.de/?p=1438 , I would suggest you to change the strategy and use handler.postDelayed(this, 2000);
But, specifically to the code, my guess is that it may get cancelled the wrong task. I don't really understand the rationale for having two calls to timer.scheduleAtFixedRate(timertask, 0, 1000); and setting maxReps = 20; first and then maxReps = 10; in the same loop, because the loop will not wait for the task to complete before continuing.
So, you are sending at least 16 calls to timer.scheduleAtFixedRate() and not all may get cancelled at the right time.
After experimenting with various methods, I finally settled on this solution.
In my OnCreate method I had this code, and it would go 20 seconds then exit.
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String s = msg.getData().getString("counter");
counterText.setText(s);
Log.d("Activity.handleMessage", s);
}
};
final Runnable runnable = new Runnable() {
#Override
public void run() {
final long start = SystemClock.uptimeMillis();
while (true) {
Message m = new Message();
Bundle b = new Bundle();
b.putString("counter", Integer.toString(cntr));
m.setData(b);
handler.sendMessageDelayed(m, cntr * 1000);
if (cntr++ == maxReps) {
return;
}
}
}
};
doneButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
exerciseText.setText(model.getName());
counterText.setText("0");
maxReps = 20;
handler.postDelayed(runnable, 1000);
});
Part of my difficulty is not thinking about how Android works. I found various approaches that didn't work well.

(Android) Why won't invalidate() update my buttons immediately?

I have read several forums and examples on using invalidate() in order to update views immediately but I still do not understand why what I am doing will not work. The code below uses image buttons defined by "red", "blue", "green", and "yellow". I set a 1 second delay between each time I try and change a button's appearance. Please someone tell me what i'm doing wrong.
private void showPattern() {
if (correct == true) {
for (int k = 0; k < temp_basket.length; k++) {
if (temp_basket[k] == 0) {
red.setPressed(true);
red.invalidate();
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
red.setPressed(false);
red.invalidate();
}
});
}
}, 1000);
There are 3 more or these blocks after this one that are blue, green, and yellow.
Invaliadate puts a redraw message in the queue
As I see in your code, there are multiple redraws happening on after the other... the OS will try to optimize the rendering by clubbing multiple redraw messages into one (under the condition that there's no other message between them).
What you may want to do is:
private Handler myHandler = new Handler() {
public void handleMessage(Message msg)
{
switch(msg.what) { /* do your work */ }
}
};
Message msg = Message.obtain(myHandler);
msg.what = <some-number>;
msg.obj = <your-data-to-process>
if(myHandler.containsMessage(<same-number>) {
myHandler.removeMessages(<same-number>);
}
myHandler.sendMessage(msg);
You can also try using postInvalidate() method, which will cause the invalidate in the UI thread.

Categories

Resources