How to implement background tasks in Android - java

In my application I need, basically, two tasks performed in the background. One is sync some data with a php server, sending values and updating the local database with the answer periodically and the other is download files requested by the main thread from the server,notifying the UI when the download finish.
I only want do those things while the app is in foreground. And if the users opens another app, finish the current transactions and stop consuming resources.
At this point I'm a little lost about how to implement that. I have never used Services and I really dont know if a service is a valid solution, due to the service is used when you want your code still running when the app goes to background.
Other solution I've thought is to implement some kind of Handler that periodically (20 minutes for example) launches a thread for sync with the server. Lauching a thread also when a download is requested and sending a broadcast at the end.
What about that solution? Is valid? If yes, how can I detect when the app (not an activity) stops beeing at foreground in order to cancell the handler's posts?
Thanks in advance

If you choose the service I recommend you to use an IntentService http://developer.android.com/reference/android/app/IntentService.html
When you implement onHandleIntent you can have a loop that waits for the amount of time you want it to sleep, after it wakes up it can perform the task that you want.
#Override
protected void onHandleIntent(Intent intent) {
while(true) {
yourBackgroundTask();
// Sleep
try {
wait(WAIT_TIME);
} catch (Exception e) {
Log.i(TAG, e.getMessage());
break;
}
}
}

Related

How do you save data after onPause(), once the app is closed by user or device?

I have a simple app that counts steps using Sensor.TYPE_STEP_DETECTOR. This sensor is NOT unregistered after the app is set into the background, meaning it continues to track steps even when it's not in focus. Once the app resumes, the step counter UI gets updated with whatever steps were counted since it was last in focus.
My goal is to have the app save the data after it's been closed in the background. It already saves it onPause() but I haven't found any method related to when the app is closed.
At first, onDestroy() seemed like the obvious place, but it's not guaranteed to be called since it only seems to be called when something calls finish() or if the system wants to clear up space.
I've also seen solutions involving using a background service or Job Scheduler. A background service wouldn't work since as of API >= 26 the background services stop after several minutes. I think Job Scheduler wouldn't work since I won't know when the user might close the app and I want the steps to be as accurate as possible, so finding an interval for when to schedule the jobs would be difficult.
I'm looking for a simple spot to basically do what my onPause() method already does.
#Override
protected void onPause() {
super.onPause();
saveSteps(currentSteps);
running = false;
}
What is exactly the problem? Do you just want to replicate the onResume somewhere else?
If so you could do that at the onRestart/onResume function since the sensor isn't unregistered you could get the same results , but I don't see how that would change things for you.

IntentService's own Thread

I know an IntentService itself runs on a different thread.
Also that it execute the onHandleIntent() and stops when that method is done.
my question is: are there any consequences for creating my own custom Thread inside the intent service?
I know it can be done in a Service but I want to know if thats a wrong way of using IntentService
for a bit more information what I need to do is to send lots of HTTP requests.
What im about to do is save on a DB the request strings, and run intent service that execute them.
That's why I use IntentService, the requests might take time and I want the service to shut down once the table containing the requests is empty.
I thought i might increase the speed of this service by adding my own threads to it as I will be running lets say, 5 threads each time.
EDIT:
This is the code I thought to do, I guess it will clear things about what im trying to do and if its possible.
protected void onHandleIntent(Intent intent) {
helper = new DBHelper(getApplicationContext());
File file;
//checks if the DB requests exists
while(helper.requestsExists()){
ArrayList<String> requestArr = helper.getRequestsToExcute(5);
if(!requestArr.isEmpty()){
//execute them and delete the DB entry
for(int i=0;i<requestArr.size();i++){
file = new File(requestArr.get(i));
new MyThread(file).start();// the DB entry is delete withing the thread
}
}
}
}
so this service will run as long as it got any DB entries on my SQLite db, after it will finish executing all of them it will stop.
is it ok or should i use Service for it?
As you have explained, the onHandleIntent is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic.
Why do you want to create a separate thread unless you want to handle multiple requests coming in and handle them in parallel ?
So, if you handle the action that you are suggesting in the onHandleIntent it will hold up other requests to the same IntentService, but it will not hold up anything else.
This answer might help you - start async task from onhandleintent

