A handler that runs every 5 minutes runs in duplicate - android

My handler will record the camera screen every 5 minutes
recently, I found handler runs in duplicate.
handler is before record the camera screen, create record file name.
if normal, 15:00:00.mp4 , 15:05:00.mp4, 15:10:00.mp4.
but current my state is 15:00:00.mp4, 15:02:15.mp4, 15:05:00.mp4, 15:07:15.mp4.
It seems that the same handler is duplicated and the 2 are executed.
so, I want if there is a handler already working, delete the old handler, execute new handler.
then, I think solve same handler duplicate problem. is right?
to sum it up,
1. Before doing handler.sendEmptyMessage, Is it possible to check if the same handler is working?.
if 1 is possible, How to delete a running handler and run only the new handler.
current my source.
private RecHandler mHandler = new RecHandler(this);
#Override
public void onCreate(Bundle savedInstanceState) {
...
mHandler.sendEmptyMessage(REQUEST_HANDLE_INIT_RECORD);
}
RecHandler.class
public class RecHandler extends Handler {
private final SoftReference<MainActivity> weak;
public RecHandler(MainActivity act) {
weak = new SoftReference<BlackEyeActivity>(act);
}
#Override
public void handleMessage(Message msg) {
MainActivity act = weak.get();
RecHandler mHandler = new RecHandler(act);
if (act != null) {
switch (msg.what) {
case REQUEST_HANDLE_INIT_RECORD:
initCapturing(); //init camera preview..
mHandler = new RecHandler(act);
mHandler.sendEmptyMessageDelayed(REQUEST_HANDLE_START_RECORD, 1000); //after 1 second, start REQUEST_HANDLE_START_RECORD.
this.removeMessages(REQUEST_HANDLE_HOLD_RECORD);
break;
case REQUEST_HANDLE_START_RECORD :
startRecording(); //start Recording.. record file 5 minute.
mHandler.sendEmptyMessageDelayed(REQUEST_HANDLE_HOLD_RECORD, 300000); //after 5 minute, start REQUEST_HANDLE_HOLD_RECORD.
this.removeMessages(REQUEST_HANDLE_INIT_RECORD);
break;
case REQUEST_HANDLE_HOLD_RECORD:
stopRecording();
mHandler.sendEmptyMessageDelayed(REQUEST_HANDLE_INIT_RECORD, 1000); //after 1 second, start REQUEST_HANDLE_INIT_RECORD.
this.removeMessages(REQUEST_HANDLE_START_RECORD);
break;
so, My handler if always record, repeat INIT(1 seconds) -> START (5 minute) -> HOLD(1 seconds)
if you know how to check if the same handler is working, and how to delete a running handler and run only the new handler. please advice for me.

Related

Android compare to a time to current time continuously

I am making an app which need to compare two date and time continuously.
I just saw some example which just compare once. I think I can use timer to repeat a method but it seem not very efficient. Anyone did this before?
Maybe you can use postDelayed like below.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
compareTime();
}
}, 5000);
replace 5000 with your own interval milliseconds.
It is easy, you can use handler; When the first time to check time send the normal message like this
mHandler.sendMessage(mHandler.obtainMessage(CHECK_TIME);
Afterwards sendDelayedMessage from inside the handler.
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case CHECK_TIME:
// Your compare time code here
// ....
// Send the delayed message to handler to check time again
mHandler.sendMessageDelayed(mHandler.obtainMessage(CHECK_TIME),
DELAY_CHECK_TIME_INTERVAL);
break;
}
}
}

How to return to main thread Android

