Welcome!

Welcome to the Official BlackBerry Support Community Forums. This is your resource to discuss support topics with your peers, and learn from each other. New to the forum? Please visit the ‘Getting Started’ link below.
inside custom component

Java Development

Reply
New Developer
darryl_parker
Posts: 14
Registered: ‎08-07-2009

LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

Hi everyone,

 

Thanks for taking the time to read....

 

The Tools:

 

I am using Eclipse JDE Plugin for Eclipse 1.0.0.67, BB Component Pack 4.7.0.46 on a Windows XP SP3 machine. I am deploying to the 8330 simulator and to a real 8530 device for debugging.

 

The Back Story:

 

I have a background thread which monitors GPS location.  I do that by getting a LocationProvider and setting a LocationListener on it.  On the invokation of the LocationListener.locationUpdated() method, the listener copies the Location object into a property available for reading by clients of the class.  There is a "latent" mode where the listener is set with an interval of 20 minutes, and an "active" mode where the listener is set with an interval of 10 seconds.

 

The background thread occasionally caches Location objects in case they are needed suddenly (I want a quick location rather than wait 3 minutes or more for a fix).  If the user opens the related UiApplication and starts using it, the latent interval listener is discarded and a new active interval listener is set.

 

This works well.  When the phone starts, I can see in the debugger the 20 minute latent GPS occuring.  When the user opens the application, the active interval listener gets swapped in and I can see in the debugger console that the GPS fixes start coming every 10 seconds. 

 

The Problem:

 

On both the 8330 simulator and the real 8530 device I see the same problem.

 

When the user closes the application, my code intends to take the active interval listener back out and put the latent interval listener back in. This never happens. The code executes, and in the debugger I step through the execution and see the interval being set back to 20 minutes.  But in spite of that, the console still shows the LocationListener.locationUpdated() method being invoked every 10 seconds. The interval did not actually change. This only happens when going active -> latent.  The original latent -> active change works no problem.

 

And the ultimate result is that battery is being burned through much more quickly that I intend. 

 

The Code:

 

The heart of the code is simply this method:

 

 

private void setListener(int interval) {
  _locationProvider.setLocationListener(null, 0, 0, 0);
  // _listener = null;
  // _listener = new MyLocationListener();
  _locationProvider.setLocationListener(_listener, interval, interval, interval);
}

 

Note that the 2 commented out lines were me desperately trying to null out stuff trying to figure out a fix. It does not correct the problem  First I set the listeneer to null, then I re-set the listener with the argument interval. Note that I have stepped through this method while setting the listener from the 10 second interval to the 20 minute interval, and it seems to work fine.  The interval agrument comes in with correct number of seconds, and it behaves exactly as expected.  There are no exceptions or errors.  The only symptom of a problem is that the Listener's locationUpdated() method continues to be invoked every 10 seconds in spite of the 1800 second interval I pass in.

 

I have also tried doing a LocationProvider.reset(), nulling it, and re-getting the LocationProvider each time I change from active to latent.  That does not correct this issue for me.

 

Any suggestions for ways to proceed would be appreciated.  Thanks again for your time everyone.

 

Darryl.

Please use plain text.
Developer
peter_strange
Posts: 17,718
Registered: ‎07-14-2008

Re: LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

Silly question perhaps, but you do have an OS >= 4.7 on the 8330 Simulator and the 8530 device?

Please use plain text.
New Developer
darryl_parker
Posts: 14
Registered: ‎08-07-2009

Re: LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

 


peter_strange wrote:

Silly question perhaps, but you do have an OS >= 4.7 on the 8330 Simulator and the 8530 device?


 

Thanks for the reply Peter. 

 

First, a correction: I am using the 4.5 component pack.

 

Directly in response: The 8330 sim uses 4.5 and the 8530 device is 5.0

 

Now for some interesting twists on my earlier post.  It is not that the location listener is not changing its interval. What I have discovered is that in fact, BOTH intervals are active.  I had posted before that the interval was not changing becaus ethe 10 second "Active" interval was definitely continuing.  It turns out that if I wait long enough for the Latent longer interval to come around, I get that one too. If I had to guess, I would say that the LocationProvider maintains a list of Timer objects and when I call the .setLocationListener() method with my long-delay latent interval, I am adding another Timer object rather than resetting the current one.

 

Ok, I thought.  Rather than passing back in the same listener with a longer latent interval, I will try to just shut down the listener entirely.  So when the app transitions from 10-second active to the latent model, I now call:

 

 

public void setListenerLatent() {
  _locationProvider.setLocationListener(null, 0, 0, 0);
  _locationProvider.reset();
  _locationProvider = null;
}

 

Now that is pretty pretty text book.  I have seen you Peter copypasta similar code in these forums.  It is what is recomended by the API javadocs and other best practices documentation available from RIM.

 

