So I am trying to start my sensor reading method after 10 seconds and stop it after say 5 minutes. This is the code for the same.
case R.id.btn_pos_poll_side: {
final Handler handler = new Handler();
//Delay Runner Here
handler.postDelayed(new Runnable() {
#Override
public void run() {
side_output.setText("Delayed Data Collection");
//Start reading LIGHT SENSOR Data, Handle Null Light Sensor Data
if (LightSensor != null || mProximity != null || mAccelerometer != null || mGyroscope != null) {
//listen to light sensor.
mySensorManager.registerListener(
MultiSensorListener,
LightSensor,
SensorManager.SENSOR_DELAY_NORMAL);
//listen to proximity sensor.
mySensorManager.registerListener(
MultiSensorListener,
mProximity,
SensorManager.SENSOR_DELAY_NORMAL);
//listen accelerometer, note this has 3-axes.
mySensorManager.registerListener(
MultiSensorListener,
mAccelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
//listen gyroscope, note this has 3-axes.
mySensorManager.registerListener(
MultiSensorListener,
mGyroscope,
SensorManager.SENSOR_DELAY_NORMAL);
//print output text
side_output.setText(Html.fromHtml("<h3> ----- Data Collection Session Starts Here -----</h3>"));
} else {
side_output.setText("No Sensor Found!");
}
}
}, 10000);
final Handler closeHandler = new Handler();
//Data Sender Runner Here
closeHandler.postDelayed(new Runnable() {
#Override
public void run() {
Button stopCollection = (Button) findViewById(R.id.btn_stop_poll_side);
stopCollection.performClick();
}
}, 120000);
break;
}
However this never works and even the data collected is somewhat corrupt (new data is concatenated to previous data).
What am I doing wrong?
Thanks.
Edit: Some more details. I want to start it after 10 seconds from when I have pressed the button and stop it after say 2 minutes. This happens only once unless I press the button again.
Added: Stop Button Logic
case R.id.btn_stop_poll_side: {
// remove sensor listener
mySensorManager.unregisterListener(MultiSensorListener,
LightSensor);
mySensorManager.unregisterListener(MultiSensorListener,
mProximity);
mySensorManager.unregisterListener(MultiSensorListener,
mAccelerometer);
mySensorManager.unregisterListener(MultiSensorListener,
mGyroscope);
side_output.append("\n" + sensorReading);
/*
Reading data and writing to Dropbox!
*/
new DropboxTask(side_output, "Back Pocket Data Reading", sensorReading).execute();
break;
}
When user presses the button the first time:
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do what you need to do
}
}
handler.postDelayed(runnable, 10_000 /* Wait 10 seconds */);
When the user presses the button the second time:
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// Stop what you want to stop
}
}
handler.postDelayed(runnable, 2*60*1000 /* Wait 2 minutes */);
This has to be done in the onClick of your button:
First define a private boolean like called isButtonAlreadyClicked = false.
Now:
yourButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
if(!isButtonAlreadyClicked) {
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do what you need to do
}
}
handler.postDelayed(runnable, 10_000 /* Wait 10 seconds */);
isButtonAlreadyClicked = true;
} else {
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// Stop what you want to stop
}
}
handler.postDelayed(runnable, 2*60*1000 /* Wait 2 minutes */);
isButtonAlreadyClicked = false;
}
});
EDIT:
If you want to prevent the runnable to be run while it is waiting, just make sure to declare the handler and your runnables outside of your method (inside your class), so that you can do (for example):
mHandler.removeCallbacks(firstRunnable);
mHandler.removeCallbacks(secondRunnable);
In that way it won't run the Runnables anymore.
Related
I need that a button can run automatically every 1-2 seconds, and, when the if condition (that i have in the method which is used by the button) is fulfilled, this function must be stopped.
I've tried this but it wasn't what i wanted because with this code the button only runs one time:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Consulta.performClick();
}
}, 1000);
onClick of my button:
public void consultaBD(View view)
{
DB db = new DB(getApplicationContext(),null,null,1);
String buscar = text_view.getText().toString();
String[] datos;
datos=db.buscar_reg(buscar.trim());
db.infraccion(buscar.trim());
if(datos[2] =="Encontrado")
{
App.matricula=buscar;
startActivity(new Intent(getApplicationContext(), MatriculasActivity.class));
Toast.makeText(getApplicationContext(),datos[2],Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getApplicationContext(),datos[2],Toast.LENGTH_SHORT).show();
}
}
Another method would be to use Timers to initiate the button click every x seconds. However, in this answer I'll stick with the method you're using. Your handler appears to be incorrect, try something like this instead:
Replace your handler with:
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
Consulta.performClick();
handler.postDelayed(this, 1000);
}
};
And initiate it with: (where 1000 is the time (in milliseconds) between each execution)
handler.postDelayed(runnable, 1000);
UPDATE:
You have also requested that the event is fired when the text inside of a textbox is changed. To do this, you need to create a new event listener (make sure you replace field1 with the actual reference to your textbox):
field1.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
/* Add the Handler Call here */
handler.postDelayed(runnable, 1000);
}
});
whatever context I understood, here is the raw code which may help you.
Handler handler = new Handler();
//initialize this method once by either clicking on button or as the activity starts
void checkAndPerformClick(boolean conditionFulfilled) {
if (conditionFulfilled) {
handler.removeCallbacksAndMessages(null);
return;
}
handler.postDelayed(new Runnable() {
#Override
public void run() {
Consulta.performClick();
checkAndPerformClick(datosEqualsEncontrado());
}
}, 1000);
}
boolean datosEqualsEncontrado() {
// apply your logic here as the name suggests
return false;
}
I need to delete a value from SharedPreferences after 5 minutes or when the user finished to do something . So when I add that value I start this:
Activity A
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
}, Utils.TIME_BEFORE_DELETE);
and in the case users finished all I do this:
Activity B
mySharedPrefernces.removeValue(mContext, Utils.MY_VALUE);
But how can I stop the Handle into second activity?? Or is there another way to do it??
you can you boolean variable if you want to cancel this.
create public static boolean to check if the task is cancelled or not.
public static boolean isCanceled = false;
Use this in run() method
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (!isCanceled)
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
}, Utils.TIME_BEFORE_DELETE);
if you want to cancel then set:
isCanceled = true;
Runnable run = new Runnable() {
#Override
public void run() {
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
};
Handler handler = new Handler();
handler.postDelayed(run, Utils.TIME_BEFORE_DELETE);
//to dismiss pending runnable
handler.removeCallbacks(run);
A better way to do: Example code
publc static final Handler handler = new Handler();
public static final Runnable runnable = new Runnable() {
public void run() {
try {
Log.d("Runnable","Handler is working");
if(i == 5){ // just remove call backs
handler.removeCallbacks(this);
Log.d("Runnable","ok");
} else { // post again
i++;
handler.postDelayed(this, 5000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
//now somewhere in a method
b1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, 5000);
}
});
You can use handler.removeCallbacksAndMessages(null);. More information link
In this case you can use service with sticky flags. So you start service with intent "start_handler" and start handler also. When you need cancel handler you send the intent to stop handler and service. Or when time is passed and handler calls your code you should also stop service.
Using service with sticky flag provides possibility restoring handler. Also you need add some logic saving time when handler was run for correct restoring handler.
For that you can't use direct Runnable inside handler, you need to take one instance of it then you can do this like below,
Runnable myRunnable = new Runnable(){};
Then assign this in handler
handler.postDelayed(myRunnable);
And on no need use below line
handler.removeCallbacks(myRunnable);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//add your code hare
finish();
}
}, 10000);
by using this way you can stop your runnable in a fix time
When i click the button ,I want an callback to capture again every 5 seconds. this is my code
but when i try to click again the camera is not shown.
private OnClickListener buttonListener = new OnClickListener() {
public void onClick(View v) {
Handler myHandler = new Handler();
myHandler.postDelayed(mMyRunnable, 5000); // called after 5 seconds
button.setText("Waiting...");
}};
There is no certain timer programmatically for the Camera . so the best thing is that you should create a thread for the camera Action and then repeat that thread after 5 seconds
Your code will trigger only one time ... so what you have to do is that after creation of thread call that thread on button click and the thread will run automatically....
private Handler handler = new Handler();
runnable.run();
private Runnable runnable = new Runnable()
{
public void run()
{
//
// Do the stuff
//
handler.postDelayed(this, 1000);
}
};
I am having trouble with a TimerTask Interfering with In App Purchasing (Async Tasks).
I am weak with Threads, so I believe it is running on the main UI thread, eating up resources.
How can I run this outside the UI thread? I have searched, and tried some suggestions using handlers. but seems like I get the same result, app gets really laggy.
when I don't run this task (refreshes every 500mS), the activity runs smoothly, and there are no hangs during In app purchases.
Your help is appreciated, code snippet below:
public class DummyButtonClickerActivity extends Activity {
protected Timer timeTicker = new Timer("Ticker");
private Handler timerHandler = new Handler();
protected int timeTickDown = 20;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainhd);
// start money earned timer handler
TimerTask tick = new TimerTask() {
public void run() {
myTickTask();
}
};
timeTicker.scheduleAtFixedRate(tick, 0, 500); // 500 ms each
} // End OnCreate
protected void myTickTask() {
if (timeTickDown == 0) {
/// run my code here
//total = total + _Rate;
timerHandler.post(doUpdateTimeout);
}
else if(timeTickDown < 0) {
// do nothing
}
timeTickDown--;
}
private Runnable doUpdateTimeout = new Runnable() {
public void run() {
updateTimeout();
}
};
private void updateTimeout() {
// reset tick
timeTickDown = 2; // 2* 500ms == once a second
}
}
You can use HandlerThread that will run your Handler on a separate Thread
documentation:
Handy class for starting a new thread that has a looper.
The looper can then be used to create handler classes. Note that start() must still be called.
example:
HandlerThread mHandlerThread = new HandlerThread("my-handler");
mHandlerThread.start();
Handler mHandler = new Handler(mHandlerThread.getLooper());
update:
private Runnable doUpdateTimeout;
private HandlerThread mHandlerThread;
private Handler timerHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainhd);
// start money earned timer handler
TimerTask tick = new TimerTask() {
public void run() {
myTickTask();
}
};
mHandlerThread = new HandlerThread("my-handler");
mHandlerThread.start();
timerHandler = new Handler(mHandlerThread.getLooper());
doUpdateTimeout = new Runnable() {
public void run() {
updateTimeout();
}
};
timeTicker.scheduleAtFixedRate(tick, 0, 500); // 500 ms each
} // End OnCreate
protected void myTickTask() {
if (timeTickDown == 0) {
/// run my code here
//total = total + _Rate;
timerHandler.post(doUpdateTimeout);
}
else if(timeTickDown < 0) {
// do nothing
}
timeTickDown--;
}
private void updateTimeout() {
// reset tick
timeTickDown = 2; // 2* 500ms == once a second
}
}
when you want to update the TextView from different thread
call this:
YOU_ACITIVITY_CLASS.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//update here
}
});
The handler is running and processing in the main ui thread,so the method doUpdateTimeout will be executed in the main thread.
In your code, after running 10 seconds later,the timeTickDown equals to 0 and code timerHandler.post(doUpdateTimeout); will be invoked,which will be executed in the main thread. Because it just let timeTickDown = 2; one second later,this code will be executed again(in the main ui thread) and then go on in each second.If there is some other code in doUpdateTimeout or updateTimeout,your main thread will be laggy.
Just change timerHandler.post(doUpdateTimeout); to updateTimeout()(call it directly and then execute it in the Timer thread,not the main ui thread).
int delay = 1000; // delay for 1 sec.
int period = 10000; // repeat every 10 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
displayData(); // display the data
}
}, delay, period);
And other:
while(needToDisplayData)
{
displayData(); // display the data
Thread.sleep(10000); // sleep for 10 seconds
}
Both of them doesn't work (application is force closed). What other options I can try?
You code is failed because you perform sleep in background thread but display data must be performed in UI thread.
You have to run displayData from runOnUiThread(Runnable) or define handler and send message to it.
for example:
(new Thread(new Runnable()
{
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(1000);
runOnUiThread(new Runnable() // start actions in UI thread
{
#Override
public void run()
{
displayData(); // this action have to be in UI thread
}
});
}
catch (InterruptedException e)
{
// ooops
}
}
})).start(); // the while thread will start in BG thread
Use onPostDelayed() accessed from any of your View or a Handler. You save memory by not creating a Timer or new Thread.
private final Handler mHandler = new Handler();
private final Runnable mUpdateUI = new Runnable() {
public void run() {
displayData();
mHandler.postDelayed(mUpdateUI, 1000); // 1 second
}
}
};
mHandler.post(mUpdateUI);
Try this :
#Override
public void run() {
TextView tv1 = (TextView) findViewById(R.id.tv);
while(true){
showTime(tv1);
try {
Thread.sleep(1000);
}catch (Exception e) {
tv1.setText(e.toString());
}
}
}
U can also try this
There is an another way also that you can use to update the UI on specific time interval. Above two options are correct but depends on the situation you can use alternate ways to update the UI on specific time interval.
First declare one global varialbe for Handler to update the UI control from Thread, like below
Handler mHandler = new Handler();
Now create one Thread and use while loop to periodically perform the task using the sleep method of the thread.
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
Thread.sleep(10000);
mHandler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Write your code here to update the UI.
}
});
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
There several mistakes you have done:
You should never invoke Thread.sleep() on the main thread (and you should never block it for a long time as well). Once main thread is blocked for more then 5 seconds, an ANR (application not responding) happens and it is force closed.
You should avoid using Timer in android. Try Handler instead. Good thing about handler is that it is created on the main thread -> can access Views (unlike Timer, which is executed on its own thread, which cannot access Views).
class MyActivity extends Activity {
private static final int DISPLAY_DATA = 1;
// this handler will receive a delayed message
private Handler mHandler = new Handler() {
#Override
void handleMessage(Message msg) {
if (msg.what == DISPLAY_DATA) displayData();
}
};
#Override
void onCreate(Bundle b) {
//this will post a message to the mHandler, which mHandler will get
//after 5 seconds
mHandler.postEmptyMessageDelayed(DISPLAY_DATA, 5000);
}
}
I came across this thread when i tried to get around the problem that you can't hide seconds in DigitalClock widget for Android. DigitalClock is deprecated now and the recommended widget to use now is TextClock. That don't work on old APIs tho... Therefore i had to write my own 24 hour clock. I don't know if this is a good implementation but it seems to work (and it is updated every second):
import java.util.Calendar;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
/**
* A 24 hour digital clock represented by a TextView
* that can be updated each second. Reads the current
* wall clock time.
*/
public class DigitalClock24h {
private TextView mClockTextView; // The textview representing the 24h clock
private boolean mShouldRun = false; // If the Runnable should keep on running
private final Handler mHandler = new Handler();
// This runnable will schedule itself to run at 1 second intervals
// if mShouldRun is set true.
private final Runnable mUpdateClock = new Runnable() {
public void run() {
if(mShouldRun) {
updateClockDisplay(); // Call the method to actually update the clock
mHandler.postDelayed(mUpdateClock, 1000); // 1 second
}
}
};
/**
* Creates a 24h Digital Clock given a TextView.
* #param clockTextView
*/
public DigitalClock24h(View clockTextView) {
mClockTextView = (TextView) clockTextView;
}
/**
* Start updating the clock every second.
* Don't forget to call stopUpdater() when you
* don't need to update the clock anymore.
*/
public void startUpdater() {
mShouldRun = true;
mHandler.post(mUpdateClock);
}
/**
* Stop updating the clock.
*/
public void stopUpdater() {
mShouldRun = false;
}
/**
* Update the textview associated with this
* digital clock.
*/
private void updateClockDisplay() {
Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR_OF_DAY); // 24 hour
int min = c.get(Calendar.MINUTE);
String sHour;
String sMin;
if(hour < 10) {
sHour = "0" + hour;
} else sHour = "" + hour;
if(min < 10) {
sMin = "0" + min;
} else sMin = "" + min;
mClockTextView.setText(sHour + ":" + sMin);
}
}
Thankyou biegleux for pointing me in the, i suppose, correct direction!