Thursday, July 14, 2011

Blackberry app for Pace Bus of Chicago - Entry 2

I wasted the whole of yesterday in watching movies, eating and sleeping and so did not work on the app at all. Today I worked some quality time on the app and overhauled the map UI interface.

I had implemented a working prototype of map feature but there were couple of problems. First thing was the Map was drawn directly from the main PaceBus screen. That was a very bad design and I thought it would be simple for now, for development sake and hence went with it. But going through that design I was having trouble bringing the route information into the Map and passing it around the timer and HTTP connection thread to fetch the route's data. So this morning the first thing I worked was to make a Map Launch Screen containing drop down box and a button to launch Map. The drop down had the routes populated from the HTTP route fetch thread.The user is required to select the route from the drop down, click on Goto Map button to open map. This way I had the selected route in the Launch screen and was able to pass it to any module as need arises.
The next problem was to handle the timer. The idea is to have a timer set up which will go off every 15 secs (say) and everytime it triggers, the timer thread would run a fetch thread to obtain the new coordinates from the PaceBus web server and pass it to map to update the locations. The change in UI helped me in this also. Previously I had problem in deciding from where to start the timer and from where to terminate it. Now it was clear that I should start the timer when user clicks on the Goto Map button. So on button click, map is invoked and timer is run.

/**
* @see FieldChangeListener#fieldChanged
* Note: Due to the reason this is only back door, when user changes _kbUseAreaBasedProbability field the threshold will be set to default.
*/
public void fieldChanged( Field field, int context ) {
if(field == _gotoMapButtonField)
{
//Map button clicked. Get the route number selected
int routeSelectedIndex = _routeNumberChoiceField.getSelectedIndex();
strRouteNo= (String) _routeNumberChoiceField.getChoice(routeSelectedIndex);
if(strRouteNo == null || PaceConstants.SELECT_ROUTE_FROM_LIST.equals(strRouteNo)){
Dialog.inform("Select a route from the list.");
return;
}
//fetch the bus coordinates for that route
Thread fetchThread = new Thread(){
public void run() {
HTTPDemo.getInstance().fetchPage(PaceConstants.MAP_COORDINATES_PAGE+"?u="+strRouteNo, PaceConstants.EXTRACT_COORDINATES);
}};
fetchThread.start();
//In the meantime, run the spinner
UiApplication.getUiApplication().pushModalScreen(spinner);
//start a timer to timely fetch bus coordinates
timer = new Timer();
task = new TimerTask()
{
public void run()
{
//on timeout, fetch data only if Map application is running
boolean MapRunning = false;
ApplicationDescriptor descriptors[] = ApplicationManager.getApplicationManager().getVisibleApplications();
for(int i=0; i
if(descriptors[i].getName().equals("BlackBerry Maps")|| descriptors[i].getName().equals("Maps")){
Thread fetchThread = new Thread(){
public void run() {
HTTPDemo.getInstance().fetchPage(PaceConstants.MAP_COORDINATES_PAGE+"?u="+strRouteNo, PaceConstants.EXTRACT_COORDINATES);
}};
fetchThread.start();
MapRunning = true;
break;
}
}
if(!MapRunning){
//cancel timer if Map application is no more running
timer.cancel();
}
}
};
//after a delay of 5 secs, the timer will timeout every 20 secs
timer.scheduleAtFixedRate(task, 5000, 20000);
PaceBusApp.log("MapLaunchScreen(): Goto Map button event is handled. Timer started.");
}

}

The code above describes the action taken when Goto Map button is clicked. It also contains the timer initialization code. Everytime the button is clicked a fresh timer is created. One more modification done was that the timer would fetch coordinates only when there is a Map application currently running. If there is no Map application running, then the timer will cancel itself.
The MapLaunchScreen implements GlobalEventListener so it gets a notification when the coordinate fetch is complete. In the event handler, if the data received from fetch is null that means there are no buses running at this time and this is also the place where we should stop the timer (remember the timer was started the moment Map launch button was clicked) plus we should invoke a default map which doesn't have any location info. Just a generic map. Makes sense.

public void eventOccurred(long guid, int data0, int data1, Object object0,
Object object1) {

if( guid == PaceConstants.GUID_PACE_FETCH_BUS_COORDINATES && data0 == PaceConstants.EXTRACT_COORDINATES)
{
PaceBusApp.log("PaceBusApp: MapLaunchScreen - eventOccured(): GUID_PACE_FETCH_BUS_COORDINATES");
//if spinner is running, close it
if(this.spinner != null){
this.spinner.close();
this.spinner = null;
}
//save the object received
if(object0 == null){
Dialog.inform("There are no buses running this time.");
//remove timer
if(timer!=null)
timer.cancel();
//show default map
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments());
return;
}
CoordinatesData = (BusCoordinatesDb)object0;
//display the coordinates on map
handleMap();
PaceBusApp.log("PaceBusApp: MapLaunchScreen - exiting eventOccured()");
}
}

