idle timeout for android app activity - android

I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!

Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.

Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation

You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.

Related

Down sides of Async Task If Any

I know you are using it quite well with your Non-UI codes in AsnycTask but I am just wondering if there is any kind of problem while using AsyntTask? I am not having any code which produce the problem. But I am just curious to know Any bad experience if you have with AsnycTask and would like to share it.
Memory Leak :
Even though activity is destroyed, AsyncTask holds the Activity's reference since it has to update UI with the callback methods.
cancelling AsyncTask :
cancelling AsyncTask using cancel() API will not make sure that task will stop immediately.
Data lose :
When screen orientation is done. Activity is destroyed and recreated, hence AsysncTask will hold invalid reference of activity and will trouble in updating UI.
Concurrent AsyncTasks: Open Asynctask.java go to line number 199, it shows you can create only 128 concurrent tasks
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
Rotation: When Activity is restarted, your AsyncTask’s reference to the Activity is no longer valid, so onPostExecute() will have no effect.
Cancelling AsyncTasks: If you AsyncTask.cancel() it does not cancel your AsyncTask. It’s up to you to check whether the AsyncTask has been canceled or not.
Lifecycle: AsyncTask is not linked with Activity or Fragment, so you have to manage the cancellation of AsyncTask.
There are some workarounds to solve above issues for more details have a look at The Hidden Pitfalls of AsyncTask
I just want to share the information that if you are using Asynctask, it will keep on doing its work even of the activity does not exist.
So in case you have asynctask which starts in onCreate() of the activity, and you rotate the device. At each rotation, a new activity is created with a new instance of Asysntask. So many requests will be send over the network for same task.In this way, a lot of memory will be consumed which effects the app performance resulting in crashing it. So to deal with it Loaders(Asynctask Loaders) are used.
For more info check the video:
Loaders

Android timer notification across application activities

I have an application with several activities, and I have a timer I start in the first activity that is presented. The problem is this:
How can I get a reference to the current activity when the timer goes off when the activity I'm currently may not be the same as the one I started the timer.
What I actually want is to have a timer traverse all my actives, show an alert dialog when it expires and the do some stuff. But because of the way android works this seems to be impossible. Does anyone has an alternative?
I've already tried:
Using an async task to access the ui thread, doesn'nt work if it is not created in the main ui thread.
Can't use a Handler, my timer is in another class
What other choice do I have?
EDIT:
I can´t change any of the activities code, the timer should be decoupled enough to function when someone plugs it in the project.
Getting an instance of the current activity from the timer worker thread should work, since it would let me run stuff in the ui thread.
Implement your timer as a singleton.
Then, implement an observer pattern:
Create an interface (maybe called AlertListener) that is implemented by each Activity you want to be alerted. This interface should have a method, something like onTimerExpired(). This method should do whatever needs to be done to the activity when the timer expires.
In your timer class, also maintain a reference to the current AlertListener and a method, named something like "setCurrentActivity(AlertListener currentActivity)".
In onResume or some other method of each activity, call MyTimer.setCurrentActivity(this).
When the timer goes off, call currentActivity.onTimerExpired().

What is the common practice to handle relation between Activity and Thread

I have the following situation
I spawn a long running user thread (Thread) from an Activity.
I press soft back button. So, the Activity was destroyed.
I launch the same Activity again. Note, the previous launched Thread is still running.
In order for me to prevent the Activity from launching another same Thread while the previous Thread is still running, here is what I am doing
After I launch the Thread, I will store it into a static variable. So, next time when I try to launch a same thread, I will check against the liveness of previous thread through the static variable. Is this a good practice? What is the best practice to overcome this?
Note, the user thread is holding reference to the Activity which launched it. However, the Activity might destroyed when user press on soft back button. So, when I launch the new Activity again, the thread is not aware of that, and it is still referring to old Activity. So, when user thread try to access any members of the old Activity, crashes will happen as the Activity already being destroyed. What is the best practice to overcome this?
The best way to overcome this is to use an AsyncTask instead. If the Activity is destroyed while the task is executing, the AsyncTask (and its underlying Thread that is performing the operation) will continue its execution until doInBackground() has completed. If the Activity is null by the time onPostExecute is called, you won't run into any NullPointerExceptions for the reasons stated in this blog post.
If you want to immediately cancel the task if the user "backs out" of the Activity, you can call mTask.cancel() on your AsyncTask in your Activity's onDestroy method.
If you don't want to immediately cancel the task if the user "backs out" of the Activity, then your long-term operation doesn't sound like it is specific to any Activity instance. In this situation, it is often advised to use a Service instead.