I have a simple Activity with two buttons "On" and "Off". I want start changing color of background in cycle with button "On" and stop this with button "Off". Also I need to have red color by click on "Off" button. I have wrote simple programm and everything is fine, but I can't understand one thing. Why the last color not always red? If I use code in main threads cycle
Thread.sleep(100);
or
Thread.sleep(1000);
I always have red color, but if I set
Thread.sleep(10);
I have random last color. Why??
Thank you !!
I have this code:
public class MyActivity extends Activity {
final Handler myHandler = new Handler();
private int randColor;
final Runnable updateColor = new Runnable() {
public void run() {
final Random random = new Random();
randColor = Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255));
mRelativeLayout.setBackgroundColor(randColor);
}
};
private ColorChanger myThread;
class ColorChanger extends Thread {
private volatile boolean mIsStopped = false;
#Override
public void run() {
super.run();
do
{
if (!Thread.interrupted()) {
myHandler.post(updateColor);
}
else
{
return;
}
try{
Thread.sleep(100);
}catch(InterruptedException e){
return;
}
}
while(true);
}
public void stopThis() {
this.interrupt();
}
}
private RelativeLayout mRelativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
}
public void onflagClick(View view) {
myThread = new ColorChanger();
myThread.start();
}
public void onflagoffClick(View view) throws InterruptedException {
myThread.interrupt();
if(myThread.isAlive())
{
try {
myThread.join();
} catch(InterruptedException e){
}
}
else
{
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
}
I agree with the previous answer-ers, but propose a different solution.
First let me say that I recommend you stop using Runnables. In general posting a Runnable to a Handler is less efficient then sending a Message, although there are very rare exceptions to this rule.
Now, if we send Messages, what should we do? What we basically want to do is keep doing whatever we're doing until a condition is hit. A great way to do this is to write a Message Handler that receives a Message, does our work (setting the color), checks if we should keep going, and if so schedules a new Message in the future to do more work. Let's see how we might do this.
Assume the code below is inside an Activity.
private static final int MSG_UPDATE_COLOR = 1;
private static final int DELAY = 10; //10 millis
private final Object mLock = new Object();
private boolean mContinue = true;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_COLOR:
synchronized (mLock) {
if (mContinue) {
setColor(Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255)));
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_COLOR, DELAY);
} else {
setColor(Color.RED);
}
}
break;
}
}
}
}
public void onflagClick(View view) {
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
public void onflagoffClick(View view) throws InterruptedException {
synchronized (mLock) {
mContinue = false;
}
// cancel any pending update
mHandler.removeMessages(MSG_UPDATE_COLOR);
// schedule an immediate update
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
Okay, so, what is happening here. We've created a Handler that will do all the color updates. We kick that off when our start event happens. Then the Message schedules a new message (and therefore color update) in ten milliseconds. When the stop event happens we reset a flag that the message handler reads to determine if a new update should be scheduled. We then unschedule all update messages because it might be scheduled for several milliseconds in the future and instead send an immediate message that does the final color update.
For bonus points we eliminate the use of a second thread which saves resources. Looking carefully I've used synchronized blocks, but these are actually unnecessary because everything is happening on the main thread. I included these just in case someone was changing mContinue from a background thread. Another great point of this strategy is that all color updates happen in one place in the code so it is easier to understand.
When you post to Handler, it will run your Runnable at some given time in the future. It is not immediate. It also works in a queue so the more times you post to Handler you are going to stack up the commands that will all get executed in order eventually.
You're facing a race condition because with Thread.sleep(10), the program is most likely stacking up a lot of Runnables to execute. They will run regardless of whether or not your Thread is running because they've been queued up to run on the main thread. Thread.sleep(100) or Thread.sleep(1000) doesn't have this issue simply because you're giving the system enough time to execute all color commands. However, it is still possible to have this issue if you pressed the off button at just the right time.
As DeeV told you, Handler sends Runnables to a Looper that is basically a Thread looping inside processing messages or runnables in each loop. You are queuing messaged to the main Looper and then you are sleeping your worker Thread. Its possible that you are sending for example 2 runnables in a row between each loop of your worker thread, but the main looper has only executed the last one so you cannot see each color as you want.
If you want a simple solution to make it work, you can use an Object or a CountDownLatch to synchronize your main Looperwith your worker Thread.
For example: Just before you will sleep your worker Thread you can do the next thing myLockObject.wait()
Then, you should change post(Runnable) to sendMessage(Message). In handleMessage from your Handler you can do myLockObject.notify() (Keep in mind that handleMessage will be executed inside the Looper that you have created your Handler or you can specify any Looper you want explicity). To obtain a new Message you should use myHandler.obtainMessage().
This will make your worker Thread wait your main Looperto process your runnable just before you wait X time until you post next color. Obviously you should create your new Object as a field of your Activity for example:
private myLockObject = new Object()

Stopping and restarting timer

I'm using a pageslider and timer for it. I wrote a timer method for this pageslider such:
public void setTimerToSlider() {
sliderTimer = new Timer();
sliderHandler = new Handler();
sliderTimerTask = new TimerTask() {
#Override
public void run() {
sliderHandler.post(new Runnable() {
#Override
public void run() {
if (viewPager.getCurrentItem()<images.length-1) {
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
} else {
viewPager.setCurrentItem(0);
}
}
});
}
};
sliderTimer.scheduleAtFixedRate(sliderTimerTask, 0, sliderTimeOut*1000);
}
When user slides it manually, timer goes on. So, for example, if 1 second remains, when user slides, it goes to next in 1 second.
My aim is that when user slides it manually, it resets the remaining time and starts the time out from 0.
Are you asking how to cancel the current timer and start a new one each time there's user input?
You allocated a Handler. Use that for your timing instead of a Timer. Handlers are more useful on Android, e.g. the Activity lifecycle knows what to do with them. They might use less battery power, too.
When a new user input event arrives, call sliderHandler.removeMessages(MSG_PAGESLIDER) to cancel any previous timers, then call sliderHandler.sendEmptyMessageDelayed(MSG_PAGESLIDER, 1000), where:
static final int MSG_PAGESLIDER = 1;
class UpdateHandler extends Handler {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_PAGESLIDER:
// react to the timeout; schedule another message if desired
break;
}
}
}
UpdateHandler sliderHandler = new UpdateHandler();
aaaaaannnnnnnnd your question is? ( not my downvote, btw, but we tend to follow a question-answer format )
=]
Consider referencing the Calendar, it goes down to the millisecond and is not as susceptible to delays f'ing up your game
Calendar calendar = Calendar.getInstance();
http://developer.android.com/reference/java/util/Calendar.html
gl hf

