The application we are developing is a mobile client for the RideGrid service. RideGrid is not in production yet, but it enables a rider and a driver to meet spontaneously for a one time shared ride.
The RideGrid service is implemented as a collection of servlets. One of them is the application portal where mobile clients communicate with the service over a proprietary protocol. The command protocol enables authentication and transactions associated with ridesharing.
A series of screenshots below how the application works.
What Ride Agreement Looks Like
We have a video of what it looks like for two users to reach ride agreement using two phones. Be sure to expand to full screen with the control in the lower right to be able to see the details.
Implementation Notes
The library for the protocol was written in Java before Android and iPhone existed. It is a maven project which can be used in J2EE or on Android. Originally we made the Android project a maven project as well, when the development environment was the Eclipse-based ADT. With the newer Android Studio environment, we’ve switched to Gradle. The Protocol project’s pom.xml needed to have a number of libraries changed to scope “provided” because these libraries are provided by the Android runtime. In the J2EE use of the project, higher level projects include those libraries.
org.apache.httpcomponents httpclient 4.3 provided javax.persistence persistence-api 1.0.2 provided toplink.essentials toplink-essentials-agent 2.0.1-04 provided toplink.essentials toplink-essentials 2.0.1-04 provided mysql mysql-connector-java 5.1.29 com.google.code.gson gson 2.2.4 compile commons-io commons-io 2.4 org.json json 20090211 provided
We used the Adapter Pattern to reduce the amount of code needed for all the message passing. Each call to the service has unique data to send and receive, and because of the nature of Android, the calls must be done in an asynch task. We defined two interfaces: ServerCall and FinisherInterface, and use these in a generic call to the service:
public class GenericAsyncTask extends AsyncTask<Void, Void, RGPErrEnum> {
private ServerCall mMethod;
private FinisherInterface mSuccessCB, mFailCB;
private RGPErrEnum mAsynchRGError = RGPErrEnum.RGPEEundefined;
GenericAsyncTask(ServerCall method, FinisherInterface successCB, FinisherInterface errCB) {
mMethod = method;
mSuccessCB = successCB;
mFailCB = errCB;
}
@Override
protected RGPErrEnum doInBackground(Void... arg0) {
// call the server and get an error code back.
try {
mAsynchRGError = mMethod.ridegridCommand();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return RGPErrEnum.RGPEEundefined;
}
return (mAsynchRGError);
}
@Override
protected void onPostExecute(final RGPErrEnum serviceResult) {
if (RGPErrEnum.RGPEEsuccess == serviceResult) {
mSuccessCB.onTaskDone(serviceResult);
} else {
mFailCB.onTaskDone(serviceResult);
}
}
A specific use of this occurs in the Activity which shows the list of potential matches.
rr = new ServerCall() {
public RGPErrEnum ridegridCommand() throws IOException {
// Load all matches into a member store
mTheMatches = mMatchSession.RGCApollProposals();
return (mMatchSession.getLastError());
}
} ;
...
GenericAsyncTask t = new GenericAsyncTask( rr, rrSuccess, rrFail);
t.execute(); // async run the ridegrid server request
Which we think is pretty clean; the transient ServerCall is declared on the fly in the instantiation, and all it’s doing is providing a way to call the RGCApollProposals() method using the generic async capability. The Android environment seems to require a lot of code to do simple things (relative to JQuery for example where a complex operation can be performed in a just a few lines of code). This is somewhat offset by the Java environment and Eclipse, which makes it easy to write correct code the first time, with fewer errors discovered at run time. We’re becoming fans.
Next step in implementation now that we have the push notifications working is to pass ride-specific data to rider and driver. The rider gets a description of the car and an image. The driver gets a route to pick up the rider.