Android Service in background thread - android

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.

Related

Intentservice doesn't call runnable

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.

Is it a good practice to use TimerTask in OnHandleIntent in IntentService?

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.

How do I run parallel actions in android?

How do I run a parallel action (process) to the main app in Android?
I know that, there are a lot of ways to do it: Threads, Tasks, Handlers and etc'...
This is the way I chose. But I think it takes a lot of memory and doesn't closes in the interrupt call.
checkReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO: Check is this a good way to handle threads
Thread t = new Thread() {
#Override
public void run() {
internetConnectionManager.TryConnect();
this.interrupt();
}
};
t.start();
}
}
};
Two things wrong with your arroach:
You should not start a thread in onRecieve method. The reason is explained here :
This has important repercussions to what you can do in an
onReceive(Context, Intent) implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes
Second, calling Thread.currentThread().interrupt() does not make any sense in your example since your thread is already done by that line and will finish, and also because you don not check interrupted flag anyway.
The better way, in my opinion, would be to start a simple IntentService from your onReceive code. Here is a simple tutorial.
Important edit based on FunkTheMonk's comment:
If the broadcast comes from an alarm or external event, it is possible that your device will go to sleep shortly after onReceive returns (even if you create a service). If that is the case, instead of using regular BroadCastReceiver you should extend WakefulBroadcastReceiver from support library.
Use handler
if you want to stop handler then fire an intent with some value eg.("quit handler")to receiver
and call remove call back and inside handler you can handle the rest using ACTION switch
you can also use intentservice

How to make periodic rest requests from Activity?

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 )

Call a specific action in certain time in Android

What I want is 5 minutes after I open the application do a specific work.
I am not sure what I suppose to do.Should I create an AsyncTask in onCreate method of my main activity or a thread? Or should i do something completely different?
This may help: http://developer.android.com/reference/android/app/AlarmManager.html
Your question is a combined question asking how (way) to perform a task as well as how to schedule it.
Decide what is the task you want to perform. If its a long running task, use either AsyncTask or IntentService
To schedule the task you can either use Hander postDelayed, Timer or AlarmManager. My pref. would be a one-time AlarmManager - Once registered, even if you app is not running, the callback will be triggered.
You could use a Handler :
new Handler().postDelayed(new Runnable() { public void run() {
//your delayed action here, on UI Thread if needed
}
}, 1000 * 60 * 5 );
Regards,
Stéphane

Categories

Resources