Using Intent Service in combination with Alarm Manager

I have used the Alarm Manager to allow the user to schedule a certain task to repeat at a certain amount of time. In the context of the application, I have an Android game where people are able to schedule when to send their ships. The Alarm Manager is working fine, alarms get kicked off at the right time etc.
What happens when an alarm is fired off (usually every hour and a bit), is that my IntentService will start communicating with the server to send the ships. This action may take 1 minute, but it can last up to 10 minutes. Even this all works fine. Alarms get fired, ships get sent, everyone happy. The problem arises at night, I go to sleep and expect when waking up that my ships have been sent all night long. Nope. Logging & notifications show that the Alarms are fired correctly, but it appears that the IntentService is killed when it's communicating with the server.
Possible cause for this is that I'm not looking at the game every once in a while like I do when I'm awake, and thus keep some form of process running which prevents the IntentService from being garbage collected.
I've already tried a LOT of things to fix this. I used to work with a BroadCastReceiver, I used to spawn ASyncTasks in the IntentService, but I've since refactored my code to not use those things anymore as they're bad practice for Services.
I have also checked this resource: http://techtej.blogspot.com.es/2011/03/android-thread-constructspart-4.html but I'm still not sure if what I'm doing is the correct thing to handle this situation. I have placed some extensive logging for the next night to review in the morning but I'd like you guys' opinion over this.
Oh I'm also requesting a WakeLock for the complete duration of the onHandleIntent function using:
PowerManager pm = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "MyApplicationWakeLock");
My IntentService:
public class ScheduledRequestService extends IntentService {
public ScheduledRequestService() {
super("ScheduledRequestService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startID){
Logger.d("OnStartCommand!");
return super.onStartCommand(intent, flags, startID);
}
#Override
protected void onHandleIntent(Intent intent) {
ScheduledRequest request = (ScheduledRequest) intent.getExtras().getSerializable("request");
// This function will start a lot of client <-> server communication
request.onExecute(this, intent);
}
#Override
public void onDestroy(){
Logger.d("OnDestroy!");
super.onDestroy();
}
}
So again, my question is; am I structuring this correctly? Should I use a normal Service instead of an IntentService ? Can my IntentService get garbage collected while it is handling an Intent (I think I read that this is possible)?
Can my IntentService get garbage collected while it is handling an Intent (I think I read that this is possible)?
No, but your process can be terminated.
am I structuring this correctly?
Not if you are trying to use a _WAKEUP alarm. You need to set things up more carefully in that case, and I would recommend either WakefulBroadcastReceiver or my WakefulIntentService to handle that pattern.
Should I use a normal Service instead of an IntentService ?
No, an IntentService will be fine. You may need to consider making it a foreground service using startForeground().
Turns out the error was somewhere else than the garbage collector of Android. I was using cache which eventually led to me 'running out of ships' because on send time, it deducted the sent amount of ships from the pool. When they returned however, they were never added back to the cache. During the day I probably manually refreshed the cache or forced Android to clear it by using my phone otherwise which didn't cause the problem to arise (as much).

Does thread die when activity is finished?

If i start a background thread, what will happen if the activity that is started from finishes() before the thread terminates. Will the thread terminate as well or will it stay alive?
new Thread(new Runnable() {
public void run() {
while (mProgressStatus > 0) {
// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
progressbar.setProgress(mProgressStatus);
}
});
}
}
}).start();
Threads run idependently from their parents. Thread dies when it returns from Thread.run() back to JVM normally or due to an uncaught exception.
For what you know your thread/application can die at any point, any time, a phone crashes to the ground and the battery is off and the last thing you know it's a phone that it's turned off in the quickest possible way.
The Android lifecycle and its management it's complicated and there is no real answer because at Google, when commenting this sort of things, they like the word "automagic" a lot, so they are surely not giving away any internal detail about this, at least not in "plain old english".
There are the first Google IO about Android that talks about this stuff, you can go back on youtube and search for a Google IO talks about the Android lifecycle if you want more details about this.
Anyway keep in mind that Android grants you absolutely nothing about how and how long your app will live, and you have at least to variables to consider: what the OS ( Android ) is doing and what the user is doing, and this 2 things can even be mixed togheter when the user gives an input involving the life of your app that Android needs to handle.

