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.
Related
I'm starting a thread like this in my app.
private void AppThreadWorker()
{
AppThread = new Thread(new Runnable() {
#Override
public void run() {
while (canRun)
{
//do async get from server
}
});
AppThread.start();
}
I want to be able to move this app in background and I want this thread continues working. This works fine. The problem is that after 1 hour the Thread stops. Do you know some tricks to let him run for more time?
Use Service for This.
Create a Thread inside Service because by default Service run in UI (Main) Thread.
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.
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.
I have a Start button to start my function for downloading data(startdownload()).
When the start button click i have placed a text view that shows data is dowmload started and when download completed the same text view show download completed .
Download function is placed under a thread.
start_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Status.setText("Download Started");
Thread t = new Thread(){
public void run() {
startdownload();
runOnUiThread(new Runnable() {
public void run() {
Status.setText("Download Completed");
}
});
}};
t.start();
}
});
Also i have a stop button to stop downloading data,which stop the thread and shows download stopped using the same text view as above mentioned.the stop button code is as below
stop_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onStop();
Status.setText("Download Stopped");
}
public void onStop() {
super.onStop();
isRunning = false;
}
The problem is that when i click start button the text view shows download started but when clicked stop button before completely dowloading the data it shows download stopped
in the text view first and after some time it shows download completed.....
Please any one verify that is there any problem with my thread implementation procedure...
I think thats why it shows download completed even when i stoped the thread using stop button....Please help me......
I think you can update UI from thread so please try to use the handler.
Thank you.
Do you actually stop thread? Or it continues to run after you press stop button?
You can use flag isStopped and in thread:
if (!isStopped) {
runOnUiThread(new Runnable() {
public void run() {
Status.setText("Download Completed");
}
});
}
and set isStopped to true in stop_button.
If onStop() is the Activity.onStop() callback method, then you should not call it. It has nothing to do with your downloading thread, and anyway it's just a system callback that is called by system. Actually, stopping a thread by yourself is not recommended, the Thread.stop() method is deprecated, as you may know. It's easy to "stop" a thread that is performing some operations in a loop: you just drop the flag controlling the loop, result is that the thread keeps on running, but it's doing nothing. Your application architecture doesn't let you stop your thread, cause you're just running a task. Post your downloading code and it will be more clear what you're doing and what you're trying to achieve.
I am currently trying to set up a WiFi Scan in my Android application that scans for WiFi access points every 30 seconds.
I have used Timer and TimerTask to get the scan running correctly at the intervals which I require.
However I want to be able to stop and start the scanning when the user presses a button and I am currently having trouble stopping and then restarting the Timer and TimerTask.
Here is my code
TimerTask scanTask;
final Handler handler = new Handler();
Timer t = new Timer();
public void doWifiScan(){
scanTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
wifiManager.scan(context);
Log.d("TIMER", "Timer set off");
}
});
}};
t.schedule(scanTask, 300, 30000);
}
public void stopScan(){
if(scanTask!=null){
Log.d("TIMER", "timer canceled");
scanTask.cancel();
}
}
So the Timer and Task start fine and the scan happens every 30 seconds however I cant get it to stop, I can stop the Timer but the task still occurs and scanTask.cancel() doesn't seem to work either.
Is there a better way to do this? Or am I missing something in the Timer/TimerTask classes?
You might consider:
Examining the boolean result from calling cancel() on your task, as it should indicate if your request succeeds or fails
Try purge() or cancel() on the Timer instead of the TimerTask
If you do not necessarily need Timer and TimerTask, you can always use postDelayed() (available on Handler and on any View). This will schedule a Runnable to be executed on the UI thread after a delay. To have it recur, simply have it schedule itself again after doing your periodic bit of work. You can then monitor a boolean flag to indicate when this process should end. For example:
private Runnable onEverySecond=new Runnable() {
public void run() {
// do real work here
if (!isPaused) {
someLikelyWidget.postDelayed(onEverySecond, 1000);
}
}
};
using your code, instead of
scanTask.cancel();
the correct way is to cancel your timer (not timerTask):
t.cancel();
The Android documentation says that cancel() Cancels the Timer and all scheduled tasks. If there is a currently running task it is not affected. No more tasks may be scheduled on this Timer. Subsequent calls do nothing. Which explains the issue.