Internal AsyncTask class to poll URL periodically - android

Problem:
What I am trying to do is have an AsyncTask poll a URL in the background periodically (every 5 seconds or so), and if specific data is received, disable an element on the activity. I have tried creating a separate class and using onPostExecute to run the method from the activity class to disable an ImageView, but I run into issues. I cannot call that method from the other class unless I make it static, and if I do declare it static, I cannot access the ImageView using findViewById.
Current status:
I have a TimerTask running my RetrieveColorTask that extends AsyncTask periodically every 5 seconds. But this causes exceptions as it tries to execute the same thread multiple times.
Timer timer = new Timer();
final RetrieveColorTask task = new RetrieveColorTask();
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, true);
AsyncTask.Status status = task.getStatus();
TimerTask doTask = new TimerTask() {
#Override
public void run() {
if(status.compareTo(AsyncTask.Status.FINISHED) == 0)
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, true);
}
};
timer.schedule(doTask, 5000, 5000);
Another method I tried was to create a new RetrieveColorTask in the TimerTask but then I don't know if the old thread has finished running yet, and ends up creating multiple AsyncTasks, most of them in the WAIT state. The most progress I have had is with this code:
Timer timer = new Timer();
final RetrieveColorTask[] task = new RetrieveColorTask[1];
final AsyncTask.Status[] status = new AsyncTask.Status[1];
final boolean[] isRun = {false};
TimerTask doTask = new TimerTask() {
#Override
public void run() {
if(task[0] == null) {
task[0] = new RetrieveColorTask();
status[0] = task[0].getStatus();
task[0].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, true);
} else {
if(status[0].compareTo(AsyncTask.Status.FINISHED) == 0) {
task[0] = new RetrieveColorTask();
task[0].executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, true);
}
}
}
};
timer.schedule(doTask, 5000, 5000);
But once the task executes the first time, it stays in PENDING state after that, so it is only run once.
I am fairly new to Android programming so I would appreciate any advice

Put the line
status[0] = task[0].getStatus();
at the beginning of the run()-method so that it updates the local status variable every time the method is executed by the TimerTask, because right now you are storing the status of the task when it is first created, but you don't update it when the method is ran again after 5 seconds and task[0] is not null anymore.
Also, I would suggest that you to create a regular variable to put the task and status in just to make it cleaner, instead of using arrays because you are initializing them with only one element anyways, so in other words declare the task and the status variables like this instead:
RetrieveColorTask task = null;
RetrieveColorTask.Status status = null;
And also, personally I would do the status check like this
if(status == RetrieveColorTask.Status.FINISHED) ...
instead of using the compareTo() methods, because you never make use of the 1 or -1 values that it could also possibly return.
Hope this helps!

Related

Call ExectuorService with time interval - android

i used a custom thread to fetch data in the background every 1 second by making a thread goes to sleep, but my App crashes and throws exception OutOfMemoryError. Now i read a documentation in android developer and i understand that using custom thread is bad practice as it is difficult to manage the memory consistency. but finally i found ExecutorService very interesting when we need to do some tasks on background So, i decided to use it.
As You know the ExecutorService is like below:
public void executeTask()
{
ExecutorService executroService = new Executor.newSingleThreadExecutor();
executroService.execute(new Runnable()
{
#Override
publi void run()
{
// now execute the server request
}
});
}
Now how can i achive calling to executorService every 1 second untill the user goes to onpause() state or untill the user shifts from the current activity to another activity? if i use a custom thread to call that service, the App goes to crash. so how can i achive that ?
What you need is a ScheduledExecutorService
It can schedule commands to run after a given delay,
or to execute periodically.
Here is a code that implements this
import static java.util.concurrent.TimeUnit.*;
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
Runnable beeper = () -> System.out.println("beep");
ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
Runnable canceller = () -> beeperHandle.cancel(false);
scheduler.schedule(canceller, 1, HOURS);
}
}

Make a call to server always running in background

I want my app to make a call to server always in background checking for any updates , I am new to android and not sure how to perform this to start with. I just want a single call always running in background. Please guide me with this to start with.
You can use Async Task for that. In your doInBackground() method, call your service providing some timespan.
Snippet to add timestamp:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
new AddStringTask().execute();
} }, 0, 5000);

Start a Service to get data from server after specified time Interval