Firing Android Activity methods on separate process at set interval

I am writing my first Android app(allot of fun so far!) and have run into a roadblock. I am using SDK tools 21.1 targeting Android 4.2.
I am trying to set up a system that allows activities to register to invoke a method at set time intervals. I wanted to do this in such a way that the processing of the request would be handled on it's own process to avoid making the UI unresponsive.
I have been doing some reading and have explored a few avenues. First I thought that a service would be a good way to go about this but found a fair bit of information suggesting that was not a good course of action due to the OS being able to kill services indiscriminately.
I'm now looking at using a ScheduledThreadPoolExecutor. I've created this simple class with an overridable method to pass methods around:
public abstract class BaseEvent implements EventListener {
public abstract void onFire(Object... params);
}
I've created this runnable task invoke the method:
public class HeartBeatTask implements Runnable {
private BaseEvent mCallback;
private Object mParams;
public HeartBeatTask(BaseAioEvent callback,Object... params){
mParams = params;
mCallback = callback;
}
#Override
public void run() {
Log.d(LOG_TAG,"Run called");
if(mCallback != null)
{
mCallback.onEvent(mParams);
}
}
}
I'm going to use it like this (inside an Activity)
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);
BaseEvent callback = new BaseEvent() {
public void onFire(Object... params){
if(params[0] !=null)
{
Context context = (Context)params[0];
Toast toast = Toast.makeText(context, "Task ran", Toast.LENGTH_SHORT);
toast.show();
}
}
};
threadPool.scheduleAtFixedRate(new HeartBeatTask(callback,(this)),0, 5, TimeUnit.SECONDS);
This will execute the task every 5 seconds, although the callback method is only being run once.
I'm thinking that this may not be a good way to do things. My feeling is that I'm overcomplicating things. What I really need is the ability to have something that will execute a method, on a process other than the main thread, and at a set interval, that activities can bind multiple actions to. So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Could any tell me if I am on the right track here? Is what I am trying to do a viable way to accomplish my goal? Is there a better approach I could be taking? Any advice or suggestions would be very much appreciated. Thanks!
a few suggestions for an Android beginner.
Don't call it a separate process. Process is a different thing (Google 'Linux process'), you want to call them on a separate thread inside the same process.
ScheduledThreadPoolExecutor IS better than anything else people will suggest you here such as Timers or PostDelayed.
But I think you do have a philosophical error here as to UI updates shouldn't be running on a timed manner but on an event base instead. Once your Db, Disk or Network operation finishes from a background thread you callback to the UI thread to update it immediately.
There`re several tools for that and I'll list a few, point the one I like the best, but let you do some research on each one
Handler: That's basic java way
AsyncTask: Nice framework but doesn't handle screen rotation
Loader: That's my preferred way
I think your approach is a bit complicated. Consider you example
So, for instance, I may want to have a UI component update after a call is made
to a database, and would want that to happen every minute.
I think I will do it this way.
Create a AsyncTask which will update the UI component.
Create a thread which will execute a new AsyncTask and sleep one minute in a while loop.
Start the thread in step 3. at some point.
Interrupt the thread if you don't want the component to be updated.
Example of step 2
while (true) {
try {
new updateTask.execute();
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
Android is a mobile platform and in all honesty each time you want something run, you better consider it separately. You may be killing the battery or using resources for no reason. I begrudge Zedge app everyday for running for no reason in the background at all times. Especially since on CyanogenMod kernel puts WiFi to sleep, while apparently it is currently on.
I am guessing this is more of an exercise and for running tasks at a specified intervals. One-offs, most universal can be done via AlarmManager class. But this may not be the best solution.
For some system wide events there is the BroadcastReceiver class.
While addressing
So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Easier done via an Interface really.

Categories

Resources