It seems to work fine.  The App signals it has gone latent, and I can interact with the simulator. To prove that, I will usually do some things like open the dialer application, maybe go into settings and look at those.  The sim is responsive.

 

And then, 10 seconds after going latent (exactly when the LocationListener would have expected to be called by the location provider) I throw a NullPointerException out of LocationProvider$ListenerThread.run() line: 628.

 

I have stepped through the code and there is no other .setLocationListener() called in my code.  I definitely call the .reset() on the provider object.  And then I set to null.  But it appears the Timer which the LocationProvider holds (internally, can't really see into the black box down there) a reference to the most recent argument to the .setLocationListener() method.  And I passed it a null, and there goes the NullPointerException.

 

I cannot believe that I discovered a bug in 4.5 where GPS threads can never ever be turned off?  Extensive googling around these keywords has turned up no one else has ever talked about this. 

 

Anyone have a thought? or suggestion? I am totally jammed here...

 

Thanks,

 

Darryl.

 

 

 

 

 

Please use plain text.
Developer
peter_strange
Posts: 17,718
Registered: ‎07-14-2008

Re: LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

I have recently written some 4.5 specific LocationListener code.  It was different to yours, in that it started up every 5 minutes or so, with an interval of 5 seconds.  Kept going until it got a location, then shutdown.  Then waited 5 minutes, well you get the picture.

 

I don't remember having any problems with my 'old' location listener's being invoked when they should have been shutdown.  Having said that the code has a failsafe.  I create a new locationlistener Object each time, when the LocationListener's job is done, I set a flag in the listener.  Once the flag is set, that listener will ignore any other locations that are passed in.

 

Because my code seemed to work OK, I suspect the GPS code in 4.5 actually does work.  But I could be wrong.

 

That said, you seem to be getting some cross talk between your listeners, so perhaps you have something that is shared, like static variables or some Object/s from your main Thread.  Alternatively you are not processing your LocationProvider stop and start in a separate Thread, so you are getting some kind of lockout condition in your LocationListener.  I know that these are unlikely, but I'm just trying to think outside the box to give some ideas of where you might look for the problem.

 

Can you reproduce this problem on the Simulator?

Please use plain text.
New Developer
darryl_parker
Posts: 14
Registered: ‎08-07-2009

Re: LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

Thanks for the response Peter.

 

I think it would be interesting if you commented out the line which sets the flag in the LocationListener implementaton and see if you have multiple listeners hanging around, but I know we're all busy and anyway I have abandoned LocationListeners altogether. They are simply too problematic.  And 2 weeks of on-again-off-again debugging are rendered moot by a 4-hour rewrite of the whole thing to top using LocationListeners.

 

Specifically on your point, I think flagging the LocationListener implementation to go dormant won't work for me after some mental bench testing. One of my listeners is going every 10 seconds, keeping the GPS chip hot and burning battery.  On my physical 8530, it would kill a full charged battery in about 8 hours even if the phone was in a desk drawer and not being used at all. So flagging the listener to not respond when invoked by the provider would not address the battery usage issue.  I need that gps chip to go cold.

 

Yesterday I rewrote the whole GPS subsystem of the app to run on a separate thread with a while loop in the run() method. Inside the while loop is a call to LocationProvider.getLocation().  No .setLocationListener() at all. The while loop inside run() will call .getLocation(10) continuously until an exit condition is reached (more than 3 minutes elapsed, valid location with a timestamp within the last minute, signal received from outside of the thread that it should cancel, etc.).  The Theads's constructor accepts a callback method off on my main thread, and the gps thread invokes the callback method as it gets valid locations from the chip.

 

So generally, rather than trying to force a LocationListener into a long-interval latent mode, I now have a GPS thread which just burns the GPS chip ful lpower until it can get a location and then exits. It does this on a schedule which I control on a Timer object in my code, rather than trying to delegate that scheduling to the provider and its implementation of LocationListeners.

 

I appreciate you taking the time to read and respond.  Can't wait for my goalposts to move and I start making use of the 5.0 and 6.0 apis.  The grass on the other side of that fence sure looks green....

 

Thanks again,

 

Darryl. 

 

 

Please use plain text.
Developer
peter_strange
Posts: 17,718
Registered: ‎07-14-2008

Re: LocationListener is not changing its interval after re-calling LocationProvider.setLocationListener with a new interval

Your rewrite sounds perfectly reasonable.

 

Just one further comment, and that is I recommend that you review the location you have been given to make sure that it is accurate enough.  I recommend checking the number of satellites at least.  Stay in your loop until you get one that is accurate enough, or alternatively enough inaccurate ones that are relatively close together to be confident.  Just a thought. 

Please use plain text.