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 )
Related
I have following code in intent service (I have to use intentservice)
//TIME HANDLER
Log.i("start", "start getting data acc & gps");
//Register listeners and start getting data
//
// ACC:
onStartAcc();
//
handle_lower.postDelayed(new Runnable() {
#Override
public void run() {
Log.i("stop getting data", "STOP");
//Stop listeners
//
// ACC:
onStopAcc();
//==========================================================================
//HERE IS CALCULATING STATUS
//
status.calculateState();
//==========================================================================
}
}, Constants.TIME_ACCELEROMETER_GETTING);
and it doesn't call runnable, no log is shown and accelerometer receiver is not unregistered.
I don't know why this happens. Can someone help me?
I have to use intentservice
You have to not use IntentService for this use case.
it doesn't call runnable, no log is shown and accelerometer receiver is not unregistered
Once onHandleIntent() returns, the IntentService shuts down and goes away. Therefore, you cannot register listeners, fork threads, use poorly-implemented timing systems, etc. in an IntentService.
You are welcome to use a Service. Convert your postDelayed() stuff into a ScheduledExecutorService (so your work is done on a background thread), and make sure that you call stopSelf() at the appropriate point to shut down the service.
I am using AlarmManager of Android and scheduling a repeating alarm using elapsed_time_wakeup for every minute. This alarm fires of a service.
Service does its work (pinging the server(Facebook server in my case) to get data). Next I call onDestroy() of the service. So every minute Service starts -> Does work -> onDestroy()
Is the best way to do this in android?
Do you really need new service every minute? I think you want to start single service. That service does each minute check on server and reports success or error somehow? You want simple always running service with periodic action, not periodic service starting. In this case, starting new service would consume maybe more resources than check itself.
Just make sure service stays running. That might be case until you call stopSelf() from it and starting activity does not stop it also. You may want to run it as
private ping() {
// periodic action here.
scheduleNext();
}
private scheduleNext() {
mHandler.postDelayed(new Runnable() {
public void run() { ping(); }
}, 60000);
}
int onStartCommand(Intent intent, int x, int y) {
mHandler = new android.os.Handler();
ping();
return STICKY;
}
You might want periodic check only on Wifi connection or connection present. And maybe to stop checking when you already know about problem and are solving it. You may want to use startForeground() from Service to start some activity to control it and display results.
I'm trying to create a service that runs in a given interval. The service's purpose is to update a database and when done notify an Activity with an Intent.
The service should also be callable from the activity when the user chooses to 'refresh'.
I have accomplished this, but I can't get it to run in a detached thread.
The service executes an update method in a Runnable:
private Runnable refresh = new Runnable() {
public void run() {
update(); //Runs updates
didUpdate(); //Sends broadcast
handler.postDelayed(this, 50000); // 50 seconds, calls itself in 50 secs
}
};
I have another runnable called ManualRefresh that is called via a broadcast from the activity.
However these runnables seem to be blocking the UI.
Need advice! :)
When you run a Runnable by calling it's run method, it runs on the current thread. To run on a background thread, you need to use new Thread(refresh).start(); (if the Runnable you want run is refresh).
You can also make use of AsyncTask for this, but that's more appropriate for an activity than for a Service. Information about using AsyncTask can be found in the API docs and in the article Painless Threading.
I suggest to write the service using the AlarmManager. The service will receive an Intent to tell it to periodically to update the database.
Once updated, you can notify the Activity with an Intent (as you mentioned).
When the user wants to manually refresh, have the Application sent an Intent to you service. Receiving the Intent from the AlarmManager or from the Activity would perform the same code.
You may also want to reschedule the alarm after a request to manually refresh.
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?.
I've been working with Android for just a couple of weeks now and have some troubles with Services.
I have a background service running which checks every minute or so if a scheduled action needs to be executed. Second use is to store some user data and make them available for my activities. There are two issues:
The service gets binded by my main application but it seems that once I quit the main app, the service gets destroyed too. Why is that and what can I do against it?
The service doesn't run forever but seems to get stopped at a random point.
I understand why Android kills my service and so on and I also tried to use the AlarmManager instead of using a Timer in the service. These approaches somehow work, but they are just not versatile and dynamic enough.
So how can I have both an regular schedule check and some kind of data-sharing the right Android-like way?
You need to read about
local service
and remote service
You can use following link to see difference or goto http://developer.android.com/guide/topics/fundamentals.html link to read about fundamental component of android.
http://saigeethamn.blogspot.com/2009/09/android-developer-tutorial-for_04.html
http://saigeethamn.blogspot.com/2009/09/android-developer-tutorial-part-9.html
You can run a thread using TimerTask and Timer to schedule your task at regular interval
I was using following code to show result on UI.
Handler handler = new Handler();
Timer t;
TimerTask timeTask;
protected void usingTimerTask() {
t = new Timer();
timeTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
btn1.setText("Hi");
}
});
}};
t.scheduleAtFixedRate(timeTask, new Date(), 1000);
}