AngularJS a new world opens

In my spare time I’m currently looking into AngularJS. Before I started working on it I was skeptical. The main reason for it is that it’s  JavaScript framework and I’m not particularly fan of this language at all. Error handling is  mess and the fact that it’s weakly typed isn’t great either.

So why start using AngularJS? I think that the main reason can be described as ‘easy of use’. Because web apps are the way to go I have  to find a tool that can help me write those apps with the least effort. Together with the templating engine and the fact that there is already a lot of stuff in the framework I don’t need to write a whole bunch of code myself just to get a input field to change its value when someone presses a button. Another thing I like about angular is the structure.

Currently, working on my first real app, I have a main module ( the app ) which has dependencies with other modules. The main app is really straight forward and contains only the global things like a user object and so fort. The other modules are in fact directives that contain isolated business logic.

And next to that I have a service module. This module is only used for storing factory definitions. One for connecting to the login REST endpoint, another one for connecting to the data REST endpoint etc. etc. I’m planning on adding some blog posts regarding angular in the future. Don’t expect these to be tutorial like posts but they will be more like post it notes so I wont forget the things I already did in the past 😉

Android Development: Simple collision detection

For my App I need to know when a user drags a specified element on top of another element. For instance when they drag one of their attack cards to the deck of the oponnent. On top of that I also need to know if the current location will result in an attack movement or just in a drag in open space. In both situations the game should do something else. So how can we detect if the current location is resulting in an attack? Simple by using the Rect.intersects method like so

package eu.jeroensomhorst.myfirst.util;

import android.graphics.Rect;
import eu.jeroensomhorst.myfirst.game.ui.UICard;

public final class CardUtil {

	public static boolean touchedCard(UICard c1, UICard c2){
		if(!(c1 == null || c2 == null)){
			Rect rect1 = new Rect((int)c1.x,(int)c1.y,(int)c1.x+c1.getWidth(),(int) (c1.getHeight()+c1.y));
			Rect rect2 = new Rect((int)c2.x,(int)c2.y,(int)c2.x+c2.getWidth(),(int) (c2.getHeight()+c2.y));
			return intersect(rect1, rect2);	
		}
		return false;
	}
	
	public static boolean touchedCard(UICard c, float x, float y) {
		
		Rect cardLocation = new Rect((int) c.x, (int) c.y, (int) c.x
				+ c.getWidth(), (int) c.y + c.getHeight());
		Rect location = new Rect((int)x,(int)y,(int)x+200,(int)y+200);
		
		return intersect(location,cardLocation);
	}
	
	private static boolean intersect(Rect r1,Rect r2){
		return r1.intersect(r2);
	}
}

this class implements a few utility methods. They bassicaly to the same thing. They convert the given parameters into two Rect instances and call the intersect method of the first Rect.  With this little tip you can easily integrate some basic collision detection. with this knowledge we can easily find out if the current user is attacking the enemy and which card is being attacked with the following code:

for(UICard c: this.enemyFrontLine){
					if(CardUtil.touchedCard(currentlyTouchedCard, c)){
						enemyFrontLineCard  = c;
						break;
					}
						
				}