Android Screen Rotation firing multiple AsyncTask Threads

From the Activity, I am creating a Handler to fire off my AsyncTask every 45 seconds in order to refresh the content of my ListView's DataAdapter. The AsyncTask works great and keeps the user informed on the progress through ProgressUpdates and Toast messages.
Since the thread's doInBackground is fire and forget and not re-usable, I am having to create a new instance of the AsyncTask from my Hander that is firing off every 45 seconds. The problem is when the screen is rotated and and then I get concurrent messages going off because the Hander was recreated and created a new instance of the AsyncTask, so the friendly user progress through ProgressUpdates and Toast messages is overwhelming and makes utilizing the ListView difficult.
And please don't suggest this as a solution: android:screenOrientation="portrait" is not an option.
For something that has to run so frequently, should I just be using a custom Thread and not the AsyncTask class? ToDo: Not shown, I have to update the Adapter later from the Sensor's onSensorChanged event to update bearings on for each location in the ListView, I was going to run that on a separate AsyncTask class because I don't need to notify the user everytime the device bearing has changed.
Since the AsyncThread cannot be reused, am I doing this all wrong? In short, what is the best way to have the Activity refresh the ListView and keeping off the UI thread when doing so?
The problem is when the screen is rotated and and then I get concurrent messages going off because the Hander was recreated and created a new instance of the AsyncTask.
Reason quoting from API Activity - Configuration Changes:
Unless you specify otherwise, a configuration change (such as a change in screen orientation, language, input devices, etc) will cause your current activity to be destroyed, going through the normal activity lifecycle process of onPause(), onStop(), and onDestroy() as appropriate.
So every object has a activity-scope life cycle (i.e. Handler, AsyncTask and etc. defined within your activity class) is suffered by this activity recreation. However, you can bypass this activity recreation, as stated in the later paragraph of Activity - Configuration Changes section:
In some special cases, you may want to bypass restarting of your activity based on one or more types of configuration changes. This is done with the android:configChanges attribute in its manifest. For any types of configuration changes you say that you handle there, you will receive a call to your current activity's onConfigurationChanged(Configuration) method instead of being restarted. If a configuration change involves any that you do not handle, however, the activity will still be restarted and onConfigurationChanged(Configuration) will not be called.
Not related to topic, but as a good practice, you should always destroy used object (Handler, AsyncTask and etc.) properly when activity is about to finish (i.e. in onDestroy() method).
For something that has to run so frequently, should I just be using a custom Thread and not the AsyncTask class?
AsyncTask is pretty handy but not suit for periodic task, I would use ScheduledExecutorService or TimerTask in this case, check out my answer here for sample code.
Can you please post a bit of your code ? It may be useful to understand where your problem is.
As york has pointed it out, you should probably use TimerTask. It seems that it suit better with what you are trying to do.
If it is the creation of a new instance of the Handler that create the probleme you can try something like this :
private Handler mHandler = null;
#Override
public void onCreate(Bundle _savedInstanceState) {
super.onCreate(_savedInstanceState);
setContentView(R.layout.my_layout);
if (mHandler == null) {
// TODO create your handler here
}
}
EDIT :
You can test _savedInstanceState == null too.
_savedInstanceState is used to save the state of the activity so turning the phone shouldn't be a problem anymore.
However, if you leave the activity and then go back to it, it will create a new handler (except if you instanciate it as a static variable).

Message Handling, unexpected behavior with worker threads

I'm taking a stab at a large program with a background Service and I'm implementing a (rather poorly thought out) Message handling procedure using basic Handler objects. The application has a main menu with buttons which start 6 different activities.
Problem is this: if i start a worker thread which kicks off a query to the database and retrieves some data, and I close the Activity that started the aforementioned worker thread, the Handler in the Activity still tries to run and show a dialog, even though the Activity that created it is now finished (or not in focus). How can I tell whether the current Activity is in focus before committing any (UI) changes?
I ended up solving the issue by simply putting the 'showDialog()' call in a try statement, but i'd like a more sophisticated solution, as this just seems like the wrong way to do things.
Use sendBroadcast(), with the Activity registering a BroadcastReceiver for the broadcast via registerReceiver() in onResume() and unregistering it in onPause(). Then, it will only process the event if it is in the foreground.
Put some flag in onPause() method of activity that starts the thread to indicate that it is not foreground anymore. In onStart() reverse the flag.
When it is a time to display dialog, check this flag and only show dialog if activity is running.

Categories

Resources