My service needs to check for something every minute and
while(true)
{
Thread.sleep(60000)
//REST OF CODE HERE//
}
is not working. Making the application freeze and asking me to forcefully stop it.
I am sure the problem is with the while loop but I thought it was the only way to infinitely repeat the service whenever the onStart() method executes.
Any suggestions are appreciated.
EDIT
I fixed it and in case you were wondering how the code looks like well there you go:
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Toast.makeText(this, "Service running", Toast.LENGTH_SHORT).show();
handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Toast.makeText(protectionService.this, "5 secs has passed", Toast.LENGTH_SHORT).show();
}
};
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(5000);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
Basically the service is been called and the tasks of that service will be repeated every 5 secs in that case.
I would like to thank vineetska, Janusz and inazaruk for suggesting to use Handlers. I would like to thank everyone who answered as well, your help was very much appreciated.
create a thread in your service and put while loop there like this:
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
while(true)
{
Thread.sleep(60000)
//REST OF CODE HERE//
}
}
}).start();
Each of lifecycle method of service is called from UI thread. If you need background task to be running all the time, you can crate new thread for this. This is actually very well described in documentation.
In your case however, you should consider using AlarmManager instead. It handles recurring events very well and was specifically designed for similar scenarios.
Another solution would be to use Handler and its postDelayed() function. This can be used when your operation (that should be executed every 60s) is not time-consuming (or otherwise you should still run it in background thread).
Overall, creating a thread that sleeps all the time is not a good solution for mobile devices. This consumes resources that could've been spent for something more useful. Especially considering a rich set of capabilities of Android for recurring events.
A service itself is not a subthread. This means that every code that is run in your service will be run on the main UI Thread. You need to start a Thread, or use an AsyncTask in your service to move the computation to the background.
Have a look at the documentation of service for more information.
If you want to repeat some code every minute you can use a handler.
A handler has a method called postDelayed this allows you to specify a time after which a runnable will be run. Just call the method again at the end of your runnable to rerun the code after a minute.
Services run on the main thread. If you want to offload processing, you have to start a separate thread. Have a look at IntentService, it does this by default. On another note, having an infinitely running service with sleep() might not a good idea. For scheduled processing, you might want to use AlarmManager.
As Janusz wrote, you can use handler to post delayed. Here is a sample:
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do repeatable stuff
handler.postDelayed(this, DELAYED_TIME);
}
};
handler.post(runnable);
It will post runnable and then post it again and again after DELAYED_TIME.
Related
I want perform a network call in every 30sec to push some metrics to Server. Currently I am doing it using thread.sleep(). I found some articles saying thread.sleep() has some drawbacks. I need to know am I doing it right? or Replacing the thread with Handler will improve my code?
public static void startSending(final Context con) {
if (running) return;
running = true;
threadToSendUXMetrics = new Thread(new Runnable() {
#Override
public void run() {
do {
try {
Thread.sleep(AugmedixConstants.glassLogsPushInterval);
} catch (InterruptedException e) {
mLogger.error(interrupt_exception + e.getMessage());
}
// to do to send each time, should have some sleep code
if (AugmedixConstants.WEBAPP_URL.equals(AugmedixConstants.EMPTY_STRING)||!StatsNetworkChecker.checkIsConnected(con)) {
Utility.populateNetworkStat();
mLogger.error(may_be_provider_not_login_yet);
} else
sendUXMetrics();
} while (running);
if (!uxMetricsQueue.isEmpty()) sendUXMetrics();
}
});
threadToSendUXMetrics.start();
}
If You are using only one thread in the network, then usage of the thread.sleep() is fine. If there are multiple threads in synchronization, then the thread.sleep() command will block all the other threads that are currently running.
As per the details you've provided, there is only one thread present which isn't blocking any other active threads which are running in synchronization, so using thread.sleep() shouldn't be a problem.
Use Handler.postDelayed to schedule tasks if you are working in UI Thread and Thread.sleep if you are working in background thread.
Apparently you are sending some data using network, you must do it in the background thread, hence Thread.sleep is recommended.
Simple is:
Thread.sleep(millisSeconds): With this method, you only can call in background tasks, for example in AsyncTask::doInBackground(), you can call to delay actions after that. RECOMMENDED CALL THIS METHOD IN BACKGROUND THREAD.
Handler().postDelayed({METHOD}, millisSeconds): With this instance, METHOD will trigged after millisSeconds declared.
But, to easy handle life cycle of Handler(), you need to declare a Handler() instance, with a Runnable instance. For example, when your Activity has paused or you just no need call that method again, you can remove callback from Handler(). Below is example:
public class MainActivity extends Activity {
private Handler mHandler = Handler();
public void onStart(...) {
super.onStart(...)
this.mHandler.postDelayed(this.foo, 1000)
}
public void onPaused(...) {
this.mHandler.removeCallback(this.foo)
super.onPaused(...)
}
private Runnable foo = new Runnable() {
#Override
public void run() {
// your code will call after 1 second when activity start
// end remove callback when activity paused
// continue call...
mHandler.postDelayed(foo, 1000)
}
}
}
The code above just for reference, I type by hand because don't have IDE to write then copy paste.
I am creating an application that needs to update values every minute even if the app isn't running.
Of course, I have set up a simple Service to do that. I have debug messages set up to tell me when the Service starts, when it updates (every minute), and when it closes. I also have a message telling me when the values update inside a runOnUiThread() method. All of my messages activate except for the one in the runOnUiThread(). Is there something I'm doing wrong (of course there is)? What do I need to change?
Code:
#Override
public void handleMessage(Message message) {
try {
if (!serviceStarted) {
serviceStarted = true;
serviceTest = true;
while (serviceStarted) {
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Thread.sleep(((1 /* minutes */) * 60 * 1000));
System.out.println("Updated values through service.");
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
stopSelf(message.arg1);
}
So there's no need to do that, unless you're creating a Thread inside
of it
Gabe Sechan's answer is correct.
But if you are using a separate thread then instead of following code:
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Try, this code:
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
As per Android docs
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process (unless you specify otherwise).
You can't create an Activity by calling new. It doesn't initialize properly that way.
Also, Services by default run on the UI thread. So there's no need to do that, unless you're creating a Thread inside of it. If you are- runOnUIThread is just syntactic sugar for posting a runnable to a handler. So you can just do that instead.
Try using a handler or LocalBroadcastManager to send a message to the activity.
See this question: Accessing UI thread handler from a service
You can use Looper.getMainLooper() within a Handler to post a Runnable that executes whatever you're trying to execute.
A good alternative though, like jinghong mentioned, is to use broadcasts - in other words, use a different pattern.
i got a FixedSizeThreadPool with 1 Thread(because i only Need one and every following request should wait till the earlier request has been finished):
myService = Executors.newFixedThreadPool(1);
myService.execute(new WorkerRunnable());
In my WorkerRunnable i do some stuff and in the middle i call a method from my Activity:
myActivity.thisMethodRunsOnUiThread();
The Method Looks like this:
public void thisMethodRunsOnUiThread() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
I'm trying to Change a View here, that's why i Need to do this on Ui Thread
}
});
}
And after that on the WorkerRunnable there Comes my last Method which should again run on the seperateThread from the fixedSizePool
myActivity.thisMethodsRunsonUiThread();
thisMethodRunsAgainOnTheSeperateThread();
But what i mentioned here is that he only calls the method which should RunOnUiThread after the MethodWhichShouldRunOnSeperateThread.(Which is the last method so my Thread would be finished at this time). Could it be that the seperateThread got a higher priority as the MainThread so that he waits till the seperateThread is finished and then he starts the method which runs on the UiThread?
I Need to finish the method
myActivity.thisMethodsRunsonUiThread();
before this method
thisMethodRunsAgainOnTheSeperateThread();
Can somebody explain why he acts like that? Any help is appreciated.
refer to http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
if the current thread is not the UI thread, the action is posted to the event queue of the UI thread
Hence, this runnable must wait some time to be executed
You can use wait() and notify()/notifyAll() java methods for thread manipulation
I'm making an app for real time image processing. For that, I made a service to capture an image without using an user interface. Now, I want to start this service again and again so that each time the service starts, it takes an image, process it, and then starts again and so on....
I'm doing this by starting a timer at the end of the process in the service and then restart the service in the onFinish() method of that timer, like this:
new CountDownTimer(3000,1000){
public void onTick(long millisUntilFinished) { }
public void onFinish() {
mCamera.release();
Intent intent = new Intent("com.example.helpingproject.CameraService");
startService(intent);
Log.d("Tag1222", "timer finished");
}
}.start();
Can anybody please help me in this? "timer finished" appears in the log but the service does not start again.
You could create a thread in your service and put while loop there like this:
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
while(true)
{
Thread.sleep(60000)
//REST OF CODE HERE//
}
}
}).start();
But this is an easy quick fix, overall, creating a thread that sleeps all the time is not a good solution for mobile devices.
You should consider using AlarmManager instead. It handles recurring events very well and was specifically designed for similar scenarios.
Use a service running in background and then, everytime you want to work with the picture start a thread.
At a certain point of my AsyncTask, after some validations have been done, I need to spawn off another thread to do some other work. So I'd like two background threads at this point, each doing it's own thing (approx 2-3 seconds to execute each). The idea is to maximize performance on dual core processors like Atrix.
Is it acceptable to create another asynctask & execute it from the first one? Can anyone suggest a better way of doing this?
Thanks!
EDIT: I'm wondering what publishProgress() from the second task would even do... since it was not started from an Activity?
Is it acceptable to create another
asynctask & execute it from the first
one?
Yes, but only inside onProgressUpdate() or onPostExecute() since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.
I'm wondering what publishProgress()
from the second task would even do...
since it was not started from an
Activity?
It does exactly the same thing, since you are starting it from the UI thread.
If you are looking for a mechanism of executing multiple async tasks, from 3.0 and above it supports a method called executeOnExecutor which will allow you to schedule tasks in parallel on a pool of thread managed by Async Task.
An AsyncTask is useful for doing some background work while communicating with the main thread to handle UI changes. It appears that this is not your case.
Besides, an AsyncTask must be executed from the main thread. From the AsyncTask reference:
There are a few threading rules that
must be followed for this class to
work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
You can a take a look at this article and see what fits you best.
This can be done using message passing concurrency and a single handler. Proof of concept code follows:
private Handler myHandler= new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
Toast.makeText(Main.this,"Message0", Toast.LENGTH_SHORT).show();
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(3000);
}
catch(Exception e){}
myHandler.sendEmptyMessage(2);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
break;
case 1:
Toast.makeText(Main.this,"Message1", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(Main.this,"Message2", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
break;
}
}
};
I launched the first thread on a button click as in:
ON CLICK HANDLER
threadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(1000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(0);
try {
Thread.sleep(3000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(1);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
}
});
The calls to thread sleep is to mimic a time intensive task.