03-30-2011 03:26 PM
I have a bunch of code that used to work until I made some changes to get the opopup to fire up everytime I start the app. Trying to fix it seems too hard and the code is long and party legacy code. So
what is a good way of doing this:
When the app starts up it will try to get a GPS fix while it is trying ot get the fix it will popup a "Waiting for fix" screen with a "Set Manually" button. Once the "Set Manually" button is pressed it will dismiss the screen, cancel the attempt to get a gps fix and open a new screen "Location".
Later if the app is told to get a new GPS fix (buy the user clicking a button on the Location screen) the popup will reappear until the GPS fix is made or the button is pressed again.
Also, when the app is using GPS it should automatically get location updates every 20 minutes or so.
I guess the way i have it has some threading issues that are really hard to debug when the app won't even start.
03-30-2011 04:30 PM
If you think your problem lies with the Thread organization and not with the GPS usage, there is an excellent 3-part example in the knowledge base by Peter Strange:
Sample "Please Wait" screen
Read them, understand Peter's logic, look at your own approach and you should see what you need to fix
03-30-2011 05:27 PM
I've just written something very similar, also for GPS. The code I used was in fact based on part 1 - with the amendment that you will find. However it was slightly confused, because the background processing is not a single Thread or Runnable, because I wanted to use a Location Listener.
Sorry this code was written for a customer and is not available. But I think I can give you the basics.
But first you really need to understand the vagaries of GPS. This is the best source I have fund fro GPS information.
OK, there are many parts.
First you have a animation screen and a Thread, that is also Stoppable - see Part 1 for more, but basically it can be stopped. So you push the screen, the animation screen has only the animation and 'stop' button. You start the background Thread, which is Stoppable. If the user presses the Stop button, the background Thread is stopped.
OK simple so far, but what happens in the Background Thread?
Well it starts by getting a LocationProvider. It then starts a LocationListener, getting a new GPS location every 5 seconds. The Thread then goes into a loop, checking to see if in fact it has been given a location. If not it just sleeps for 5 seconds. I didn't in fact use wait/notify on this as timing is not an issue, though perhaps I should have, Ah well, an enhancement.
The LocationListener gets bumped every 5 seconds with a new location. It applies some logic to the location (number of satellites) and when it thinks it has a good one, it stops the LocationProvider and returns this location to the waiting Thread. So the Listener has a reference to the Thread, which I didn't mention before.
If the Background Thread gets a location, it exits, dismissing the Popup.
OK so what if the user pushes the stop button.
Well the Popup Screen stops the running Thread - this will stop the LocationProvider (the Thread started it so it has a reference), which will in fact mean the LocationListener stops being used and will be freed automatically. The running Thread termination processing will dismiss the Popup.
So the Popup Screen has a reference to the Thread, which creates the LocationProvider and the LocationListener. The Listener can supply a location to the Thread, which will stop the Thread, which can then dismiss the Screen. Or the Screen can stop the Thread which then dismisses the Screen.
I use exactly the same mechanism, but this time without the popup screen, when I get a new location every 30 minutes or so.
Hope this is useful and clear.
03-30-2011 07:13 PM - edited 03-30-2011 07:35 PM
Thanks again Peter,
Should the screen be a member of the threads class? So a new one gets created every time the thread is run? In my code now I have it separated and use a reference to it so the same screen can be pushed and popped several times over the life of the app.
I was thinking of putting it inside the thread class and remaking it each time so there will be no more reference juggling.
When I push the screen (its a popup) should I do anything special like make it modal or push globalscreen
or just use a basic pushscreen command. When I pop the screen is there a way to make sure it really gets popped in case some other screen or popup gets on top of it?
03-31-2011 04:13 AM
"Should the screen be a member of the threads class?"
I have a PleaseWaitScreen class, which I use anyway I need to wait from something (GPS Fix, network interaction etc). So for me, no. But your design is your design. Look at the sample that arkadysz provided.
"should I do anything special like make it modal"
Yes make is modal. Do not make it Global -if you make it Global you will force the user to wait because the global screen appears in front of any application screen. Just make it modal and the user can actually swap to another application while waiting.
"is there a way to make sure it really gets popped"
You should not need to worry about this.
Have a look at PleaseWait part 1 especially the amendment. The code there should help answer your questions.
04-01-2011 01:36 PM
OK, I hav ethe following design now:
1) defined a class MyThread which
a) includes the popup screen definition code
b) runs the GPS code
c)starts out by pushing the popoup screen and which pops that screen again if a gps fix is made
d)which defines and runs another thread (childThread) near the top of MyThread.run() which monitors the a MyThread_object.keeprunning boolean variable - if after a
minute has passed and no gps fix is made then changes some text in the popup screen.
e) a loop at the end of MyThread.run() reruns the get-gps-fix code every 20 minutes.
f) the die() method of MyThread also pops the popup screen and sets keeprunning to false;
2) a) the app's main class has a reference for the MyThread object.
b)the main class has methods for recreating and running the MyThread object and calling its die() method.
c) the main class calles the myThread variable's start() method in its constructor so it will always be called when the app starts.
So far in testing this all seems to work. Howerver, Is the e) part above completely redundant since in my get-gps-fix code I have this :
location_provider = LocationProvider.getInstance(criteria); location_provider.setLocationListener(new ThisLocationListener(), 60*20, -1, -1);
which if I read the spec right means that every 60*20 seconds the location will be updated thereby making the aformentioned loop redundant?
Also, what do you think of this little design? Buggy? thread unsafe?
Thanks again Peter
04-01-2011 07:04 PM
Please carefully review the Part 1 Sample PleaseWait code, especially the amendment. I'm not comfortable with the approach you are taking to the Popup screen.
I'm also confused about when the popup screen will appear, especially in relation to the automated GPS fixes.
You need to review the link I have already provided you that explains GPS. I think you have missed some of the implications.
One of the things that you have missed is that the LocationListener may or may not deliver you valid locations. What I suggest you do is start it and have the location listener give you locations every 5 seconds. This is a good time because it takes a while to get active, but once it is active, the anything up to 10 seconds will keep it active without forcing it go through the start up again, which is the real battery killer. You will find that it will take sometime, possibly as much as 3 minutes, before you start getting reasonable fixes. And remember that you will get fixes delivered to you that are, to be blunt, rubbish. Check the number of satellites. 3 or fewer the location is just going to be wrong, 4 is dubious, 5 is mostly OK, 6 is, in my experience, always OK.
I also suggested that once you have a location, you shutdown your Location Listener. leaving it hanging round for 20minutes is not how Location Listener is meant to be used.
I would not have a Thread hanging round for 20 minutes either. There are other ways to make sure this process is triggered when you need it, I would recommend ReadltimeClockListener.
In short, I don't think what you have implemented looks like any of the samples or suggestion that you were given. I suggest you review these again, and if you think your design stacks up, then stick with it. But at least understand the implications.
And can I recommend that you try this on a real device for a significant period, in real conditions (e.g. in and out of buildings, in and out of GPS coverage), and make sure that it stays up and finds a fix when you want.
04-04-2011 08:58 AM
Ok, reviewing it now. BTW, the popup screen will appear once when the app first loads as I want to try to get a GPS fix then, and later if the user hits a certain button. The app allows the user to specify their location serveral ways - GPS fix being just one. So if a user chooses another method and then later wants to return to using GPS, they will hit the GPS button and the popup will appear while the system trys to make the fix.
04-12-2011 08:48 AM
OK, I'm back at this issue now. I made things more like you suggest with the realtimer but that said I have to ask - should I bother with a LocationListener at all?
04-12-2011 10:36 PM
You don't have to. But GPS locations vary significantly in terms of their accuracy, and in my experience, the first location you get can be a little dodgy. So by getting a Location Listener with an interval of say 5 seconds, then, once the fix has been found, you will get 10 GPS fixes in the next minute of so and you choose the most accurate of these or perhaps average them to get a better approximation. But that is just me.