developing an android app

English: Android Robot. Français : le logo d'a...

Image via Wikipedia

I find the easiest way to learn to develop for a new system or learn a new programming language is to actually create a complete application.  It is even better if there is an actual use for this application because it forces you to complete the whole process from analysis to deployment.  For my android application I wanted to try and learn as many features as possible including using a  database, creating a background service, and using GPS.  Of course not being a java programmer it was going to be a steep learning curve anyway.

The application I decided to develop was a safety camera (speed camera) alert.  There are several applications freely available on the Market that performed this task so I knew it was possible.  The reasons I decided that this would be good as a learning application are :-

  • It would have to use the location service to know where it is.
  • It would have to use a database to store the camera locations.
  • The application would ideally run in the background as a service.
  • It would have to provide some form of visual or audio alert.
  • There would be an opportunity to offer the user a visual of their location on Google map

One of the first things I noticed when researching how to develop this application is the low number of sites dedicated to android development compared to other languages.  Having said that the official android developer site is excellent and stack overflow  also proved invaluable.

Phase 1

As I would not get the time to develop the app in one go I decided to break it down in to three main areas, the location, the database, and the service/notification.  Phase 1 is to find out where I am and decide if I am in a safety camera zone.  To achieve this I took a small selection of the safety camera locations and stored them in an array.

camLong[0] = -8.67112461252223; camLat[0] = 52.6658318926801;
camLong[1] = -8.67337601710352; camLat[1] = 52.6676832277938;
camLong[2] = -8.67487041452395; camLat[2] = 52.6701446666049;
camLong[3] = -8.67500595542655; camLat[3] = 52.6739653070099;
camLong[4] = -8.67586001178516; camLat[4] = 52.6746594788642;
camLong[5] = -8.68802677037349; camLat[5] = 52.6780380717042;

It turned out to be very easy to access the location services on the android platform with only a few lines getting me up and running.  The code below calls showUpdate() every time the GPS location changes.

mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String locationprovider = mLocationManager.getBestProvider(criteria,true);
mLocation = mLocationManager.getLastKnownLocation(locationprovider);
mLocationManager.requestLocationUpdates(locationprovider, 0, 0, this);

public void onLocationChanged(Location location) {
mLocation = location;
showupdate();
}

I was now in a position to display my current coordinates and speed using Location getLatitude(), getLongitude(), getSpeed().  There is no function in the API however to tell you if you are on a road between two coordinates so to determine if I was in a safety camera zone I tried some geometry.  Having three points, the start of the zone, the end of the zone, and my location I used area of a triangle.  The logic being if the area is zero then it must be a straight line.  The testing proved unsuccessful and so was slope of a line.  A closer look at the KML file in Google earth explained why.

You can see from the image the line between two coordinates does not follow the curves of the road so I was only briefly intercepting this line, the rest of the time I was outside the zone.  To resolve this I needed to reduce the accuracy of the GPS.  Initially I took GPS readings to only 3 decimal places but this was also unsuccessful.  The image below shows that I only made the situation worse.

To resolve the issue it was back to geometry again.  The formula that worked was the shortest distance from a point to a line.  I set my code to alert when I was withing 250 metres of a zone.

public void inZone2() {
//initialize variables
double x, y, x1, y1, x2, y2, xx, yy, A, B, C, D, dot, len_sq, param, dist;
double tempDistance = 0;
double shortestDistance = 0;

for (int z = 0; z < camLong.length; z++)
{
//cycle through all coordinates
for (int i = 0; i < camLong[z].length-1; i++)
{
x1 = camLong[z][i];
y1 = camLat[z][i];
x2 = camLong[z][i+1];
y2 = camLong[z][i+1];
x = mLocation.getLongitude();
y = mLocation.getLatitude();

A = x – x1;
B = y – y1;
C = x2 – x1;
D = y2 – y1;
dot = A * C + B * D;
len_sq = C * C + D * D;
param = dot / len_sq;
Location pointLocation = new Location(“point”);

if(param < 0)
{
xx = x1;
yy = y1;
}
else if(param > 1)
{
xx = x2;
yy = y2;
}
else
{
xx = x1 + param * C;
yy = y1 + param * D;
}
pointLocation.setLongitude(xx);
pointLocation.setLatitude(yy);
tempDistance = pointLocation.distanceTo(mLocation);
if (tempDistance < shortestDistance || shortestDistance == 0)
{
shortestDistance = tempDistance;
}
}
}
tvInZone.setText(“distance: ” + shortestDistance/1000+”kms”);
if (shortestDistance < 250)
{
tvInZone.setTextColor(Color.RED);
if (!alertSent)
{
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.post(mUpdateTimeTask);
alertSent = true;
}
}
else
{
tvInZone.setTextColor(Color.GREEN);
mHandler.removeCallbacks(mUpdateTimeTask);
alertSent = false;
}
writeLocation(); //write coordinates to text file for debugging

}

Success at last, next phase will be importing the KML file and storing in in a SQL database.  I will publish the complete code once I have had a change to tidy it up.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s