I have a requirement to get data from server by sending a call after specified interval like 5 minutes. So app would keep checking for new data after 5 minutes. It is just like gmail or facebook. Which automatically get new feeds or emails after some time and show in list. I am using service for this like following:
public class MessagesLoaderService extends Service {
// constant
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
//********************************************************************************************************************************/
#Override
public IBinder onBind(Intent intent) {
return null;
}
//********************************************************************************************************************************/
#Override
public void onCreate() {
// cancel if already existed
if (mTimer != null)
{
mTimer.cancel();
}
else
{
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new MessageLoaderTask(), 0, Commons.TIME_INTERVAL_REFRESH_MESSAGES);
}
//********************************************************************************************************************************/
class MessageLoaderTask extends TimerTask
{
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable()
{
#Override
public void run() {
//Get Data from Server and store in local db
}
});
}
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Utils.showToast_msg(getApplicationContext(), "Service Destroyed");
}
//********************************************************************************************************************************/
}
//////////////////////////////////////////////////////////////////
Starting service from main activity MainActivity:
startService(new Intent(this, MessagesLoaderService.class));
I want service to run (send calls after 5 minutes) only when the app is running or in foreground/background. But the problem is that it keeps running even if I exit from the application. I want service to stop when Application is closed. Any solution for this?
Shouldn't you stop your timer in "OnDestroy" with mTimer.cancel() if you want it to stop ?
This method works when you enter the activity which actually queries the server. Call the method in onCreate. If value returned is true, then fetch data from server, if false, do whatever is in youf flow.
This Example below uses Singleton class. The current system time, plus five minutes is stored in singleton class variable, while local variable stores the current time. If current time exceeds the time of Singleton variable, then true is returned and it is time to call server.
SingletonClass app;
app = (SingletonClass ) getApplication();
public boolean serverQueryFrequency() {
boolean isTimeElapsed;
Calendar cal = Calendar.getInstance();
long time = cal.getTimeInMillis();
// If No Time is set, only then Set the Current time + 10 into
// application variable. This should fire only once, until 10 minutes
// have passed
if (app.getServerCallTime() == 0) {
Calendar cal2 = Calendar.getInstance();
// updating calendar to get current time + 10
cal2.add(Calendar.MINUTE, 5);
long timeTen = cal2.getTimeInMillis();
app.setServerCallTime(timeTen);
// returning true, to enable server check
return true;
}
// Log.v("******", "Current : " + time);
// Log.v("******", "App Time : " + app.getServerCallTime());
// Comparing current time with SeverCalltime which is set 10 minutes
// ahead. Code below fires conditionally as stated
if (time == app.getServerCallTime() || time > app.getServerCallTime()) {
isTimeElapsed = true;
// Once true fired from here, reset serverCallTime
app.setServerCallTime(0);
} else {
// 5 minutes have not passed
isTimeElapsed = false;
}
// returning the related value
return isTimeElapsed;
}
you can stop service by using this line
stopService(new Intent(this, MessagesLoaderService.class));
so your service get stopped
you need to identify in your app from where your exiting the app at that point you need to call above code also OS automatically kill the service in certain circumstances like low battery and so on but this is not good solution so you can stop it by above line in your exit point of application
I have learned when the app is closed the service get closed also because they are in a one thread, so the service should be on another thread in order fot it not to be closed, look into that and look into keeping the service alive with alarm manager here an example http://www.vogella.com/articles/AndroidServices/article.html this way your service won't be shown in notification.
lastly, after all the research I've done I'm coming to realize that the best use of a long running service is start foreground(); because it is made for that and the system actually deals with your service well.
when the user presses back button on the first page of your app..means they want out.
override the onbackpressed and put the stopService call there.
else..
use an exit button..give it an onclick and inside it put the stopService there

Android TimerTask crashes when called twice

I'm calling my TimerTask (m_timer) upon a button click:
m_timer.schedule(m_progressUpdater, 0, 500);
Which kicks off my run method:
#Override
public void run() {
//do some stuff
progressBar.setProgress(currentProgress);
if (progress >= 100) {
handler.post(new Runnable() {
#Override
public void run() {
CompleteTask();
}
});
}
}
I can call this once and it works perfectly. When I call it again, my app stops responding. I'm thinking that I need to cancel the task in my CompleteTask() method, but I've tried cancelling both the TimerTask and the Timer, and it still crashes. Anyone know what the problem might be?
Have you tried creating new TimerTask instance for the second call? And by the way, don't cancel the timer otherwise it will cancel all of its task. And what did the log say?
When you reschedule a Timer, it throws:
java.lang.IllegalStateException: TimerTask is scheduled already
It seems that you can only use a timer for once.
In order to reschedule a Timer, you need to simply create a new instance of it, each time. like the following:
// if you have already started a TimerTask,
// you must(?) terminate the timer before rescheduling it again.
if(m_timer != null)
m_timer.cancel();
m_timer = new Timer();
m_progressUpdater = new myTimerTask();
m_timer.schedule(m_progressUpdater, 0, 500);

How to display timer in activity?

I need to display a time duration on a few of my Activities within the application. The timer starts when one of the Activity starts.
Should I use service for the timer ?
Is this the best way ?
Or should I start thread from one of the Activity ?
I think in the use case you're describing it would be best to store time stamps (see Data Storage) and calculate the deltas for GUI use. If you need to display a real-time clock in one of your activities you can create a separate thread in that activity just to update the clock.
Well, depending on how much interface work you need to display your progress, I would start a thread within the activity and then create a timer that checks the status of the thread progress and updates the interface as needed. Services are good for background tasks that don't require a lot of interface notification/updates.
Here's an example from a project I'm currently working on (UpdateListRunnable just calls "notifyDataSetChanged()" on my list adapter. I do it multiple times in the code so I encapsulated it in a class. Also, updateHandler is just a regular Handler instance):
#Override
public void run() {
Timer updateProgressTimer = null;
UpdateItem currentItem = null;
for(int i = 0; i < items.size(); i++) {
currentItemIndex = i;
currentItem = items.get(i);
if (currentItem.isSelected() == true) {
updateProgressTimer = new Timer();
updateProgressTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
updateHandler.post(new UpdateListRunnable());
}
}, 0, 2000); // check every 2 seconds
lookupDb.downloadUpdate(currentItem);
currentItem.setUpToDate(true);
currentItem.setStatusCode(UpdateItem.UP_TO_DATE);
currentItem.setProgress(0);
updateProgressTimer.cancel();
updateHandler.post(new UpdateListRunnable());
} // end if its the database we are hosting on our internal server
} // end for loop through update items
currentItemIndex = -1;
} // end updateThread run

Categories

Resources