I am implementing a Service that starts when Android boots, and it's supposed to scan every 10 mins for nearby Bluetooth devices. When it discovers devices, it does some work. Also, this periodic scanning should occur the entire time the device is on. I am trying to schedule a TimerTask, but I don't understand how to use it. I guess it should start this service and let the service do the work instead of writing the code in the TimerTask's run method? How would I start the service from the TimerTask as this seems the easiest way to remedy my problem, but TimerTask is part of java.util and not one of Android's classes.
I just found Android's AlarmManager. Should I use that? Can it start a Service?
So far I have this, but I need help:
class Timer extends Service
{
private Handler myHander;
Runnable r = new Runnable()
{
run()
{
startService(new Intent(Timer.this.getApplicationContext() ,MyService.class));
myHandler.postDelayed(r,10 minutes);
}
}
onCreate()
{
myHandler=new MyHandler();
}
onStartCommand()
{
//Do the bluetooth work.
r.run();
}
onDestroy()
{
super.onDestroy();
myHandler.removeCallback(r);
}
}
class MyService extends Service
{
}
Sorry, I don't understand how the formatting works here.
Will I need to override onDestroy() in the Service? Where to do I use stopService() ?
You need to:
Write service that will be started from one of your activities and/or after device has booted.
In your service in onStart/onStartCommand you need to schedule either using Handler or AlaramManager periodic updates.
The difference between Handler and AlarmManager in this case will be that: Handler will not run when device is in deep sleep, while you can configure AlaramManager to wake up the device and run your code.
I'd recommend to go with Handler, as its easier and because you said you only need to run your code when device is awake.
And one more thing, Handler doesn't use extra thread while TimerTask does. And this is considered a bad practice on Android to waste on thread for timer only.
An example code for how to repeat task using Handler can be found here: Repeat a task with a time delay?.
Related
In one of my android applications, I need to run a task for every minute. It should run even if the app closes and when device is in Idle state also.
I have tried handler, it is working fine when device is active, but not working when device is in idle state.
I have tried workmanager(one time and repeated ) as well. Document says this works even when the device is in Idle mode, but this is stops working after 3/4 repeats.Workmanager is inconsitent, its working sometimes and not working most of the cases till i reboot device.
Can anyone suggest better way to handle the situation?
Thanks
bhuvana
Work manager can only work within 15 minutes of interval, if you do not define a longer time. To run something every minute, you need a Foreground Service with a sticky notification in it. There is no other way to run something every minute.
To start a foreground service, create a service as usual, and in its onStartCommand, call startForeground and from the method, return START_STICKY. These should achieve what you need.
Edit: Sample code for handler thread (this is Java btw, should be similar on Xamarin):
private HandlerThread handlerThread;
private Handler backgroundHandler;
#Override
public int onStartCommand (params){
// Start the foreground service immediately.
startForeground((int) System.currentTimeMillis(), getNotification());
handlerThread = new HandlerThread("MyLocationThread");
handlerThread.setDaemon(true);
handlerThread.start();
handler = new Handler(handlerThread.getLooper())
// Every other call is up to you. You can update the location,
// do whatever you want after this part.
// Sample code (which should call handler.postDelayed()
// in the function as well to create the repetitive task.)
handler.postDelayed(() => myFuncToUpdateLocation(), 60000);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
handlerThread.quit();
}
i have an IntentService that calls webservice in OnHandleIntent every 45 seconds using TimerTask.
my question is:
i am calling on app start the IntentService, and in OnHandleIntent the task keeps repeating due to TimerTask..is it a good practice to do this or does this have any drawbacks? should i use an alarm manager in my activity to call the intent service every amount of time or its fine to keep on repeaing the task in OnHandleIntent using the timer task?
my code is like this:
#Override
protected void onHandleIntent(Intent intent)
{
context=this; //INTENT CONTEXT
final int timerValue = Integer.parseInt(MainActivitySharedPref.GetValue(context, "serviceTimer"));
Log.d(TAG, "DOWNLOADSERVICE called having MainActivity.callService as: " + MainActivity.callService);
t = new Timer();
task = new TimerTask()
{
public void run() {
//run tasks
};
t.scheduleAtFixedRate(task, 0, timerValue); // service executes task every 45 seconds
Thank you.
Is it a good practice to use TimerTask in OnHandleIntent in IntentService?
Absolutely not.
IntentService is designed to allow you to perform work in a supplied background thread via onHandleIntent(). It is not designed for you to fork threads, register listeners, set up TimerTask/ScheduledExecutorService, or do anything else that would be running past the end of onHandleIntent(). The IntentService will shut itself down once onHandleIntent() ends, after which Android may terminate your process within seconds, before your background threads (or, in this case, TimerTask) can do its work.
Please use a regular Service.
should i use an alarm manager in my activity to call the intent service every amount of time or its fine to keep on repeaing the task in OnHandleIntent using the timer task?
If you are doing this only while some activity of yours is in the foreground, the every-45-seconds part is OK. If you are trying to do this continuously, on battery-powered devices, be prepared to be attacked by users for the battery drain that you are causing.
But, while an activity of yours is in the foreground... ScheduledExecutorService (the modern replacement for TimerTask) in a regular Service should be fine. You should not need AlarmManager, which is specifically designed to give you control after your process has been terminated, for longer polling periods.
My Requirement is
Android application has to send user location details(latitude & longitude) to the server for every one hour(which is configurable).
The approach I followed is using the alarm manager i am invoking my service at configured intervals which will send the location details to server irrespective of whether the application is running.
Is this a good approach?
I prefer ScheduledExecutorService, because it is easier for background Tasks.
AlarmManager:
The Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing. This guarantees that the phone will not sleep until you have finished handling the broadcast. Once onReceive() returns, the Alarm Manager releases this wake lock.
ScheduledThreadPoolExecutor:
You can use java.util.Timer or ScheduledThreadPoolExecutor (preferred) to schedule an action to occur at regular intervals on a background thread.
You can see complete answer here => Which is Better ScheduledExecutorService or AlarmManager in android? And Here
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// Hit WebService
}
}, 0, 1, TimeUnit.HOURS);
Yes, using AlarmManager is a good approach
The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
please refer this https://developer.android.com/training/scheduling/alarms.html
Android service run on UI thread so you should not execute long running task in it, like sending data to server. The approach you can use is ScheduledThreadPoolExecutor or AlarmManager for scheduling and using asynctask or any other background thread for sending data to servers
I prefer Timer for repeated tasks.
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
process();
}
};
Timer mTimer = new Timer();
mTimer.schedule(timerTask, 0,60*60*60*1000);
I had a thread which executes a function in every 30 minutes, so I used a combination of handler and runnable thread ( like postdelayed,removemessages ).At that time I couldn’t find any way to stop thread.I tried hander. Removemessages() and hander.removeCallbacks(Runnable) but couldn’t help..
I will suggest you to use TimerTask instead of Thread. Here you can cancel & restart the TimerTask.
I suggest you to use alarmmanager. There is a problem with timertask.
Sometimes the service where the timertask is initiated might be destroyed. If the service is not running timertask will also become disable. It happen frequently when the device is in idle state. So the best solution is to use alarmmanager which trigger an alarm in every 30 minutes whether your device is in idle state or not. You only need to initiate the alarm when you first start the application and need to re-initiate when the device is rebooted. You can use a broadcast receiver to get message when your device is rebooted.
To stop a thread in java, you need to call thread.interrupt(); method.
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if(your condition to stop thread)
{
timer.cancel();
}else
{
\\ your code
}
}
}, 0, 1800000);
use timer inside....it will solve your problem
One of my activity periodically updates nearby friends, which location is obtained from rest service
Currently I use postDelay:
private Runnable updateNearbyFriendsTask = new Runnable() {
#Override
public void run() {
list = api.getNearby(.....)
handler.postDelayed(this, UPDATE_RATE);
}
};
The problem is that postDelayed executed on UI thread, so this runnable task block ui with poor internet connection.
What is the right way to make periodic background rest requests from activity? I don't want to create service for that, because this rest method is used only in this activity.
EDIT
Currently switched to using ScheduledExecutor
this.scheduledExecutor.scheduleWithFixedDelay(new UpdateNearbyFriendsTask(), 0, UPDATE_RATE, TimeUnit.MILLISECONDS);
private class UpdateNearbyFriendsTask implements Runnable() {
#Override
public void run() {
list = api.getNearby(.....)
runOnUiThread(.....)
}
};
I don't see what the problem is with creating a Service, even if it is only used for this activity.
That being said, have a look at the TimerTask. It seems to do what you want.
How about BroadCast receiver using Alarm manager.. http://developer.android.com/reference/android/app/AlarmManager.html
Since its a long running and on going task, would you want to write a Service or an Intent service which does the background job for you.
You can just ping the service whenever your time ticks and let the service do the network activity, freeing up the UI thread for something else. you can always query the service to know the status, or the service itself can respond back to your UI thread.
For ticking the timer, you can use the alarm manager, or perhaps something else (I am not good at any :P )