Original:
Is there a way to kill a child activity of a TabActivity. I have a very simple tab setup. There are two tabs. One of the tabs contains a MapActivity. When I switch to the MapActivity the GPS turns on. When I press back, the TabActivity exits, but the GPS is still on. The gps doesn't turn off until I explicitly kill the app. Is there a way to kill the MapActivity from the TabActivity? I would like to kill it when TabActivity exits/onBackPressed.
Edit:
I do attempt to stop location requests in onDestroy and onPause in my MapActivity. I am using the MyLocationOverlay class an calling disableCompass and disableMyLocation in the onDestroy method. These methods are called, but the GPS remains on. If I call enableMyLocation and immediately call disableMyLocation (during onCreate), the gps will turn off.
Edited title to reflect the answer:
Turns out the problem is unexpected behavior with MyLocationOverlay's enable*/disable*. These functions do not appear to be idempotent. Multiple calls to enable and disable do not turn it on once or off once as one might expect. Ensuring one call to enable (in onResume) and one call to disable (in onPause) will disable location requests when exiting an activity.
The location service cannot be killed by stopping an activity, you should read up more on location services and how they operate:
http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html
Specifically, when you request location updates from the providers (in your case the GPS provider) you should only request it for a certain period of time, and then you need to make a call to stop the requests.
Also see:
http://developer.android.com/reference/android/location/LocationManager.html
The best thing to do would be to override onStop() or onBackPressed() to stop the GPS. When you are in one of the activities, you have the option of calling getParent() to return the tab activity, as a side note.
It turns out that calling MyLocationOverlay.enable*() multiple times (I was calling it twice) makes the GPS stay on even if you call MyLocationOverlay.disable*() as many times. At least, this is the behavior I observed. I expected enable and disable to be idempotent, but they are not.
Related problem
Related
I have created an application that has a 'geolocation' feature responsible for spotting a user on the Google map like many other applicatons. I used "LocationManager.NETWORK_PROVIDER" to locate the user and at the same time I instantiate and start "MyLocationOverlay" (in the onLocationChanged() method) to get the location. Because of the second one, the GPS turns on (blinking on the top) which is OK.
The problem is, after the application is closed (back button or through task manager), the GPS feature is still hanging there, trying to get the updates.
How to turn it off after the user leaves the activity? I tried suggestions from here and other forums like putting locationManager.removeUpdates(this); and locationManager.removeUpdates(mMyLocationOverlay); within the methods onPause(), onStop(), onDestroy(). The method OnPause looks like this:
#Override
protected void onPause() {
super.onPause();
locationManager.removeUpdates(this);
locationManager.removeUpdates(mMyLocationOverlay);
}
('this' references my class that implements LocationListener)
Please, can someone help me to turn off GPS updates after leaving the activity (it's a class that extends MapActivity) but not turn off the GPS feature on the phone itself?
Interesting thing is that when I remove the part with MyLocationOverlay, GPS will not start of course and therefore no problem. So I'm pretty sure that mMyLocationOverlay is the listener that "won't stop" and producing a problem.
googleMap.setMyLocationEnabled(false); in onPause() solved my issue. And I'm setting that to true in OnCreate(). Hope this may help others.
If you want to close (or end) the application you can use
System.exit(0);
so when the application is closed, all the services you use will close.
Set your LocationListener equal to null and re-instantiate onResume()
I am currently working on a task where i need to fetch the locations from GPS.
The concern i am having here is that once i obtain the location & the task goes completed, after this if the application goes in background i do not wish to obtain any locations until & unless my application is back on screen (foreground) whatis currently not happening. (kindly note here i am not talking about switching the activity from one to another via intent as my app has only one screen & one activity).
I wish to know what place exactly the code to handle this situation must go & how can i do achieve this. I have tried with setting the instance to null & remove update but it proves ineffective. May be i am putting it at wrong place i am putiing it outside onCreate() inside the class extending activity.
Call requestForLocationUpdates() in onResume()
and removeUpdates() in onPause()
Once I obtain the location & the task goes completed
If you just want one Lat, Lon fix: don't use the tracking mode, instead use : requestSingleUpdate()
I have two activities, A and B. Activity A implements a LocationListener that periodically prints out the raw GPS coordinates the screen. Activity B is simply a MapActivity with a MapView. I want to be able to pass the periodically-generated coordinates from A to B, even with A paused in the background and B in the foreground. Turns out that the LocationListener indeed continues to retrieve the coordinates when activity A is paused. With B in focus, then, how do I pass those values over from A? Is startActivity(intent) appropriate for an activity that's already started and in the foreground?
If you need to constantly poll for location updates, consider making a "Sticky" service (but not like androidika). Check out the Remote Messenger Service example. This will allow the activity to "hear" updates on the location from the service.
In my app, i made a base class that "heard" updates of location and if connectivity was lost. Then, the ui activities inherited from this base class. Thus, i could make two different activities receive updates, but minimize duplicate code.
I d' recommend using a service, that runs in the background.
Or rather than having one activity decide when to update the location, write an IntentService that you launch from either of the 2 activities whenever you need them.
Take a look at PlacesUpdateService This does more than just look for the gps coordiantes, but it will give you the idea.
Ok, so the application I've written has a service (that tracks GPS data) with a single main activity that binds to it with bindService in it's onStart() method, and unbinds from the service in it's onStop() method using unbindService(ServiceConnection).
I also have an activity which is an options screen, that is launched by pressing a button on the main activity. On this options screen, I have a checkbox that says "Run in background", which, if set to true, means that when the user exits the application with either the Home or Back buttons, the service will continue running, not turning the GPS off.
I do this by calling this.startForeground onUnbind, and this.stopForeground onRebind, if the setting is set to true, and stopping and starting my location reader onUnbind and onRebind respectively if the setting is false.
If the service is running in the background, it also displays a notification to ensure the user understands that the GPS is still running and draining their power. This notification is displayed and stopped by relying on the startForeground and stopForeground methods.
So, the problem lies in the fact that whether or not this setting is true, if I'm viewing the options screen, I want the service to keep going, and I do not want that notification to appear. So I set a flag that is set to true if I've hit the button to go to the options screen, and do not call unbindService if the flag is true.
This works, except for one slight problem. If the user hits the home button while viewing the options screen, the service is not stopped if it is supposed to be (because it's still bound to the main screen), and if it is supposed to keep running, it does not display the warning notification (and of course, this means that the service is still considered to be in the background).
How should I go about getting this application to behave the way I want it to?
Ok, so I just found a solution that seems to work. I bind the options screen to the service in the activity's onStart() method, and unbind it again in onStop(). The previous activity's onStop() method isn't called until after the new one's onResume() method, so it works.
Does anyone have a better way though? It seems silly to bind an activity to a service that it doesn't actually need access to.
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?
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.
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!
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.
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.
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.
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.
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.
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();.