When somebody is doing some game they can do it like this: mainActivity which extends Activity and in this main activity there is a method e.g:
setContentView(BouncingBallView);
BouncingBallView extends View and there we have got methods: onDraw() invalidate() and these methods are use to do update and they are performing in all frames.
My problem is I would like to have some method like "onDraw-invalidate" which are update but in class Activity not in View.
I would like to know if there are some main loop, methods which are perform all the time some update()? I know that in Activity there is: onCreate(); onStart(); onRestart(); onResume(); onPause(); onStop(); and onDestroy(), but I can't see update? How would I do this?
Do you want periodic updates? Then a timer might be a way to go. Create an instance of a timer in your activity's onStart and schedule an update task with a desired delay as follows:
public class MyActivity extends Activity {
...
private Timer timer;
private BouncingBallView ballView;
...
#Override
public void onResume() {
timer = new Timer();
// This timer task will be executed every 1 sec.
timer.schedule(new TimerTask() {
#Override
public void run() {
ballView.update();
}
}, 0, 1000);
}
...
#Override
public void onSuspend() {
// Suspend the updates when the activity is inactive.
timer.cancel();
}
}
Note that timer tasks run in a separate thread, and in Android modifying UI elements in a different thread from the one they were created in may cause problems. If you run into these problems handlers (android.os.Handler) are helpful, and in Honeycomb there are better solutions for that but the Timer/Handler combination works well in older versions.
Related
Is there a way to take a picture two seconds after the Camera.takePicture method is invoked? For some reason, I do not want to use handler/timer to schedule the invocation of takePicture.
Precisely, I would like to use a different solution than the following one:
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
<here takePicture is invoked>
}
});
}
}, 2000);
You could use AlarmManager with a PendingIntent and handle taking the camera capture in your Activity.onNewIntent method, but it is a very confusing solution for what you are trying to solve (a much better use of AlarmManager is to schedule tasks so that they are performed even if the user exits your application). This solution also requires more code and is less precise/reliable and less efficient than using a Handler.
EDIT: You can also use a ScheduledThreadPoolExecutor along with a Runnable.
(Personal opinion following) If you are exploring the APIs available in Android for performing timed tasks, that is ok, but I wouldn't use AlarmManager to schedule timed tasks within an Activity that's already running.
If you just want to have the code a bit more organised, you can make an inner class that implements Runnable and schedule your action like this:
class MyCameraActivity extends Activity
{
class TakePictureTask implements Runnable
{
public void run()
{
MyCameraActivity.this.takePicture();
}
}
void scheduleCameraShot()
{
(new Handler(this.getMainLooper())).postDelayed(new TakePictureTask(), 2000);
}
}
I'm working on an app that synchronizes some graphic UI events with an audio track. Right now you need to press a button to set everything in motion, after onCreate exits. I'm trying to add functionality to make the audio/graphical interaction start 10 seconds after everything is laid out.
My first thought is, at the end of onCreate, to make the UI thread sleep for 10000 miliseconds using the solution here and then to call button.onClick(). That seems like really bad practice to me, though, and nothing came of trying it anyway. Is there a good way to implement this autostart feature?
Never ever put sleep/delay on UI-thread. Instead, use Handler and its postDelayed method to get it done inside onCreate, onStart or onResume of your Activity. For example:
#Override
protected void onResume() {
super.onResume();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//do whatever you want here
}
}, 10000L); //the runnable is executed on UI-thread after 10 seconds of delay
}
Handler handler=new Handler();
Runnable notification = new Runnable()
{
#Override
public void run()
{
//post your code............
}
};
handler.postDelayed(notification,10000);
Yes, putting the UI thread to sleep isnt a good idea.
Try this
private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
worker.schedule(task, 10, TimeUnit.SECONDS);
I'm updating my game using a Handler posting a delayed Runnable.
public class Example implements Runnable
{
Handler handler;
public Example()
{
handler = new Handler();
handler.postDelayed(this,10);
}
public void run()
{
handler.postDelayed(this,10);
}
}
Whenever I press the lock screen button and then resume the game, it runs much faster than it is supposed to. Every time I lock the screen and resume, it runs faster and faster. However, if I restart the activity or finish and then re-open the activity, it runs at normal speed again. Help please.
Thanks in advance.
What seems to be happening is every time you lock your screen and then resume it is making another Runnable on top of the Runnable you already have doubling your run thus making the thread go faster and faster everytime, you need to somehow pause your thread something like thread.sleep() or something similar when you lock your screen so when you resume you aren't recreating a new Runnable and instead just starting from where you left off in your thread.
If you are making a new Runnable in an onCreate method. It is going to get called anytime the phone is rotated, or when the phone resumes etc. and thus is why you are probably having this issue. The reason it doesn't happen after you finish() your activity or close your app is because when you restart the app, that Runnable is going to get created once, until you start locking the phone and resuming again etc.
you may also want to look at an inner class you can use to help handle your threads:
public class YourClass extends Activity {
public void yourUpdateMethod() {
runOnUiThread(new Runnable() {
public void run() {
new YourUpdateClass().execute(0, null, null);
}
});
}
private class YourUpdateClass extends AsyncTask<Integer, Void, Void> {
#Override
protected synchronized Void doInBackground(Integer... index) {
return null;
}
#Override
protected synchronized void onPostExecute(Void result) {
//your statements here
}
}
}
This might help handle threads that have to be paused/restarted/resumed or whatever a little better. More info here: http://developer.android.com/reference/android/os/AsyncTask.html
Dunno how it would work in a game though, didn't play around with that.
Good Luck, hope this helps.
I need my Android app to periodically fetch data from a server using AJAX calls, and update the UI accordingly (just a bunch of TextViews that need to be updated with setText()). Note that this involves 2 tasks:
Making an AJAX call, and updating the UI once I receive a response - I use a simple AsyncTask for this.
Doing the above repeatedly, at regular intervals.
I haven't figured out an elegant way to achieve Point 2 above. Currently, I am simply executing the task itself from OnPostExecute(). I read on this thread at SO that I need not worry about garbage collection as far as the AsyncTask objects are concerned.
But I'm still unsure as to how I set up a timer that will fire my AsyncTask after it expires. Any pointers will be appreciated. Here is my code:
public class MyActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AjaxRequestTask().execute(MY_REST_API_URL);
}
private void updateReadings(String newReadings) {
//Update the UI
}
class AjaxRequestTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... restApiUrl) {
//Do AJAX Request
}
#Override
protected void onPostExecute(String result) {
updateReadings(result);
/*Is there a more elegant way to achieve this than create a new AsyncTask object every 10 seconds? Also, How can I update the UI if I create a timer here? */
new AjaxRequestTask().execute(MY_REST_API_URL);
}
}
}
Thanks in advance
EDIT:
I tried posting an answer but couldn't do it since I don't have the reputation to answer within 8 hours.
Well, so I found a solution. I'm not convinced however.
protected void onPostExecute(String result) {
updateReadings(result);
// super.onPostExecute(result);
new Timer().schedule(
new TimerTask() {
#Override
public void run() {
new AjaxRequestTask().execute(MY_REST_API_URL);
}
},
TIMER_ONE_TIME_EXECUTION_DELAY
);
}
Are there any flip sides that I should be aware of when I use this? In particular, I am seeing lots of GCs happening in the LogCat. Also, I am wondering how an AsyncTask can be candidate for GC unless the onPostExecute() completes?
How can I "stop" the updates? One way I thought of was to make the very first AsyncTask instance as a member variable of the Activity. That way, I can invoke cancel(true) on it and hope that this will "stop" the tasks.
SOLUTION:
In case anyone is looking for something similar - none of the solutions I mentioned here work satisfactorily. They all suffer from OutOfMemory issues. I did not debug into the details of the OOM, but I suspect it could either be because of the recursion, or because of having HTTP-related objects as member variables in the AsyncTask rather than as members of the Activity (basically because of NOT reusing HTTP and other objects).
I discarded this approach for a different one - making my Ajax Calls endlessly in the doInBackground() of my AsyncTask; and updating the UI in onProgressUpdate(). That way I also avoid the overhead of maintaining too many threads or Handlers for updating the UI (remember UI can be updated in onProgressUpdate() ).
This approach also eliminates the need for Timers and TimerTasks, favoring the use of Thread.sleep() instead. This thread on SO has more details and a code snippet too.
Call postDelayed() on any View to schedule a hunk of code to be run on the main application thread after a certain delay. Do this in onPostExecute() of the AsyncTask to create and execute another AsyncTask.
You could use AlarmManager, as others have cited, but I would agree with you that it feels a bit like overkill for timing that occurs purely within an activity.
That being said, if the AJAX calls should be occurring regardless of whether the activity exists, definitely consider switching to AlarmManager and an IntentService.
I think the android way to do this is using AlarmManager. Or you can user a basic java Timer as well. I'd recommend AlarmManager.
Set it up to send some intent with a custom Action, and register a broadcastreceiver for it.
If the ajax calls are only executed in the activity you can just use a timer in the activity which starts the tasks.
Otherwise use a service which uses the AlarmManager and which connects to the gui via a broadcast.
The recommended way to do a repeated task, is via AlarmManager, as alluded to by Scythe. Basically it involves setting up a broadcast listener, and having AlarmManager fire off an intent to that listener at whatever interval you choose. You then would have your broadcast listener call out to the activity to run the AsyncTask. If you need a very tight timer (less than 5s calls I'd say), then you're better off using a Timer within a Service, and using AIDL to call back to the activity.
Instead of talking directly from the broadcast intent, you could also setup an IntentService which you can poke, and use AIDL to update the activity.
This is how I achieved it finally. Note that the AsyncTask cancel(true) method is useless in my scenario because of the recursion. I used what #CommonsWare suggested - used a flag to indicate whether any more tasks should be executed.
public class MyActivity extends Activity {
/*Flag which indicates whether the execution should be halted or not.*/
private boolean mCancelFlag = false;
private AjaxRequestTask mAjaxTask;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if(mAjaxTask == null){
mAjaxTask = new AjaxRequestTask();
}
mAjaxTask.execute(MY_REST_API_URL);
}
#Override
protected void onResume() {
super.onResume();
mCancelFlag = false; /*when we resume, we want the tasks to restart. Unset cancel flag*/
/* If the main task is Finished, create a new task and execute it.*/
if(mAjaxTask == null || mAjaxTask.getStatus().equals(AsyncTask.Status.FINISHED)){
new AjaxRequestTask().execute(TLS_REST_API_URL);
}
}
#Override
protected void onPause() {
mCancelFlag = true; /*We want the execution to stop on pause. Set the cancel flag to true*/
super.onPause();
}
#Override
protected void onDestroy() {
mCancelFlag = true;/*We want the execution to stop on destroy. Set the cancel flag to true*/
super.onDestroy();
}
private void updateReadings(String result) {
//Update the UI using the new readings.
}
class AjaxRequestTask extends AsyncTask<String, Integer, String> {
private AjaxRequestTask mChainAjaxRequest;
private Timer mTimer;
private TimerTask mTimerTask;
#Override
protected String doInBackground(String... restApiUrl) {
//Do AJAX call and get the response
return ajaxResponse;
}
#Override
protected void onPostExecute(String result) {
Log.d(TAG, "Updating readings");
updateReadings(result);
// super.onPostExecute(result);
if(mTimer == null){
mTimer = new Timer();
}
if(!mCancelFlag){/*Check if the task has been cancelled prior to creating a new TimerTask*/
if(mTimerTask == null){
mTimerTask = new TimerTask() {
#Override
public void run() {
if(!mCancelFlag){/*One additional level of checking*/
if(mChainAjaxRequest == null){
mChainAjaxRequest = new AjaxRequestTask();
}
mChainAjaxRequest.execute(MY_REST_API_URL);
}
}
};
}
mTimer.schedule(mTimerTask,TIMER_ONE_TIME_EXECUTION_DELAY);
}
}
}
}
I have an activity (MapActivity actually) that has a linearLayout with a mapView and a textView, for displaying current speed, among other things. The thing is that I would like the textView to be updated every 0.5 seconds, for example.
I know this can be done with a service (at least that is how I learnt to do it), but I was wondering if it is possible to do so using a Timer inside the MapActivity itself. I tried this approach:
onCreate{
...
updateTimer = new Timer();
updateTimer.scheduleAtFixedRate(doRefresh, 0, updateInterval);
}
private Timer updateTimer;
private TimerTask doRefresh = new TimerTask()
{
public void run()
{
updateData();
}
};
private void updateData()
{
//update the textView with the data
}
private int updateInterval = 500;
However, it gives me the following error:
04-10 22:24:56.529: ERROR/AndroidRuntime(9434): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Then, is it possible to do what I'm trying in an easy way, without using a service class?
Thank you and regards,
=)
Call postDelayed() on some widget, supplying a Runnable and 500 as the delay. The Runnable should do whatever work you want done, then call postDelayed() again with itself as the Runnable and 500 as the delay.
This avoids background threads and services, which are not needed for simple timing events in an activity.