In this example we loop over the enemyfrontline cards and for every card we check if it intersects. If that is the case we break out of the loop and use the found card to do the stuff we want to do with it ( in my case find out which card has ‘won’ and respond accordingly.

 

Android Development: Loading image

In a previous post I talked about loading bitmaps. In this post I will tell something about caching the loaded resources. For this I created a little util class. To give you an example how to use it here is the code. I will explain it step by step.

private Matrix scaleMatrix;

public UICard build(Card c, int color) {

	if (getBitmap(c, color) == null) {
		this.loadBitmap(c, color);
	}

	if (getBitmap(Card.Front, color) == null) {
		this.loadBitmap(Card.Front, color);
	}
	
	
	UICard card = new UICard(c, color);
	card.setBackImage(getBitmap(c, color));
	card.setFrontImage(getBitmap(Card.Front, color));
	return card;
}

private Bitmap getBitmap(Card c, int color) {
	LruCache<Card, Bitmap> cache = this.imageCacheRed;
	if (color == UICard.BLUE) {
		cache = this.imageCacheBlue;
	}
	return cache.get(c);
}

private void loadBitmap(Card c, int color) {
	int drawable = getRedDrawable(c);
	if (color == UICard.BLUE) {
		drawable = getBlueDrawable(c);
	}
	Bitmap cardImage = BitmapFactory.decodeResource(context.gtResources(),drawable);

	cardImage = Bitmap.createBitmap(cardImage, 0, 0, cardImage.getWidth(),cardImage.getHeight(), scaleMatrix, true);

	if (color == UICard.RED) {
		this.imageCacheRed.put(c, cardImage);
	} else {
		this.imageCacheBlue.put(c, cardImage);
	}
}	

private void init() {

	final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
	final int cacheSize = maxMemory / 4;
	this.imageCacheBlue = new LruCache<Card, Bitmap>(cacheSize) {
	@Override
	protected int sizeOf(Card key, Bitmap bitmap) {
		return (bitmap.getRowBytes() * bitmap.getHeight()) / 1024; 
		}
	};

	this.imageCacheRed = new LruCache<Card, Bitmap>(cacheSize) {

	@Override
	protected int sizeOf(Card key, Bitmap bitmap) {
		return (bitmap.getRowBytes() * bitmap.getHeight()) / 1024	}
	};

	Matrix m = new Matrix();
	m.preScale(0.1f, 0.1f);
	this.scaleMatrix = m;
}
}

When the View needs an image it calls the method ‘build’ (3).

It passes a Card object that specifies which card we want to load. We also need to tell the builder which color we need  ( two sides in this game remember? )

It will first check if bitmap belonging to the card specified already has been loaded in the past (20-26).  It therefore will get the correct cache (21-24) ( Yes I have 2 cache’s one for each side ). When the card has not been found in the cache it should be loaded (  5 and 6). Therefore we find the correct drawable (from the R object ) (29-32) and create a bitmap out of it (33-35). We scale it down using a scale matrix and we put the image back in the correct cache (37-41). After that we try to load it again (line 15-16).

By using this approach we asure the app that it will always be using the same instance of a particular bitmap.

I hope this will help you a bit developing your own game apps.

Android Development: Adding touch support

When creating an App users need to somehow interact with your program. Mostly this will include touch support. To set up touch support you need to do the following Warning lots of code !! I will try to explain everything step by step.

Lines 8, 39,73: Listen to the various events.

Line 11-28: When a mouse-down event is detected it means that we are in a new cycle of down->move->up events. In this case it means that we first have find out if the current location was not the previous location and if this is not the case we need to find out if we touched something we are interested in ( 13 ). If so we will do all kinds of stuff with that element and call invalidate. This causes the UI to redraw everything.

Line 39 – 65: If the action_up is detected it means that we are done with our current operation. In this case it means that we have to find out where currently are situated. If that location somehow intersects with another element we are interested in it will cause a change in the ui ( in this case some cards will be redrawn with another image )

73 – 83: Touch support means in most cases drag support. We do this simply by getting our current location and move the current selected element ( a card ) to that new position. Since the x and y coordinates of the event are left/top coordinates we need to change that location so that we don’t touch the top/left corner of that element but somewhat in the middle this feels a bit more natural to the user.

