6

I have a Service which tracks the location of the user. Currently, the Service boots when the application starts and stops when the application terminates. Unfortunately, if users keep the application in the background, the Service never stops and drains battery.

I would like the Service to stop when my application is not in the foreground. I was hoping the Application class would let me Override onPause and onResume handlers, but it does not have them. Is there another way I can accomplish this?

Andrew
  • 20,756
  • 32
  • 99
  • 177
  • When you say "your application is not in the foreground" are you referring to an Activity that is different from your Service (although part of the same app, I'm sure)? – Brandon Dec 04 '10 at 19:32
  • Inside the service's never ending loop, add a check to see whether you application is in the foreground. But it will cost you the 'GET_TASKS' permission in the manifest. – Ε Г И І И О May 25 '13 at 18:53

8 Answers8

5

I haven't tested this yet, but it looks like if you use Context#bindService() (instead of Context#startService()), the service should stop when no more activities are bound to it. (see Service lifecycle).

Then use onPause()/onResume() in each activity to bind/unbind from the service.

Alternatively, you could add a pair of methods on your service which tell it to start/stop listening for location updates and call it from each activity's onResume()/onPause(). The service would still be running, but the location updates wouldn't be draining the battery.

Pete Doyle
  • 937
  • 7
  • 11
  • Interesting. My only problem with the onPause/onResume approach is that, when launching a new Activity, the currently Activity is paused before the new Activity is resumed. So, launching a new Activity would stop the Service. Your second suggestion may work, though. – Andrew Dec 05 '10 at 03:12
1

Reading all the above answers I would suggest Simply add a boolean global flag for each activity & put it in your onResume & onPause & also while launching an Activity Something like this

public void onPause()
{
super.onPause();
activity1IsResumed = true;
}

&same for onResume

& similarly when launching a new Activity

startActivityForResult(myintent ,0);
activity2IsResumed = true;
activity1IsResumed = false;

then in your Service simply check

if(activity1IsResumed || activity2IsResumed || activity3IsResumed)
{
//your logic
}
else
{
//another logic
//or dont run location tracker
}

& you are done!

100rabh
  • 6,156
  • 5
  • 27
  • 41
0

Try using the Bound Services technique to accomplish this.

Bound Services | Android Developers

You can use bound services in a way such that the service will stop when no activities are bound to it. This way, when the app is not in the foreground, the service will not be running. When the user brings the app back to the foreground, the Activity will bind to the service and the service will resume.

Dan Wuensch
  • 104
  • 1
  • 4
0

You should override the onPause and onResume methods on your Activity. If you have multiple activities you may want to have a common base class for them and put the start/stop logic into the base class.

fornwall
  • 2,877
  • 3
  • 25
  • 38
  • So you want my location Service to stop and start every time I go to a new screen? I don't think that's what I'm looking for. – Andrew Oct 28 '10 at 19:06
  • You could set a flag when launching an activity within your own application, and only stop your service if the launching-own-activity flag is not set. – fornwall Oct 28 '10 at 20:14
0

I have not tried this approach but I think you can override the home key of android device by using KeyEvent.KEYCODE_HOME and you can use stopService(Intent) to stop your service and when again application resumes, you can write startService(Intent) in the onResume() method of your Activity.

This way I think your service will only stop when user explicitly presses home button to take application in the background and not when he switches from one activity to another.

MegaMind
  • 336
  • 3
  • 8
0

What I would suggest is overriding the onPause/onReume methods as others have said. Without knowing more about the flow of your application and interactions between Activities, I can't give much more information beyond guesswork.

If your Activities are persistent, however, my recommendation would be to utilize the Intents better when switching between Activities.

For instance, each Activity should have a boolean "transition" flag. So, when you move from one Activity to the next, you set up an Intent extra:

intent.putExtra("transition",true);

Followed in the receiving Activity by: (in onCreate)

intent.getBooleanExtra("transition",false);

This way, for each Activity that launches, you can know whether it has come from another Activity, or if it has been launched from a home screen launcher. Thus, if it gets a true transition, then onPause should NOT stop the service--that means you will be returning to the previous Activity after it returns. If it receives no "transition" extra, or a false transition, then you can safely assume there is no Activity underneath it waiting to take over for the current one.

On the first Activity, you will simply need to stop the service if you are switching to another Activity, which you should be able to figure out programmatically if one Activity is started from another.

Matt D
  • 1,476
  • 3
  • 17
  • 26
0

It sounds like the real problem is how to only stop the service when you go to an activity that isn't one of your own? One way would be to in your onPause method to stop the activity. Do this for all your activities. Then override your startActivity method. And in here do a conditional test to confirm that you are purposefully navigating to one of your own. If your are set a flag to true.

Now go back to your on pause overridden method. And only stop your service if the flag is not equal to true. Set the flag to false.

All events that navigate away will close your service. Navigating to your own will leave it intact.

Do the overriding in a base class that all your activities extend.

Writeen in my andolroid. Will post ezaple later.

Emile
  • 11,451
  • 5
  • 50
  • 63
-1

Create methods registerActivity() and unRegisterActivity() in your Application object and implement first method in all you acts onResume() and second in acts onPause().

First method add activity to List<Activity> instance in your app object, unRegisterActivity() checks size of list in every call if==0 stopService();.

halfer
  • 19,824
  • 17
  • 99
  • 186
asaad399
  • 31
  • 5
  • Interesting, but how will this work? If I launch a new Activity, the previous Activity's onPause() will execute before the new Activity's onResume(). Thus, the count will == 0 momentarily and the Service will stop every time you launch a new Activity. – Andrew Dec 07 '10 at 16:24
  • u r right u may check size in a handler.postDelayed(Runnable,500); or a delay sufficient for all activities to pause ; try this and let me know – asaad399 Dec 07 '10 at 17:54
  • This concept is good but adding activity references to the static Application instance is the easiest way to cause memory leaks. Incrementing a counter on your register / unregister methods would be a better approach and when the counter is less than 0 stop your service. – S-K' Apr 10 '14 at 13:40