I have a 5 seconds count down timer and I need to detect the amplitude of acceleration within the duration. If the amplitude meet the statement, a true will be return. However, due to the void method OnTick and also it is an inner class, I couldn't return or pass any value to outer class.
public boolean low_high_Detection(final double ampA) {
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
final double low_TH = 9.0, high_TH = 10.5;
boolean lying_on_floor = false;
if(ampA > low_TH && ampA <high_TH)
{
lying_on_floor = true;
}
}
public void onFinish() {
Toast.makeText(detect.getBaseContext(), "5 seconds dectection over",Toast.LENGTH_SHORT).show();
}
}.start();
if (lying_on_floor == true)
{
return true;
}
return false;
}
Anyone can suggest me how can I fix this method? Or there is another way to deal with it.
This can be achieved with an anonymous class as a listener.
Declare an interface which actues as a listener.
public interface LowHightDetectionListener {
void onDetected(boolean result);
}
Then, to call this method and pass an instance of this listener to the method low_high_Detection()
low_high_Detection(ampA, new LowHightDetectionListener {
#Override
public void onDetected(boolean result) {
// Process the result
}
});
Here you get the "returned" value.
To return the desired value inside the low_high_Detection() method you need to call the listener.
public void low_high_Detection(final double ampA, final LowHightDetectionListener callback) {
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
final double low_TH = 9.0, high_TH = 10.5;
boolean lying_on_floor = false;
if(ampA > low_TH && ampA <high_TH) {
lying_on_floor = true;
callback.onDetected(true); // EXAMPLE OF RETURNING VALUE INSIDE AN ANONYMOUS CLASS
}
}
public void onFinish() {
Toast.makeText(detect.getBaseContext(), "5 seconds dectection over",Toast.LENGTH_SHORT).show();
}
}.start();
if (lying_on_floor == true) {
callback.onDetected(true);
return;
}
callback.onDetected(false);
}
}
Related
My app is built with around 50-60 screens. Each screen has a button to open a new screen. Now the issue I am facing is when user double tap button, a new screen is open twice.
For this issue, I found a solution like below.
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000){
return;
}
mLastClickTime = SystemClock.elapsedRealtime();
But to prevent double click, I need to write the above code in each button click. I have not created common custom button which used everywhere.
Is there any way to double tap on app level?
i got same issue i solved it as below it might be helpfull for you.
you can achive by two ways
One:
try to using a boolean variable:
public class Blocker {
private static final int BLOCK_TIME = 1000;
private boolean isBlockClick;
/**
* Block any event occurs in 1000 millisecond to prevent spam action
* #return false if not in block state, otherwise return true.
*/
public boolean block(int blockInMillis) {
if (!isBlockClick) {
isBlockClick= true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
isBlockClick= false;
}
}, blockInMillis);
return false;
}
return true;
}
public boolean block() {
return block(BLOCK_TIME );
}
}
use this as below in every click.
button.setOnClickListener(new View.OnClickListener() {
private Blocker blocker = new Blocker();
#Override
public void onClick(View v) {
if (!blocker.block(block-Time-In-Millis)) {
// do your action
}
}
});
Two
or you can set button.setEnable(false) on every clickevent of button as below
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btn.setEnabled(false);
}
});
actually you can set the activities not to have multiple instances by adding the flag Intent.FLAG_ACTIVITY_REORDER_TO_FRONT to the intent.
see answer from other question
If the activity is in the stack, it will not be created twice
use this custom class it can handle any doubletab or single tab on button click event
public class DoubleTabCustomButton implements View.OnClickListener {
private boolean isRunning = true;
private int resetInTime = 500;
private int counter = 0;
private DoubleClickCallback listener;
public DoubleTabCustomButton(Context context) {
listener = (DoubleClickCallback) context;
}
#Override
public void onClick(View v) {
if (isRunning) {
if (counter == 1) {
listener.onDoubleClick(v);
}
else if (counter==0){
listener.onSingleClick(v);
}
counter++;
if (!isRunning) {
isRunning = true;
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(resetInTime);
isRunning = false;
counter = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
}
it's interface
public interface DoubleClickCallback {
public void onDoubleClick(View v);
public void onSingleClick(View V);
}
and finally you can use in activity like this
public class ButtonDoubleTab extends AppCompatActivity implements DoubleClickCallback {
Button btndoubletab;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_double_tab);
btndoubletab=findViewById(R.id.btndoubletab);
// btndoubletab.setOnClickListener(this);
btndoubletab.setOnClickListener(new DoubleTabCustomButton(this));
}
#Override
public void onDoubleClick(View v) {
//do double tab action
}
#Override
public void onSingleClick(View V) {
//single tab action
}
}
If you have a base activity class, you can override the startActivity(Intent) method to add the Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
abstract class BaseActivity: AppCompatActivity() {
final override fun startActivity(intent: Intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
super.startActivity(intent)
}
}
Use this inline function:
inline fun View.onSingleClick(minimumClickInterval: Long = 800, crossinline onClick: (View?) -> Unit) {
var isViewClicked = false
var mLastClickTime = 0L
setOnClickListener { view ->
val currentClickTime = SystemClock.uptimeMillis()
val elapsedTime = currentClickTime - mLastClickTime
mLastClickTime = currentClickTime
if (elapsedTime <= minimumClickInterval)
return#setOnClickListener
if (!isViewClicked) {
isViewClicked = true
Handler(Looper.getMainLooper()).postDelayed({ isViewClicked = false }, 600)
} else {
return#setOnClickListener
}
onClick(view)
Log.d(this.javaClass.simpleName, "onSingleClick successfully called")
}
}
Use with any view like this:
button.onSingleClick {
// do something here on the button click
}
You can also set the minimum click interval like this:
button.onSingleClick(1000) {
// do something here on the button click
}
make the button disable on click .
b.setEnabled(false);
You can make it back enable it onResume or any other certain callback
b.setEnabled(true);
I have implemented one counter and onFinish() of first counter,I started second counter but the first counter not able to finish.Text "Bye Guyz" remain for some time so how to finish the text.
Please help me.
Thanks in advance.!!!
Code :-
counter= new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
if (count == 0) {
tv.setText("First counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Guyz");
}
}
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
else if(flag) {
counter1 = new CountDownTimer(9000, 1000) {
public void onTick(long millisUntilFinished) {
flag = false;
tv.setText("Second counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Girls");
count = 0;
}
public void onFinish() {
tv2.setVisibility(View.VISIBLE);
tv2.setText("Bye Girls");
count = 0;
}
}.start();
Did you "debug" the code to be sure the code is arriving to counter1 = new CountDownTimer(9000, 1000)?
Are you sure when the first counter arrives to onFinish() the flag variable is true?
Why do you call counter.cancel() in onFinish() when obviously the counter is already over?
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
If you say your tv2 displays "Bye Guyz" it means that your flag is set to false, so the "else if" part is not being executed. onFinish() is only executed once, so you need to make sure the flag is set for true to start the second counter.
Also you shouldn't cancel your counter in onFinish() because it's already finished.
Here is my alternative is as follows
Create the custom Counterextending Thread
class Counter extends Thread {
private long timeOne, timeTwo;
private OnCounterFinishedListener mCounterFinishedListener;
private Thread t;
Activity activity = null;
Counter(Context context){
t = new Thread(this);
activity = (Activity)context;
}
#Override
public void run() {
try {
sleep(timeOne);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.firstCounterFinished();
}
});
sleep(timeTwo);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.secondCounterFinished();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void setTimes(long timeOne, long timeTwo){
this.timeOne = timeOne;
this.timeTwo = timeTwo;
}
public void start(OnCounterFinishedListener listener){
mCounterFinishedListener = listener;
t.start();
}
interface OnCounterFinishedListener{
void firstCounterFinished();
void secondCounterFinished();
}
}
Then inside your main thread you can start this counter as
final Counter counter = new Counter(this);
counter.setTimes(5000, 5000);
counter.start(new Counter.OnCounterFinishedListener() {
#Override
public void firstCounterFinished() {
// Update your first TextView
}
#Override
public void secondCounterFinished() {
// Update your second TextView
}
});
I'm designing a game and have a problem with countdowntimer not stopping. The timer starts normally as it should, and should stop in the end() method. It works well when ENEMY_HULL is checked as 0 or less, which is calulated seperatly when the users presses a button, and checkEnemyDefeat() is called, but it does not work when ENEMY_CREW is 0. On both situations the message in log cat that the timer is stopped appears, so my guess is that .cancel() is called. I've included all code that seems relevant.
NOTE: All variables including CountDownTimer are global variables
Here is the method containing the timer:
private void BadGameLoop() {
if (GAME_PAUSED == true && !GAME_TIME_STARTED) {
Log.d(" -------- ", "TIMER STARTED");
GAME_PAUSED = false;
GAME_TIME_STARTED = true;
gameTimer = new CountDownTimer(GAME_TIME, UPDATE_RATE) {
#Override
public void onTick(long millisUntilFinished) {
TICKS++;
timer.setText(String.valueOf(GAME_TIME / 1000 - TICKS / 10));
if((CREW_BOARDING > 0 || ENEMY_CREW_BOARDING > 0) && TICKS%10 == 0){
crewFightCalculator();
}
updateViews();
}
#Override
public void onFinish() {
TICKS=0;
GAME_TIME_STARTED = false;
GAME_PAUSED = true;
end();
}
};gameTimer.start();
}
}
Next is the crewFightCalculator method:
private void crewFightCalculator(){
// this just changes the values of ENEMY_CREW (global variable) and then
//calls checkEnemyDefeat() to verify if it should end the timer or not
checkEnemyDefeat();
}
The checkEnemyDefeat and end methods:
private void checkEnemyDefeat(){
if(ENEMY_HULL <= 0){
updateViews();
end();
}else if ( ENEMY_CREW < 1){
updateViews();
end();
}
}
private void end(){
if(GAME_TIME_STARTED){
GAME_TIME_STARTED = false;
gameTimer.cancel();
Log.d("---------"," TIMER STOPPED !");
}
// do more stuff
}
It is simply bizzare to me why it dosen't work. My only guess is that it has something to do with the fact that .cancel() is not triggered by a chain of functions started by user input .
The only solution to this problem that I found, was to modify the onTick method, so that it should check every time if it should run or stop the timer like this:
private void BadGameLoop() {
if (GAME_PAUSED == true && !GAME_TIME_STARTED) {
Log.d(" -------- ", "TIMER STARTED");
GAME_PAUSED = false;
GAME_TIME_STARTED = true;
gameTimer = new CountDownTimer(GAME_TIME, UPDATE_RATE) {
#Override
public void onTick(long millisUntilFinished) {
if(GAME_TIME_STARTED) {
TICKS++;
timer.setText(String.valueOf(GAME_TIME / 1000 - TICKS / 10));
if((CREW_BOARDING > 0 || ENEMY_CREW_BOARDING > 0) && TICKS%10 == 0){
crewFightCalculator();
}
updateViews();
}else{
gameTimer.cancel();
}}
#Override
public void onFinish() {
TICKS=0;
GAME_TIME_STARTED = false;
GAME_PAUSED = true;
end();
}
};gameTimer.start();
}
}
Still, i can't figure out why it didn't work properly before.
I have an animation in my Android app that flashes a TextView different colors. I've used a TimerTask, Timer, and Runnable method to implement this. What I need to do is stop the thread when a user leaves the app during this animation in onPause(), and resume the thread when the user returns to the app in onResume(). The following is the code I've implemented, but it's not working (the onPause(), and onResume() pieces), and I don't understand why. I've read a few other posts on similar matters, but they haven't helped me figure out what to do in my situation. I've read that TimerTasks are outdated, and I should probably use an ExecutorService method; it is unclear to me as how to implement this function.
...timerStep5 = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (b5) {
cashButton2SignalText.setBackgroundColor(Color.RED);
cashButton2SignalText.setTextColor(Color.WHITE);
b5=false;
} else {
cashButton2SignalText.setBackgroundColor(Color.WHITE);
cashButton2SignalText.setTextColor(Color.RED);
b5=true;
}
}
});
}
};
timer5.schedule(timerStep5,250,250);
}
public void onPause(){
super.onPause();
timerStep5.cancel();
}
public void onResume(){
super.onResume();
timerStep5.run();
}
After a TimerTask is canceled, it cannot run again, you have to create a new instance.
Read details here:
https://stackoverflow.com/a/2098678/727768
ScheduledThreadPoolExecutor is recommended for newer code, it handles the cases like exceptions and task taking longer time than the scheduled interval.
But for your task, TimerTask should be enough.
Here's how I did it. Add pauseTimer boolean where ever the pause takes place (button listener perhaps) and don't count timer if true.
private void timer (){
Timer timer = new Timer();
tv_timer = (TextView) findViewById(R.id.tv_locationTimer);
countTimer = 0;
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
String s_time = String.format("%02d:%02d:%02d",
countTimer / 3600,
(countTimer % 3600) / 60,
countTimer % 60);
tv_timer.setText(s_time);
if (!pauseTimer) countTimer++;
}
});
}
}, 1000, 1000);
}
Timer timer1;
private boolean timerStartFlag = false;
private boolean hiddenVisibleFrg = false;
int timerSize = 0;
int videoTime = 0;
#Override
public void onPause() {
super.onPause();
Log.e("keshav", "onPause timer1 " +timer1);
if (timerSize >0 &&hiddenVisibleFrg){
timerStartFlag =true;
}
if (timer1 != null) {
this.timer1.cancel();
}
}
#Override
public void onResume() {
super.onResume();
if (timerSize >0 && timerStartFlag && hiddenVisibleFrg) {
callTimerTask(timerSize);
timerStartFlag = false;
}
}
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
Log.e("keshav", "HomeFragment visible ");
if (timerSize >0 && timerStartFlag) {
callTimerTask(timerSize);
timerStartFlag=false;
}
hiddenVisibleFrg=true;
} else {
Log.e("keshav", "HomeFragment in visible " +timer1);
if (timer1 != null) {
this.timer1.cancel();
}
if (timerSize >0){
timerStartFlag =true;
}
hiddenVisibleFrg=false;
}
}
private void callTimerTask(int size) {
// TODO Timer for auto sliding
printLog("callTimerTask size " + size);
timer1 = new Timer();
timer1.schedule(new TimerTask() {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (getActivity() == null) {
return;
}
if (count1 < size - 1) {
//TODO ADD ME kk
count1++;
} else {
count1 = 0;
}
if (intro_images != null) {
intro_images.setCurrentItem(count1);
}
videoTime++;
Log.e("KeshavTimer", "callTimerTask videoTime " + videoTime);
}
});
} else {
printLog("callTimerTask getActivity is null ");
}
}
}, 1000, 1000);
// TODO 1000, 3000;
}
For Kotlin user, checkout this
How to use:
// Init timer
lateinit var timerExt: CountDownTimerExt
timerExt = object : CountDownTimerExt(TIMER_DURATION, TIMER_INTERVAL) {
override fun onTimerTick(millisUntilFinished: Long) {
Log.d("MainActivity", "onTimerTick $millisUntilFinished")
}
override fun onTimerFinish() {
Log.d("MainActivity", "onTimerFinish")
}
}
// Start/Resume timer
timerExt.start()
// Pause timer
timerExt.pause()
// Restart timer
timerExt.restart()
Ok,I need to create an infinite loop on a countdown. My code is:
public void countdown() {
if (x != null) {
x.cancel();
}
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
}
};
x.start();
}
x is just a static countdowntimer variable. The problem is that I tried many methods to make the above code work,I mean when the countdown ends,and it displays that notification,it should start again and so on....but I can't find a way to do it.
Hope this will help you.
public void countdown(){
if (x != null) {
x.cancel();
}
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
x.start();
}
};
}
For the record CountDownTimer(long millisInFuture, long countDownInterval)
// A not so infinite but close to infinte interval for each second
CountDownTimer cdt=new CountDownTimer(Long.MAX_VALUE, 1000) { .... }
Where Long.MAX_VALUE = 9223372036854775807 miliseconds or around 292 million of years (seconds more or less)
Its not infinite but its incredibly long.
is to restart your timer when his has finished :)
like this :
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
start();// here, when your CountDownTimer has finished , we start it again :)
}
};
x.start();
Simple way to create an infinite loop:
Every one secod call method
new CountDownTimer(1000, 1000)
{
public void onTick(long l) {}
public void onFinish()
{
//Code hear
start();
}
}.start();
Why not just use a regular Timer? It will repeat on a specified interval until you call cancel(), something like:
public void countdown() {
if (x != null) {
x.cancel();
}
x = new Timer("timerName");
x.schedule(_timerTask, 0, 20000);
}
private static final TimerTask _timerTask = new TimerTask() {
#Override
public void run() {
showNotification();
}
};
You can just use a while loop:
while (true) {
// do stuff
}
When it has done "the stuff" it wil start again, infinite!
to keep your timer working just put
<countdowntime>.start();
in the onfinish block
Well, I have implemented an indefinite timer that takes multiple listeners and calls them simultaneously on a specific interval.
import android.os.CountDownTimer;
import java.util.Arrays;
public class InfiniteCounter extends CountDownTimer {
private static final int MAX_LISTENERS = 100;
private static InfiniteCounter timer;
private static InfiniteCounterListener[] listenerList = new InfiniteCounterListener[MAX_LISTENERS];
private InfiniteCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
//Milliseconds Intervals in which the counter should call its listeners
public static InfiniteCounter initInstance(int intervalMillis) {
removeAllListeners();
if (timer == null) {
timer = new InfiniteCounter(60 * 60 * 1000, intervalMillis);
timer.start();
}
return timer;
}
public static void attachListener(InfiniteCounterListener listener) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] == null) {
listenerList[i] = listener;
break;
}
}
}
public static void removeListener(InfiniteCounterListener listener) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] == listener) {
listenerList[i] = null;
break;
}
}
}
private static void removeAllListeners() {
Arrays.fill(listenerList, null);
}
public static void stopTimer() {
removeAllListeners();
if (timer != null) timer.cancel();
timer = null;
}
#Override
public void onTick(long l) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] != null) listenerList[i].onTick();
}
}
#Override
public void onFinish() {
timer.start();
}
public interface InfiniteCounterListener {
void onTick();
}
}
Just Attach listeners to this class and with single timer, it can call multiple listeners -- which makes is very performance optimised.