// Add a TouchListener
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		Log.d(TAG, "Event : " + event.getAction());

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.d(TAG, "X: " + event.getX());
			Log.d(TAG, "Y: " + event.getY());
			if (event.getX() != this.previousX
					&& event.getY() != this.previousY) { // we changed
				if (this.touchedMyDeck(event.getX(), event.getY())) {
					if((myDrawnCard!=null && myDrawnCard.getParent().equals(Card.Empty))|| myDrawnCard == null){
						if(myDrawnCard!=null){
							myDrawnCard.recycle();
						}
						if (StrategoGame.getInstance().showCurrentCardOnStack() != null) {
							Card c = StrategoGame.getInstance()
									.drawCardFromStack();
							this.myDrawnCard = new UICard(c,
									StrategoGame.getInstance().getColor(), getContext(),
									this.drawnCardX, this.drawnCardY);
							myDrawnCard.flip();
							this.invalidate();
						}
					}

				} else

				if (this.touchedDrawnCard(event.getX(), event.getY())) {
					currentlyTouchedCard = this.myDrawnCard;

				}

			}

			break;
		case MotionEvent.ACTION_UP:
			if (currentlyTouchedCard != null) {
				UICard frontlineCard = null;

				for (UICard c : this.frontLine) {
					if (CardUtil.touchedCard(currentlyTouchedCard, c)) {
						frontlineCard = c;
						break;
					}
				}

				if (frontlineCard != null) {
					if (frontlineCard instanceof UICardPlaceHolder) {

						int index = frontLine.indexOf(frontlineCard);
						
						UICard newUICard = (UICard) currentlyTouchedCard.clone(getContext());
						if(currentlyTouchedCard.isFlipped()){
							newUICard.flip();
						}
						
						frontLine.set(index, newUICard);
						this.currentlyTouchedCard = null;
						this.myDrawnCard = null;
					}

				}
			}
			// TODO Find out if currentlyDrawnCard is touching frontline. If so
			// check if frontline is empty location
			// IF so add this card to that spot in the frontline else move card
			// to default location.

			break;
		case MotionEvent.ACTION_MOVE:
			if (this.currentlyTouchedCard != null) {

				this.currentlyTouchedCard.x = (int) event.getX()
						- (currentlyTouchedCard.getWidth() / 2);
				this.currentlyTouchedCard.y = (int) event.getY()
						- (currentlyTouchedCard.getHeight() / 2);

			}

			break;
		}
		return true;
	}

This concludes this little blogpost about touch…

Android development: Loading bitmaps

If you want to add graphics to your application you can use the following information

Create a custom Activity like this

public class GameActivity extends Activity implements Observer{

	private static final String TAG = "StrategoGameActivity";
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(new StrategoGameView(this));
		ActionBar actionBar = getActionBar();
		actionBar.hide();
        
	}
    
	
	@Override
	public void update(Observable observable, Object data) {
		// TODO Auto-generated method stub
		
	}

}

Create your own View ( in this example StrategoGameView)

public class StrategoGameView extends View{

public StrategoGameView(Context context){
 super(context);
 initView(context);
}

private InitializeView(Context c){
...
}

}

I personally find it a good practice to call an initialize method in your constructor. This way you can decide if you want to make it public so when needed you can reinitialize easily.

Now if you want to add a Bitmap to your application you need to do the following things

Add a res/drawable directory to your project

create some fancy images and save them in this directory.

After a rebuild you can get a pointer to the using the R.drawable object like this

Bitmap mybitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.cardtop_blue);

to draw the bitmap to the screen you need to add a onDraw method to your View like this:

protected void onDraw(Canvas canvas){

canvas.drawBitmap(mybitmap,x,y, null);


}

 

Android Development: Responding to a socket request

Warning: Worst Blog post written ever in history!

in my current project, a simple multiplayer game, I need to react on a connection request from another device. Currently both devices start their own service discovery. On one device I go to the list of found services and pick on. On the click the ServiceHelper will try to resolve the chosen device and if successful it will start communication sending a simple ‘gameplayrequest’ string.

the other device reacts to this with a OK response. This response is generated only when the user accepts the ‘invitation’. Ok and now some code 😉

try {
	this.server = new Socket();
	server.connect(new InetSocketAddress(location,this.port));
	this.sendRequest(new GameRequestResponseNotifier(GameRequestResponseNotifier.REQUEST_CONNECTION,null));
			
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

....

public void sendRequest(Notifier n) {
 ClientRequestThread ct = new ClientRequestThread(n,this);
 Thread t  = new Thread(ct);
 t.start();
}

..
public void run() {
  try {
    Socket server = instance.getServerConnection();
    PrintWriter writer = new PrintWriter(instance.server.getOutputStream(),true);
				
   writer.println(notifier.toString());
if(!(notifier instanceof OKNotifier)){
	BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
	String data = reader.readLine();
	instance.notifyAll(data);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

These are some code snippets First we need to connect to the other device after we done that we need to send a response. This has to be done in a separate thread. The reason for this is that Android does not allow any heavy operations in the main thread. When we have notified the device that we are ok with the request the result is notified to all our listeners ( the view in this case )

And now the code to start resolving the chosen service

listView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				Object item = listView.getItemAtPosition((int) id);
				
				ServiceHelper.getInstance(null).addObserver((Observer) ListActivity.this);
				ServiceHelper.getInstance(null).resolveService(
						(NsdServiceInfo) item);
				Log.d(TAG, item.toString());
			}

		});

We get an instance of our service helper and subscribe ourselves to it

We start to resolve the service and logging which thing we clicked.

Now the update code in this activity

		if (data instanceof Notifier) {
			Notifier n = (Notifier) data;
			switch (n.toString()) {
			case Notifier.SERVICE_RESOLVE_SUCCESS:
				sendGameRequest();
				break;
			case Notifier.SERVICE_RESOLVE_FAILED:
				showUnabletoConnectToast();
				break;
			case GameRequestResponseNotifier.RESPONCE_CONNECTION_ALLOWED:
				Log.i(TAG,"Lets go to the next screen!");
			}
		}
	}