Android create e timer that goes also in background

i need to create a timer (with start and stop function), that continue to work also in background, because:
- my app have 2 activity switchable via intent, so if i return to activity 1 the timer must continue to work, and if i return to activity 2 (that of the timer) the "textview" must update the timer that is continuing to work
- if i put the app in background, the timer must continue to work.
how can i do this?
i've found this, but i'm not sure that it can do what i need: http://examples.javacodegeeks.com/android/core/os/handler/android-timer-example/
Thanks!
For making the timer working in background, use Asynctask. Then if necessary, you can switch activities in the foreground from doinBackground function of Asynctask using RunOnUiThread method (or separate thread if you so desire).
Standard Java way to use timers via java.util.Timer and java.util.TimerTask works fine in Android, but you should be aware that this method creates a new thread.
You may consider using the very convenient Handler class (android.os.Handler) and send messages to the handler via sendMessageAtTime(android.os.Message, long) or sendMessageDelayed(android.os.Message, long). Once you receive a message, you can run desired tasks. Second option would be to create a Runnable object and schedule it via Handler's functions postAtTime(java.lang.Runnable, long) or postDelayed(java.lang.Runnable, long).
For a repeating task:
new Timer().scheduleAtFixedRate(task, after, interval);
For a single run of a task:
new Timer().schedule(task, after);
task being the method to be executed
after the time to initial execution
(interval the time for repeating the execution)
Handler:
private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
Private Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
}
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
Message:
private final int EVENT1 = 1;
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Event1:
Toast.makeText(MyActivity.this, "Event 1", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(MyActivity.this, "Unhandled", Toast.LENGTH_SHORT).show();
break;
}
}
};
...
Message msg = handler.obtainMessage(EVENT1);
handler.sendMessageAtTime(msg, System.currentTimeMillis()+interval);
handler.sendMessageDelayed(msg, interval);

How to cancel a handler before time in Android code?

I create 1 minute delayed timer to shutdown service if it's not completed. Looks like this:
private Handler timeoutHandler = new Handler();
inside onCreate()
timeoutHandler.postDelayed(new Runnable()
{
public void run()
{
Log.d(LOG_TAG, "timeoutHandler:run");
DBLog.InsertMessage(getApplicationContext(), "Unable to get fix in 1 minute");
finalizeService();
}
}, 60 * 1000);
If I get job accomplished before this 1 minute - I would like to get this delayed thing cancelled but not sure how.
You can't really do it with an anonymous Runnable. How about saving the Runnable to a named variable?
Runnable finalizer = new Runnable()
{
public void run()
{
Log.d(LOG_TAG, "timeoutHandler:run");
DBLog.InsertMessage(getApplicationContext(), "Unable to get fix in 1 minute");
finalizeService();
}
};
timeoutHandler.postDelayed(finalizer, 60 * 1000);
...
// Cancel the runnable
timeoutHandler.removeCallbacks(finalizer);
If you don't want to keep a reference of the runnable, you could simply call:
timeoutHandler.removeCallbacksAndMessages(null);
The official documentation says:
... If token is null, all callbacks and messages will be removed.
You might want to replace use of postDelayed with use of sendMessageDelayed like so:
private Handler timeoutHandler = new Handler(){
#Override
public void handleMessage(Message msg)
{
switch (msg.what){
case 1:
((Runnable)msg.obj).run();
break;
}
}
};
Then post a Message:
Message m = Message.obtain();
m.what = 1;
m.obj = new Runnable(){
public void run()
{
Log.d(LOG_TAG, "timeoutHandler:run");
DBLog.InsertMessage(getApplicationContext(), "Unable to get fix in 1 minute");
finalizeService();
}
};
timeoutHandler.sendMessageDelayed(m, 60 * 1000);
and then cancel:
timeoutHandler.removeMessages(1);
No tracking of the runnable necessary.
If I get job accomplished before this 1 minute - I would like to get this delayed thing cancelled but not sure how.
Use Handler.removeCallbacks(yourRunnable).

Categories

Resources