First app ever for me, and first time experiencing with java coding.
I'm building an app for assisting my Rubiks cube speed training, and i'm stuck on my timer.
My general plan is:
I have my main activity screen, where with 1 touch (anywhere on the screen except my 2 buttons) can start a timer. When the timer starts the buttons will fade, and only the timer is visible.
At this moment I have my MainActivity, and a Timer activity. When pressing the screen the timer activity "launches". I then have to press once more to start the timer, this is ok for now, I will fix it somewhat later.
My main goal for now is:
On the timer activity, I want to press and HOLD for at least 2 seconds, and THEN upon release, the timer must start. Hereafter, with a new click, the timer must stop.
I have searched, but it is difficult with minimum knowledge. I have tried a few different things. And what I have is basically something like this.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
TimerView = (TextView) findViewById(R.id.TextTimerView);
View StopTimeView = (View) findViewById(R.id.StopTimeView);
StopTimeView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
starttime = SystemClock.uptimeMillis();
timerhandler.postDelayed(timerrunnable,2000);
timestarted = true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
if(timestarted = true){
timestarted = false;
timerhandler.removeCallbacks(timerrunnable);
}
}
return true;
}
});
}
This code stops when the touch is released. If I remove the last IF sentence, the timer automatically starts after the given 2 seconds, no matter if I hold or not. Furthermore, I need to add an additional button to stop the timer, which I do not want (the ability to be able to stop by touching everywhere is important).
I hope the question is understandable and not to vague. If more of the code is needed, please let me know.
Thanks for your time!
Simply check in your timerrunnable if the button is still pressed. Also, start the onTouch method with a check whether your timer is running. If it is, you know you want to stop it - if it isn't, you can continue with the code you already have.
Related
I'm making match3 game on libGdx. After scanning for matches I have to wait for animations to complete and run scanning again until no more matches left. I do it with Java Timer and when I run application on desktop it works fine but on Android device it crashes after one, two or few more iterations. Any ideas what is wrong?
Timer animationTimer;
scanForMatches(){
//do some stuff
//...
checkAnimationComplete();
}
checkAnimationComplete(){
animationTimer = new Timer();
animationTimer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run() {
boolean animDone = true;
// do some stuff to
// check if anim done
if (animDone){
animationTimer.cancel();
scanForMatches();
}
}
}, 1000, 100);
}
Without looking at the rest of your code, I would highly suggest dropping the timer altogether as it is almost certainly unnecessary in this case and not very efficient. Are you using an Action to animate with a stage, or are you manually moving things based on position in draw()? If you are just moving something in draw(), I would use a boolean flag to signal that it has reached it's destination, like if you are dropping down solved tiles or something. If you are using an Action, it is possible to use a new Action to act as a callback like the following...
myGem.addAction(Actions.sequence(
Actions.moveTo(230f, 115f, 0.25f, Interpolation.linear),
new Action() {
public boolean act(float delta) {
System.out.println("Done moving myGem!");
scanForMatches();
return true;
}
}));
There are quite a few ways to do what you're looking for depending on how you have your grid set up. Post up how you are animating whatever it is so I can take a look. Basically, you need to know exactly when it is done animating so that you can fire off your scan method again.
I have this loop
while (true) {
game.update();
view.repaint();
Thread.sleep(DELAY);
}
In the game.update various components of the game have their position changed and those updates are reflected when the repaint() method is called on the view. The view extends JComponent and loops through the game objects and calls their print methods.
What I want to do is have a boolean called nextLevel in the game and if it's true Flash text on the screen for the player to notify them that they're going onto the next level. Maybe flash 4-5 times. Then continue the game.
Is this possible? I have been playing around with Thead.Sleep() but this only seems to pause the displaying and in the background the game is still going on.
Any ideas on how to do this?
Maybe you want to avoid threading by using a Timer object.
an example like that could be
int flashTimer = 0;
if(nextLevel) {
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
//flash something method here
flashTimer++;
}
});
timer.start();
}
and then check your flashTimer if it reaches the number you want then just stop the timer by timer.stop();
Just an idea which seems to me a bit simpler. the 1000 value is milliseconds which is passed and executes the code inside the actionPerformed method every 1 sec.
Hope it helped
So I have spent a long time looking to see if there is a solution for this. Basically, the below code allows me to press on a button, when I press (action_down) the 'pressed version' of the button is displaying good, then when I remove my finger the graphic returns to normal (action_up).
This part is working good BUT I need the ACTION_DOWN to stay active a little longer after the user presses the button and not return to ACTION_UP so fast. I can see lots of different people asking this question but no answers relating to editing the action_up or action_down part. I thought there must be some simple way to achieve this goal..
The current code:
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
int img = Integer.parseInt(v.getTag(R.id.tag_press_down_img).toString());
if (v instanceof ImageView) {
((ImageView) v).setImageResource(img);
}
} else if (MotionEvent.ACTION_UP == event.getAction()) {
int img = Integer.parseInt(v.getTag(R.id.tag_press_up_img).toString());
if (v instanceof ImageView) {
((ImageView) v).setImageResource(img);
}
}
return false;
}
(This code is working fine but the user experience is bad because the button reverts back to ACTION_UP too fast (immediately) after being released - I would like ACTION_DOWN to 1) display for 1-2 seconds then revert back to ACTION_UP OR 2) remain in action_down until the called event is complete - in this case loading another screen).
Thank you!
I've created a button to trigger a pulse LED action on my app, but I cant make it pulse forever. It always Pulses by value ( on the example above you will see it pulses 10 times and then stops )
//Button Pulse
Button bpulse = (Button) findViewById(R.id.bpulse);
bpulse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent led = new Intent(IlluminationIntent.ACTION_START_LED_PULSE);
led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.devsgonemad.xslc");
led.putExtra(IlluminationIntent.EXTRA_LED_ID,
IlluminationIntent.VALUE_BUTTON_2);
led.putExtra(IlluminationIntent.EXTRA_LED_NO_OF_PULSES, 10);
led.putExtra(IlluminationIntent.EXTRA_LED_PULSE_ON_TIME, 1000);
led.putExtra(IlluminationIntent.EXTRA_LED_PULSE_OFF_TIME, 1000);
led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, m_ledColor);
startService(led);
m_isEnabled = true;
}
How can I make this pulse forever when the button is pressed until the user goes back to the app and stops it from pulsing?
Best regards
How about using a while loop? You could put the number of pulses as 1, and let this run continuously in a while loop, until some condition (in your case some button is pressed) is satisfied.
while(buttonNotPressed){
led.putExtra(IlluminationIntent.EXTRA_LED_NO_OF_PULSES, 1);
startService(led);
}
Ofcourse this has an obvious pitfall that you may start many parallel services all trying to flash the LED once. But I guess you can control your while loop to wait for the service to end before you start the next iteration.
EDIT: For the while loop to wait for your service, you will need to add some sort of flag inside your service on which the while loop can wait. Once the service finishes, the flag can be set and the while loop can move onto the next iteration, thus giving you infinite rounds of flashes until the button is pressed.
Inside of the onReceive(Content context, Intent intent) method of my public class MediaButtonIntentReceiver extends BroadcastReceiver I need to count the number of headset button clicks (single, double, triple), which is denoted by KeyEvent.ACTION_DOWN of the ACTION_MEDIA_BUTTON.
What I have almost works, but my current algorithm sucks and is unreliable after a few times. Basically every successive ACTION_DOWN (hit within a certain number of milliseconds to the previous ACTION_DOWN) I do numClicks++. But also I need to see when the user is done pressing, so after each event I start a CountDownTimer, and if by the time it runs out there are no new clicks, then I'm done and now know the number of clicks.
The problems I'm running into are as follows: for one, the button itself seems noisy - if I press it too fast I usually miss a click. Two, after a few trials when the app it loaded, it starts getting random and I'm assuming that there are multiple CountDownTimer threads (is that the right word?) still running which screws my stuff up.
Anyways here's the main code snippet:
//note: thisClickTime uses System.currentTimeMillis()
if (action == KeyEvent.ACTION_UP) {
if (isDown == true) {
if (numClicks == 0 && lastClickTime == 0) {
//we have a new click
numClicks++;
lastClickTime = thisClickTime; //update the click time
isDown = false;
elapsedTime = thisClickTime - lastClickTime;
} else if (thisClickTime - lastClickTime < clickDelay) { //&& thisClickTime - lastClickTime > 10
numClicks++;
lastClickTime = thisClickTime;
isDown = false;
}
final int oldNumClicks = numClicks;
final CountDownTimer checkIfDone = new CountDownTimer(clickDelay, 10) {
public void onTick(long millisUntilFinished) {
if (oldNumClicks != numClicks) {
cancel();
}
}
public void onFinish() { //code that executes when counter is done
if (oldNumClicks == numClicks) {
//if user doesn't click anymore in time clickDelay + X milliseconds, then it's done
Toast.makeText(context, "Number of clicks: " + Integer.toString(numClicks), Toast.LENGTH_SHORT).show();
//reset state variables
numClicks = 0;
lastClickTime = 0;
}
}
}.start();
} else {
//?
}
}
For reference, I've been looking around at stuff like:
http://musicqueueproject.googlecode.com/svn-history/r83/trunk/src/com/yannickstucki/android/musicqueue/old/PlayerService.java
To see if there's a good way to register number of clicks. I don't really understand their code too well though, and from what I can see they only deal with single/double clicks (I may need triple and quadruple).
EDIT - uploaded the current code I'm working with. It works pretty decently most of the time. Here's what I've noticed though: if I do my button testing too close together in time, the results start screwing up and under counting the clicks. I think this is because other CountDownTimers from previous attempts are still open, and when they finish, they reset certain state variables (numClicks = 0, for one). So am I misusing the timer? I can't think of another solution though as I need some concept of elapsed time after the last click to determine when the clicking is done.
Thanks for any help.
If your BroadcastReceiver is registered in the manifest, the BroadcastReceiver will only exist for a single call to onReceive() -- subsequent broadcasts may result in another BroadcastReceiver instance. And a manifest-registered BroadcastReceiver cannot fork threads, as the whole process may get shut down once onReceive() is over.
I am skeptical that there a clean way to get your code to be reliable, as the media button simply was not designed for your intended use pattern.