the update call first checks if the data that we receive is of the type notifier ( a class created by me to send data and some payload ). after we have resolved succesfully (see previous code snippet) we send a request to the server (first snippet) . The server will respond with an ok response ( or response_connection_allowed in this case ). We will log that for now but in the future this will cause a switch to another activity.

That’s it for now.

Android Development: Starting a server socket

As you already know the application i’m building is using service discovery to connect to other devices. How does this work?

Step 0:  Add activity as observer to the servicehelper class (line 4)

Step 2: Start registering the service to the network (10)

protected void onResume() {

		Log.d(TAG, "On Resume called");
		ServiceHelper.getInstance(this).addObserver(this);
		if (!ServiceHelper.getInstance(this).hasServiceRegistered(
				StrategoService.SERVICE_NAME, StrategoService.SERVICE_TYPE)) {

			ServiceHelper sh = ServiceHelper.getInstance(this);
			try {
				sh.registerNewService(StrategoService.SERVICE_NAME,
						StrategoService.SERVICE_TYPE);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		super.onResume();
	}

Step 3: If service has been registered successfully update ui and start a server socket that waits for any connection. (line 19)

	@Override
	public void update(Observable observable, Object data) {
		if (data instanceof Notifier) {
			Notifier n = (Notifier) data;
			switch (n.toString()) {
			case Notifier.SERVICE_REGISTRATION_SUCCESS:

				
				final TextView text = (TextView) findViewById(R.id.edit_message);
				final NsdServiceInfo info = (NsdServiceInfo) ((Notifier) data)
						.getPayLoad();
				if (text != null) {
					runOnUiThread(new Runnable() {
						public void run() {
							text.setText(info.getServiceName());
						}
					});
				}
				ServiceHelper.getInstance(this).startAndListen();
				break;
			case GameRequestResponseNotifier.REQUEST_CONNECTION:
				// TODO Show dialog
				// Dialog OK send connection_accept response
				IncomingGameRequestDialog dialogCreater = new IncomingGameRequestDialog(this);
				dialogCreater.show(this.getFragmentManager(),TAG);
				
				
				
			default:
				Log.d(TAG, data.toString());
			}
		}
	}

 

Android development about listeners

For my App I need to use service discovery. Service Discovery is a piece of code that lets your android device search for other devices in the same network that can connect to you. But also it gives you the power to generate your own service so other devices can find you.

I wont go into detail about how to setup all this but it involves a lot of callback listeners. Althrough I like the idea of this I dont like the way some people on the internet, who explain this to people who never done this before, implement it. As stated in my previous android blogpost the standard tutorials work with the idea of putting everything in a activity. And well I just dont like that.

So for the service discovery logic and all listeners (3!) that go with it I created a class called ServiceHelper ( if you take a look at the tutorials from android about service discovery they use the same idea ). This helper is a singleton that registers a certain service on the network and works as its own listener for these type of events. So how is this different from the default approach?

The difference comes when I want to let the activity know that something has happened. I’m using the so called Observer/Observable pattern for this. I create my activity. I retrieve an instance of my servicehelper and add myself as a listener to that helper class.

the only thing I need to do next is to add a method ‘update’ so the helper can inform me about what happened. Why I like this idea better? Simple. If an activity implements a RegisterServiceListener, a ResolveListener, a GetMeSomeCoffeeListener the activity gets poluted with all kinds of ‘listener’ methods such as ‘onCoffeeServed’ or ‘onNoCoffeeAnymore’ methods.

Now I only have 1 method update(source, data) and in this update method I can add the logic to handle all the events I’m interested in. I think it makes the code a bit cleaner and easier to understand.

Android Development

It has been a while since my last dev related posting but here it goes. I decided to pick up android development to see how it goes and if it is as hard as people say it is. This blogpost will give you a little insight in the things I stumbled upon. Be warned. This blogpost is not written in some chronological order. It just a bunch of things I have to remember when doing android development. Therefore this post can be updated in the future.

Continue reading “Android Development”

Java: Reading GPX data from Endomondo

I’ve started using Endomondo as my primary workout application for a couple of weeks now and although it is a great app I want to have more control over my data. Luckily for us endomondo users they offer a export function that exports the workouts in GPX format.

Today I’ve been playing around with this library: https://sourceforge.net/projects/gpxparser/ and get the GPX file from Endomondo to be parsed succesfully..

So first of all I created a new project in my Eclipse and imported the GPX parser from the website into another project. I downloaded a file from my endomondo account and wrote a little code:

GPXParser p = new GPXParser();
p.addExtensionParser(new HeartRateExtensionParser());
FileInputStream in = new FileInputStream(location);
GPX gpxFile = p.parseGPX(in);

As you can see. Nothing to fancy. So now what? If we take a sneak peek at the file http://www.jeroensomhorst.eu/wp-content/uploads/20140816_100357.gpx you will see there is no information whatsoever about distance, speed, average heartrate and so on. We have to add that ourselves. Luckily its GNU license so I can edit the source as I please (or atleast that’s what I make out of the license..).

Let start by refactor the GPXParser class. I want to generate a custom GPX class that implements my interface EndomondoGPX. First create the interface

public interface IEndomondoGPx {

	public double getAverageHearthRate();
	public double getTotalDistance();
	public double getMaxHearthRate();
	public double getMinHearthRate();
	public double getTotalDuration();
	public double getMaxSpeed();
}

Nice, isn’t? Next create a new class called EndomondoGPX

package org.alternativevision.gpx.beans;

import java.util.ArrayList;
import java.util.Iterator;
import org.alternativevision.gpx.beans.sort.WayPointComparator;
import org.alternativevision.gpx.extensions.HeartRateExtensionParser;

public class EndomondoGPX extends GPX implements IEndomondoGPx {

	double avgHearthRate = -1;
	double trackpoints = -1;
	double maxHearthRate = -1;
	double TotalDuration = -1;
	double maxSpeed = -1;
	double minHearthRate = -1;

	public EndomondoGPX() {
		super();
	}

	private Iterator<Waypoint> getAllTrackPoints() {
		ArrayList<Waypoint> tp = new ArrayList<Waypoint>();
		for (Object o : this.getTracks().toArray()) {
			Track t = (Track) o;
			tp.addAll(t.getTrackPoints());
		}
		tp.sort(new WayPointComparator());
		return tp.iterator();
	}

	public double getAverageHearthRate() {

		if (avgHearthRate == -1){
			double hearthRate = 0;
			int trackpointcount = 0;
			
			Iterator<Waypoint> trackpionts = getAllTrackPoints();
			while(trackpionts.hasNext()){
				Waypoint wp = trackpionts.next();
				Object hr = wp.getExtensionData(HeartRateExtensionParser.PARSER_ID);
				if(hr instanceof HearthRate){
					hearthRate += ((HearthRate) hr).getHearthRate();
					trackpointcount++;
				}
			}
			
			this.avgHearthRate = (hearthRate / trackpointcount);
		}
		return avgHearthRate;

	}

	@Override
	public double getTotalDistance() {
		double currentDistance = 0;
		Iterator<Waypoint> trackpoints = this.getAllTrackPoints();
		while(trackpoints.hasNext()){
			Waypoint p1 = trackpoints.next();
			Waypoint p2 = null;
			if(trackpoints.hasNext()){
				p2 = trackpoints.next();	
			}
			
			if(p2 != null){
				System.out.println(p1.getTime());
				System.out.println(p2.getTime());
					double distance = getDistance(p1,p2);
					if(distance == 0){
						distance = getDistance(p2,p1);
					}
					System.out.println(distance);
					currentDistance += distance;
			
			
			}
		}
		currentDistance = (currentDistance/100)*101;
		return currentDistance;
	}

	@Override
	public double getMaxHearthRate() {

		if (this.maxHearthRate < 0) {
			double hearthRate = -1;
			Iterator<Waypoint> trackpoints = this.getAllTrackPoints();
			while(trackpoints.hasNext()){
				Object hr = trackpoints.next().getExtensionData(HeartRateExtensionParser.PARSER_ID);
				
				if (hr != null && hr instanceof HearthRate) {
					if (((HearthRate) hr).getHearthRate() > hearthRate) {
						hearthRate = ((HearthRate) hr).getHearthRate();
					}
				}
			}
			this.maxHearthRate = hearthRate;
		}
		return this.maxHearthRate;
	}

	@Override
	public double getMinHearthRate() {
		if(this.minHearthRate<0){
			double hearthRate = -1;
			Iterator<Waypoint> trackpoints = this.getAllTrackPoints();
			while(trackpoints.hasNext()){
				Object hr = trackpoints.next().getExtensionData(HeartRateExtensionParser.PARSER_ID);
				if (hr != null && hr instanceof HearthRate) {
					double entryRate = ((HearthRate)hr).getHearthRate();
					if(hearthRate == -1){
						hearthRate = entryRate;
					}
					else if(entryRate< hearthRate){
						hearthRate = entryRate;
					}
				
					
				}
			}
			this.minHearthRate = hearthRate;
		}
		return this.minHearthRate;
	}

	@Override
	public double getTotalDuration() {
		Iterator<Waypoint> trackpoints = this.getAllTrackPoints();
		while(trackpoints.hasNext()){
			Waypoint p = trackpoints.next();
			p.getTime();
		}
		return 0;
	}

	@Override
	public double getMaxSpeed() {
		// TODO Auto-generated method stub
		return 0;
	}
	
	private static double getDistance(Waypoint p1, Waypoint p2){
		double EARTH_RADIUS = 6371;
		double dLat = toRad(p2.getLatitude() - p1.getLatitude());
		double dLon = toRad(p2.getLongitude() - p1.getLongitude());
		double dLat1 = toRad(p1.getLatitude());
		double dlat2 = toRad(p2.getLatitude());
		double a = Math.sin(dLat/2)*Math.sin(dLat/2)+Math.cos(dLat1)*Math.cos(dlat2)*Math.sin(dLon/2)*Math.sin(dLon);
		double c = 2 * Math.atan2(Math.sqrt(a),Math.sqrt(1-a));
		double d = EARTH_RADIUS * c; // distance Kilometer
		return d;
		
	}
	private static final double toRad(double f){
		return f * (Math.PI/180);
	}
}

The code is pretty simple. There are some util functions there for retrieving all the trackpoints. This method also sorts them by time.

To make this happen I had to make  change to class that is base for all classes in the default GPX parser. The extension class. I had to make it abstract, implement a interface (comparable !) and make a abstract method public int compareTo(Object o1, Object o2).

All other classes such as waypoint should implement the compareTo. For this patch I only need to add the compareTo to the Waypoint class.

After some testing I found out there is a little bug in the GPX parser. When there is more then 1 trkseg node it will overide that node all the time. So you will end up with only the last trkseg node. In this case (see file) it will only contain one trkseg with one trkpt node. Not what we want!

The fix for this is the following method in Track.java

public void setTrackPoints(ArrayList<Waypoint> trackPoints) {
		
		if(this.trackPoints == null){
			this.trackPoints = trackPoints;
		}else{
			this.trackPoints.addAll(trackPoints);
		}
	}

It won’t overwrite all trackpoints for the current track it will add them. For now that is correct but I wont recommend it for all GPX files out there.

So, when that is done. We can start changing our Parser class.

Open up the GPXParser class and add the following method:

	@SuppressWarnings("unchecked")
	public <T extends GPX> T parseGPX(InputStream in, Class c) throws ParserConfigurationException, SAXException, IOException{
		try {
			return (T) parseGPX(in,(GPX) c.newInstance());
		} catch (InstantiationException e) {
			logger.error("Could not Instantiate custom GPX class");
		} catch (IllegalAccessException e) {
			logger.error("Could not instantiate custom GPX class illegal access");
		}
		return null;
	}

and refactor the method signature of parseGPX to

private GPX parseGPX(InputStream in, GPX gpx) throws ParserConfigurationException, SAXException, IOException {
..
}

Now add the following method for backwards compatability:

	public GPX parseGPX(InputStream in) throws ParserConfigurationException, SAXException, IOException{
		return this.parseGPX(in,new GPX());
	}

What we have done is pretty simple. First we created a new method to parse given GPX file (using inputstream) to a object of our own. We tell the GPXParser to parse the xml to our own instance of the GPX class. (in our case EndomondoGPX ).

Next, because we added that method we had to change the default method. We made it private, so that nobody can use it behind our back and we added a new parameter an instance of the GPX class. Inside this method we had to remove the  the GPX gpx = new GPX() because we now send it in as a parameter;

Last of but least we had to add a new method for backwards compatability. All this does is creating a new default GPX object and pass it into the changed method. We can now change our first code snippet to :

GPXParser p = new GPXParser();
p.addExtensionParser(new HeartRateExtensionParser());
FileInputStream in = new FileInputStream(location);
IEndomondoGPx gpxFile = (IEndomondoGPx) p.parseGPX(in, EndomondoGPX.class);
gpxFile.getAverageHearthRate();
gpxFile.getTotalDistance();
gpxFile.getMaxSpeed();
gpxFile.getMaxHearthRate();
gpxFile.getMinHearthRate();
gpxFile.getTotalDuration();

As you can see we have now full control what type of GPX object we get.

To get this all working by the way you also need to create a new HeartRateExtensionParser class. This class is used to parse extensions that comes with Endomondo.

<gpxtpx:TrackPointExtension>
            <gpxtpx:hr>146</gpxtpx:hr>
          </gpxtpx:TrackPointExtension>
package org.alternativevision.gpx.extensions;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.alternativevision.gpx.beans.GPX;
import org.alternativevision.gpx.beans.HearthRate;
import org.alternativevision.gpx.beans.Route;
import org.alternativevision.gpx.beans.Track;
import org.alternativevision.gpx.beans.Waypoint;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class HeartRateExtensionParser implements IExtensionParser {

	public static final String PARSER_ID = "HeartRateExtensionParser";
	private XPathFactory xPathFactory = XPathFactory.newInstance();
	private XPath xpath = xPathFactory.newXPath();
	private XPathExpression exp = null;
	
	
	
	public HeartRateExtensionParser() {
		try {
			exp  = xpath.compile("d");
			
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	@Override
	public String getId() {
		return PARSER_ID;
	}

	@Override
	public Object parseWaypointExtension(Node node) {
		NodeList childNodes = node.getChildNodes();
		for(int i = 0; i < childNodes.getLength();i++){
			Node n = childNodes.item(i);
			if("gpxtpx:TrackPointExtension".equals(n.getNodeName())){
				NodeList tpNodes = n.getChildNodes();
				for(int j = 0;j<tpNodes.getLength();j++){
					Node m = tpNodes.item(j);
					if("gpxtpx:hr".equals(m.getNodeName())){
						String t = m.getTextContent();
						if(t!= null && !"".equals(t)){
							double d = Double.parseDouble(t);
							return new HearthRate(d);
						}
						
						
						
					}
				}
			}
		}
		
		System.out.println("No Hearthrate node found..");
		return null;
	}

	@Override
	public Object parseTrackExtension(Node node) {
		System.out.println("Parse Track Extension");
		return null;
	}

	@Override
	public Object parseGPXExtension(Node node) {
		System.out.println("Parse gpx Extension");
		return null;
	}

	@Override
	public Object parseRouteExtension(Node node) {
		System.out.println("Parse Route Extension");
		return null;
	}

	@Override
	public void writeGPXExtensionData(Node node, GPX wpt, Document doc) {
		System.out.println("Write ExtensionData");
	}

	@Override
	public void writeWaypointExtensionData(Node node, Waypoint wpt, Document doc) {
		System.out.println("Write WaypiontExtensionData");

	}

	@Override
	public void writeTrackExtensionData(Node node, Track wpt, Document doc) {
		System.out.println("Track extension");

	}

	@Override
	public void writeRouteExtensionData(Node node, Route wpt, Document doc) {
		System.out.println("Write Route Extension");
	}

}

If you want to code.. let me know. It is still little buggy (the distance calculations seems to be a bit odd compared to endomondo ) but it works.