The code above is the event handler which is invoked everytime the coordinates have been fetched.
handleMap is a simple function which forms the location string from the coordinates obtained and call the Map application with that argument.


public void handleMap(){
//return if we did not receive valid coordinates
if(CoordinatesData == null)
return;
Vector lt = CoordinatesData.getLatitude();
Vector lg = CoordinatesData.getLongitude();
//prepare the location string
stringBuffer = null;
stringBuffer = new StringBuffer("");
for (int i = 0; i
int g = (int) ((Double.parseDouble((String)lg.elementAt(i))) * 100000);
int t = (int) ((Double.parseDouble((String)lt.elementAt(i))) * 100000);
stringBuffer.append("");
}
stringBuffer.append("");
//launch the map application. If Map is already running, the locations will be updated
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments( MapsArguments.ARG_LOCATION_DOCUMENT, stringBuffer.toString()));
}

The map code idea is borrowed from BlackBerryMapsDemo project under the sample applications. This much should suffice for now. Next time I'll try to fix some UI related bugs in the module developed so far.

KD

Stumble Upon Toolbar

Wednesday, July 13, 2011

Blackberry app for Pace Bus of Chicago - Entry 1

If I had the power to go back in time 4 months from now, this would be that blog entry. Today I realized I should blog about my 4 month old project i.e the Blackberry app I am developing for the Pace Bus transit system of Chicago suburban. The project is still going strong and I am very pleased with the results so far. Since I am late in blogging about it, I'll start it right away. In this blog I'll summarize the work done so far and from now on I will make sure to have one entry at-least every time I am working on the app.

I was in Chicago 4 months ago, doing my internship at Research In Motion when my colleague Anu suggested that we should develop an app as an internal project in RIM. I thought its exciting and will be a good use of my spare time so I agreed instantaneously. Then we decided to sit down every Wednesday for 2 hrs to discuss about it. The first meeting was to decide on the app we would be developing. Necessity is the mother of invention. I suggested to let us make a list of things we do from the moment we get off the bed till we go to bed and see if we can improve on something to make the job easier. To make my point clear, I gave Anu an example. Lets say you wake up in the morning on a typical day and do what, may be brush your teeths, shower, dress up, then reach the bus stop and wait for bus....wait a sec....may be we can develop an app that would let you know whens the bus coming and ...Bingo! We got our-self an app.
The agenda for next Wednesday meeting was 'Research'. We would look around for an existing app that does the same thing more or less. We could not find any, no Android or iPhone or BlackBerry app. There were apps for the Chicago subways but not for Pace Bus, the suburban bus service system. Next is feasibility study. Doing an exercise on sample BB apps and the tools, IDE etc went fine and a successful HelloWorld app was a boost for the confidence. Pace Bus has its own website of course and a little help from their web server combined with our effort could indeed produce an app.
And so we began coding. Design was simple. Ask the user about routes, directions and stop info through drop down menus and fetch the information from their web server using a background thread. The UI design is driven by how the Pace Website UI is. Anu's contribution is invaluable to the project. She is a genius in coding and makes the job so much easier for me to code thereafter. The app was now able to display the next three times at which a bus is expected at the selected stop just like website. On top of that we added 'MyFaves' wherein the user's selected stop info can be saved to be used later without going through selecting the stuff all over again. Then we added 'Rider News' to the app which will display news about any route affected because of construction, re-routing, temporary suspension of service etc.
We wanted to implement the map feature but it was close to my end of term and so we submitted the app to BB App guys for launching. Maps and other knickknacks were postponed for ver2. Then I moved to Florida to finish my last term in the University. Anu remained at RIM.
For reasons beyond significance here, the launch date of AppWorld got postponed to 3 months which is like 5 weeks from now. While in Florida and with launch delay, I got around to fix couple of things in the app. The Logo, for instance, had to be changed. We had used Pace's official logo but afraid of copyright issues, I designed a new logo for the app. Then I started working on the map feature. Anu was busy with company work and I didn't want to distract her so much but she was again very helpful in this. She sent me a list of links she visited when she was researching about the Map thing.

These were really important esp the first one which actually holds the dynamic coordinates of the bus, exactly the thing I was looking for. I have no idea how on Earth was she able to find that link. I tried real hard myself to locate one such link but failed. With these parameters available and borrowing codes from sample BBMaps codes, I made a working map feature, which is now able to display the location of buses in the map and updates them periodically.
This much information is enough for this post. In short, the app is working, with features like dynamically displaying time, MyFaves, Rider News and now Maps (partially done).
Next post onwards I'll discuss the development on a daily basis.


KD

Stumble Upon Toolbar