Android – RideGrid’s mobile client

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.

login

Image 1 of 7

The first time you run the application it asks you for credentials. Thereafter it persists them but allows you to override them.

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.