I want to check unread messages after 30 seconds of previous check, means when the first check (AsyncTask) is complete and I have the result then I want to wait 30 seconds, then I want to check for unread messages again and so on. Here is my code:
TimerTask timerTask = new CheckUnreadMessages(menuItem);
Timer timer = new Timer();
timer.schedule(timerTask, Constants.CHECK_UNREAD_COUNT_INTERVAL);
Here is my TimerTask:
class CheckUnreadMessages extends TimerTask{
MenuItem menuItem;
public CheckUnreadMessages(MenuItem menuItem) {
this.menuItem = menuItem;
}
#Override
public void run() {
Log.i("PrivateHome", "Checking for unread message...");
new CheckUnreadMessagesTask(menuItem, PrivateHome.this).execute(LocalDBSP.init().getID(PrivateHome.this));
}
}
Here goes my AsyncTask:
public class CheckUnreadMessagesTask extends AsyncTask <String, String, Boolean> {
Activity activity;
JSONObject result;
MenuItem menuItem;
public CheckUnreadMessagesTask(MenuItem menuItem, Activity activity){
this.menuItem = menuItem;
this.activity = activity;
}
#Override
protected Boolean doInBackground(String... params) {
try {
//now update to server
result = getResponse(URLManager.getUnreadCount(params[0]));
return JSONHelper.isResultOK(result);
}catch (Exception e){
e.printStackTrace();
}
return false;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean resultOK) {
super.onPostExecute(resultOK);
if(resultOK){
try {
String count = result.getString(JSONKeys.RESULT);
menuItem.setTitle(Constants.NAV_SEE_MESSAGES_TITLE+" ("+count+")");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
But it's being executed for the first time only, it's not repeating.
Dont use a AsyncTask to do this, they have a lot of problems with activity lifecycle.
You should use a periodic service or use the AlarmManager. Even a Java Thread with a while true with a sleep of 30 seconds is more safe than an async task.
Basically you are not re-scheduling the CheckUnreadMessages, so it gets executed only once, and therefore it triggers the CheckUnreadMessagesTask only once.
One solution is to use timer.scheduleAtFixedRate() instead, but this has a fixed rate and may not be what you want (often it is, though).
If you want to have the next check running 30s after the last task executed, you need to do rescheduling in CheckUnreadMessagesTask instead:
#Override
protected void onPostExecute(Boolean resultOK) {
super.onPostExecute(resultOK);
TimerTask timerTask = new CheckUnreadMessages(menuItem);
timer.schedule(timerTask, Constants.CHECK_UNREAD_COUNT_INTERVAL);
// ...
}
You'll need to pass a reference to the timer to the tasks, though. I'd avoid re-creating a new timer every time, but you could do that.
Additionally, I find the name confusing, since both look similar, at least name CheckUnreadMessages as CheckUnreadMessagesTimerTask so that it is more obvious which is which.
Related
I want to set network status in TextView, which I want to repetitively call method and set in background, so I used AsyncTask class with infinite loop
class setNetworkText extends AsyncTask
{
#Override
protected Object doInBackground(Object[] params) {
for(;;)
{
if(isNetworkConnected()) //check internet connection and if found it return true
setOnline(); // it set my TextView text to Online
else
setOffline(); // it set my TextView text to Offline
Thread.sleep(2000);
}
return null;
}
}
but it is not working, it stops my application.
Android will (in most versions) only execute one AsyncTask at a time - so if you keep blocking in doInBackground of one AsyncTask, no other AsyncTasks will run, thus blocking your application.
Take a look at using Handler.postDelayed or using a TimerTask. They are more suited for repeating actions.
You can not use AsyncTask to do that. You should use Handler to schedule a task periodically.
// Create the Handler
Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnableTask = new Runnable() {
#Override
public void run() {
if(isNetworkConnected())
setOnline();
else
setOffline();
}
};
// Call on main thread (for example, inside onResume())
#Override
protected void onResume() {
super.onResume();
handler.postDelayed(runnableTask, 2000);
}
// Remember to unregister it onPause()
#Override
protected void onPause() {
super.onPause();
handler.removeCallbacks(runnableTask);
}
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
//check something on time interval here 1 second
}
public void onFinish() {
//when your task done here 3 second is time to end
}
}.start();
explanation
CountDownTimer(long millisInFuture, long countDownInterval)
millisInfuture will be how long you want to run the task and countDownInterval is the interval in your case it is 2 seconds
For my app I want to disable/change a specific button that is pressed.
I have an onclick method called btnClicked which simplified looks like this:
Public class MainActivity extends Activity{
Button myBytton;
#Override
protected void onCreate(Bundle savedInstanceState) {
myBytton = (Button)findViewById(R.id.buttonCall);
}
public void btnClicked(View view)
{
myBytton.setText("loading");
myBytton.setEnabled(false);
myBytton.setClickable(false);
// Do a call to an external api
callApi();
}
public void callApi(){
// run querys
if(succesullyCalledApi){
vibrator.vibrate(500);
// I tried commenting out the below part,
// it is than visible that the phone vibrates before it
// has changed the text (atleast a quarter of a second).
myBytton.setText("search");
myBytton.setEnabled(true);
myBytton.setClickable(true);
}
}
}
In the callApi method is a vibrate method which vibrates after the function gets a result.
Also if there is a result in the callApi myButton will be enabled and the text changed to search.
What happens is the following:
I click on the button, the phone vibrates first and afterwards it changes its text.
my question.
Why did callApi / vibrate run before myBytton.setText ?
what NigelK said is true.
When you arrive in the btnClicked method all the instructions are made on the UI thread. Therefore when you ask the System to vibrate, it will be blocked for XX time depending on the time you passed to the method vibrator.vibrate(XX);.
In order to avoid this "freeze" you need to make the vibration on another Thread.
Here is what it will look like :
Public class MainActivity extends Activity
{
Button myBytton;
#Override
protected void onCreate(Bundle savedInstanceState)
{
myBytton = (Button)findViewById(R.id.buttonCall);
}
public void btnClicked(View view)
{
myBytton.setText("loading");
myBytton.setEnabled(false);
myBytton.setClickable(false);
// Do a call to an external api
callApi();
}
public void callApi()
{
// run querys
if(succesullyCalledApi)
{
// here you create and run the Thread.
// put anything you want to do inside the run method
new Thread(
new Runnable()
{
public void run()
{
// here you start the vibration
vibrator.vibrate(500);
}
}
).start();
// I tried commenting out the below part,
// it is than visible that the phone vibrates before it
// has changed the text (atleast a quarter of a second).
myBytton.setText("search");
myBytton.setEnabled(true);
myBytton.setClickable(true);
}
}
}
And that's it. It will launch another Thread that will handle the vibration and not freeze your UI thread.
EDIT
Here is the AsyncTask version :
The three elements asked when you extend AsyncTask are :
The type of the parameters you pass to the doInBackground() method
The Type of the elements that are passed in the onProgressUpdate() method.
The Type of the element returned by the doInBackground() method that is also the parameter of the onPostExecute() method.
This is what it looks like :
public class MyTask extends AsyncTask<Void, Integer, Boolean>
{
private Button mButton;
public MyTask(Button button)
{
mButton = button;
}
// Here everything will run on a background Thread
protected Boolean doInBackground(Void... voids)
{
boolean succesullyCalledApi = false;
// do your long querys here
// ...
return succesullyCalledApi;
}
// Here everything will run on the UI Thread
protected void onProgressUpdate(Integer... progress) {
// here you can make some update to the UI like updating a
// progress bar
}
// Here everything will run on the UI Thread
protected void onPostExecute(Boolean succesullyCalledApi)
{
if(succesullyCalledApi)
{
mButton.setText("search");
mButton.setEnabled(true);
mButton.setClickable(true);
// here you start the vibration
vibrator.vibrate(500);
}
}
}
And in your callApi() method you only have to to this :
public void callApi()
{
new MyTask(myButton).execute();
}
EDIT 2
In order to retrieve the query back to your main Thread (or UI Thread) all you have to do is ... nothing.
You are in the UI Thread when the onPostExecute() method is called.
But I assume that you want to retrieve the query back to your MainActivity. To do so :
Pass MainActivity in parameter of MyTask constructor,
Create a method in MainActivity named processQuery() (or whatever you want),
Finally call this method in the onPostExecute() method.
Here are some snippets :
Public class MainActivity extends Activity
{
Button myBytton;
...
public void callApi()
{
// add this to the constructor
new MyTask(this, myButton).execute();
}
// I put String here but adapt it to your query Type.
public void processQuery(String query)
{
// process your query here.
}
}
public class MyTask extends AsyncTask<Void, Integer, Boolean>
{
private Button mButton;
private MainActivity mMainActivity;
public MyTask(MainActivity mainActivity, Button button)
{
mButton = button;
mMainActivity = mainActivity;
}
...
// Here everything will run on the UI Thread
protected void onPostExecute(Boolean succesullyCalledApi)
{
if(succesullyCalledApi)
{
// process your query
mMainActivity.processQuery("THE QUERY YOUR WANT TO PROCESS");
mButton.setText("search");
mButton.setEnabled(true);
mButton.setClickable(true);
// here you start the vibration
vibrator.vibrate(500);
}
}
}
There probably is a better way to do this but this one is simple and work :)
Hope it helps.
Cheers
This is because your call to the API is being done on the UI thread. Even though you have made changes to the UI, the screen won't refresh until the processing invoked from the button clicked event completes. Call your API on a new thread or via an Async Task to get the behaviour you want.
Because you are doing all stuff at the UI Thread. You must use an AsyncTask for your long running operations.
Try below implementation:
public void callApi() {
MyTask myTask = new MyTask();
myTask.execute();
}
private class MyTask extends AsyncTask<Void, Void, Boolean> {
protected void doInBackground(Void... params) {
// This runs on a separate background thread
boolean succesullyCalledApi = false;
// run querys
// do your long running query here and return its result.
return succesullyCalledApi;
}
protected void onPostExecute(Boolean succesullyCalledApi) {
// this runs on UI Thread
if(succesullyCalledApi){
vibrator.vibrate(500);
myBytton.setText("search");
myBytton.setEnabled(true);
myBytton.setClickable(true);
} else {
// You should better think this part also. what will happen if result is false?
}
}
}
I'm not sure if this is the correct way to go about but I will try and explain what I want to do.
I have an Activity which creates a fragment called TemporaryFragment with a label. What I want to do is create and start a service with a Timer in it and that Timer then updates the time in that TextView.
The way I am thinking of going is somehow, when the Service is started, passing the TextView from the Activity to the Service and then the Service keeping a reference to it.
Another possible way is to make the Activity become a listener of the Service and then calling a method in the Service to update the TextView.
Any thoughts would be great and maybe some options.
Thanks in advance.
ADDITION
I'm sorry, I should also specify that I need this timer to run in the background. So when the application is sent to the background, I need the timer to carry on and only stop when I tell it to.
Service is not ideal for such minor task like this, moreover, Service can be run independently of activity. Also spawning new thread or using timer which introduces new thread into the application is not ideal for this relatively minor reason if you are thinking in the terms of mobile applications.
Instead use Handler in your fragment.
create handler in your fragment
private Handler mHandler = new Handler();
to execute your defined task call
mHandler.postDelayed(mUpdateTask, 1000);
or
mHandler.post(mUpdateTask);
and define your task in the fragment
private Runnable mUpdateTask = new Runnable() {
public void run() {
Toast.makeText(getActivity(), "hello world", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(this, 1000);
}
};
If you are showing time-like information instead of countdown-like one, use
mHandler.removeCallbacks(mUpdateTimeTask);
in onPause() method to stop executing your task if the activity is not visible as updating UI isn't relevant and it saves battery (you start task again in onResume() method)
Basically, the idea behind the timer is eventually I am going to add some tracking into my application and therefore need it to continue running even if the application isn't in the foreground – Disco S2
Based on this comment I suggest you to use a local service which resides in the background, doing it's stuff (start a thread from Service#onStart), until it gets stopped by stopService(..).
Activities on the other hand may bind and unbind to that service (see: bindService(..)) to get notified about updates or to communicate with the service in any way.
I would use a more simple approach by using a Thread:
public class MainActivity extends Activity implements Callback {
private static final int MSG_UPDATE = 1;
private static final long INTERVAL = 1000; // in ms
private final Handler handler = new Handler(this);
private Thread worker;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE:
updateView();
return true;
}
return false;
}
private void updateView() {
// TODO tbd
}
#Override
protected void onStart() {
super.onStart();
// start background thread
worker = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
break;
}
// send message to activity thread
handler.sendEmptyMessage(MSG_UPDATE);
}
}
});
worker.start();
}
#Override
protected void onStop() {
super.onStop();
// stop background thread
worker.interrupt();
try {
worker.join();
} catch (InterruptedException e) {
}
worker = null;
}
}
You can use the TimerTask Class for this. Override the TimerTask.run() method and then add that TimerTask to Timer class.
Also check this question: controlling a task with timer and timertask
I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!
There are several ways for doing that,
AsyncTask -
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.
You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}
Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3
You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}
Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};
The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.
I have a Service that launches a Thread and a Runnable like so.
t = new Thread(new Runnable() {
public void run() {
doSomething();
}
});
t.start();
The reason for the thread is to perform an Async task doSomething(). For now lets not worry about the other class AsyncTask. I have tried it and it does not work for my case. Edit: I can't use AsyncTask because it is meant for the UI thread only. This piece of code has to operate inside a Service, so nope, no AsyncTask :(
doSomething() contains some external libs so the issue I am having is that it can potentially be hung at one of the commands, without return any value (hence no error checking can even be done)
To work around this, I will want to, at some point of time, destroy the Service.
stopService(new Intent("net.MyService.intent));
This works fine and is easily verified on the phone. However, the Thread which was created above will continue to run even when the Service that spawned it is destroyed.
I am thus looking for the correct commands to insert in the Service's onDestroy() which will clean up the Thread for me.
t.destroy();
t.stop();
are both depreciated and cause application crashes.
I took this code from somewhere
#Override
public void onDestroy() {
Thread th = t;
t = null;
th.interrupt();
super.onDestroy();
}
but it still does not work, the thread continues to run. Any help guys?
The thread destroy and stop methods are inherently deadlock prone and not safe. Their existence also gives the illusion that there might be some way of halting another thread immediately when something else tells it to.
I understand your thinking, from your point of view their is one main thread, and when this thread hasn't received a response from it's worker thread in a while you'd like to kill it and restart it, without caring what it's up to. But the reason those methods are deprecated is you should care what the thread is up to. A lot.
What if the thread has a lock around a variable you need to use later? What if a thread has a file handle open? In all these cases, and many more, simply stopping the thread at it's current operation would leave things in mess -- quite likely your application would just crash further down the line.
So in order for a thread to be interruptible or cancel-able or stoppable, it has to manage this itself. If a thread or operation provides no way for itself to be interrupted, then you cannot interrupt it - it is assumed to do so would be unsafe.
If you runnable is literally
public void run() {
doSomething();
}
then there is no way to interrupt it. One would hope that if doSomething were a long operation that there might be a way to either interact with it incrementally with something like
public void run() {
while (running) {
MyParser.parseNext();
}
}
or to be able to pass in a variable by reference which indicates whether the thread is interrupted or not, and hopefully the method would interrupt itself at suitable location.
Remember a blocking operation is blocking. There is no way to get around that, you cannot cancel it part way through.
Alternative answer
Use the following code:
MyThread thread; // class field
Create and start the thread as you do it right now.
thread = new MyThread();
thread.start();
When the service is destroyed, "signal" the thread to quit
public void onDestroy() {
// Stop the thread
thread.abort = true;
thread.interrupt();
}
Here is thread implementation
//another class or maybe an inner class
class MyThread extends Thread {
syncronized boolean abort = false;
//ugly, I know
public void run() {
try {
if(!abort) doA();
if(!abort) doB();
if(!abort) doC();
if(!abort) doD();
} catch (InterruptedException ex) {
Log.w("tag", "Interrupted!");
}
}
}
You might want to read the following:
How do you kill a thread in Java?
Thread Primitive Deprecation as already pointed by Claszen
http://www.devx.com/tips/Tip/31728 - based my code from here, but there are some issues with the code!
I think that you could rely on catching the exception and not check abort but I decided to keep it that way.
UPDATE
I've seen this sample in codeguru:
public class Worker implements Runnable {
private String result;
public run() {
result = blockingMethodCall();
}
public String getResult() {
return result;
}
}
public class MainProgram {
public void mainMethod() {
...
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
// Returns when finished executing, or after maximum TIME_OUT time
thread.join(TIME_OUT);
if (thread.isAlive()) {
// If the thread is still alive, it's still blocking on the methodcall, try stopping it
thread.interrupt();
return null;
} else {
// The thread is finished, get the result
return worker.getResult();
}
}
}
Did you check the Java Thread Primitive Deprecation Documentation which is referenced in the Thread API JavaDoc. You will find some hints to handle your problem.
why don't you use an AsyncTask?
A task can be cancelled at any time by
invoking cancel(boolean). Invoking
this method will cause subsequent
calls to isCancelled() to return true.
After invoking this method,
onCancelled(Object), instead of
onPostExecute(Object) will be invoked
after doInBackground(Object[])
returns. To ensure that a task is
cancelled as quickly as possible, you
should always check the return value
of isCancelled() periodically from
doInBackground(Object[]), if possible
(inside a loop for instance.)
I like to take the following approach:
class MyHandler extends Handler {
final Semaphore stopEvent = new Semaphore(0);
#Override
public void handleMessage(Message msg) {
try {
while (!stopEvent.tryAcquire(0, TimeUnit.SECONDS)) {
doSomething();
if (stopEvent.tryAcquire(SLEEP_TIME, TimeUnit.MILLISECONDS)) {
break;
}
}
} catch (InterruptedException ignored) {
}
stopSelf();
}
}
On service onDestroy just release the stopEvent:
#Override
public void onDestroy() {
myHandler.stopEvent.release();
myHandler = null;
super.onDestroy();
}
Better to use global variable stopThread, stop thread once variable changed to true.
btnStop.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0){
stopThread = true;
}
});
public void run() {
while (!stopThread) {
//do something
}
}
I think the best way to create and communicate with another thread is to use an AsyncTask. Heres an example of one:
public class Task extends AsyncTask<Void, Void, Void> {
private static final String TAG = "Task";
private boolean mPaused;
private Runnable mRunnable;
public Task(Runnable runnable) {
mRunnable = runnable;
play();
}
#Override
protected Void doInBackground(Void... params) {
while (!isCancelled()) {
if (!mPaused) {
mRunnable.run();
sleep();
}
}
return null;
}
private void sleep() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w(TAG, e.getMessage());
}
}
public void play() {
mPaused = false;
}
public void pause() {
mPaused = true;
}
public void stop() {
pause();
cancel(true);
}
public boolean isPaused() {
return mPaused;
}
}
You can now easily use this class, and start the thread by writing:
Task task = new Task(myRunnable);
task.execute((Void) null);
Along with this you can easily pause or stop the thread from looping:
Example of pausing and playing the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isPaused()) {
task.play();
} else {
task.pause();
}
}
});
Example of stopping and starting the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isCancelled()) {
task = new Task(myRunnable);
task.execute((Void) null);
} else {
task.stop();
}
}
});