google maps

Android Google Maps v2 Tutorial

The great power of mobile applications software, is that it gives us the opportunity to develop many ideas that use hardware features, in order to complete simple everyday tasks. One idea that is implemented in a very good way in the mobile applications world, is the use of maps and the location based applications, that help us in multiple ways in our every day life. So, the use of maps is very important in various mobile applications.

Google provides via Google Play Services a library for using maps. This library is the second attempt of Google Maps and this version provides significant improvements to the older API version. So, in this example, we are going to work with Google Maps v2 and see how we will import a fully working map Fragment in an Activity, as well as, we are going to work with basic Markers and CameraPosition on Google Map.

For our example will use the following tools in a Windows 64-bit or an OS X platform:

  • JDK 1.7
  • Eclipse 4.2 Juno
  • Android SDK 4.4.2

Let’s take a closer look:

1. Create a Google Maps API key

To begin with, we should create a new Google Maps API key and subscribe our application in order to grant access for our application to succesfully use Google Maps v2. In order to use this API, we will have to enter the Google API console portal. If you do not have an account, just create one or login with your current Google account.

Figure 1. Enter Google API Console
Figure 1. Enter Google API Console

After we enter the console, we are going to see the full list, of all the APIs that Google serves. Now we can see the enabled APIs that this console user has.

Figure 2. Go to APIs list

After we enter the console,we are going to see the full list, of all the APIs that Google serves. The API that we are going to use, is the Google Maps v2 API. We click on the right service, and we turn it on. We have to accept the terms of Google Maps v2 API, by ticking the checkbox and by clicking the “Accept” button.

Figure 3. Enable Google Maps v2 API
Figure 3. Enable Google Maps v2 API

We should see the Google Maps v2 API enabled.

Figure 4: Google Maps v2 API enabled
Figure 4: Google Maps v2 API enabled

We are going to create a Public API access credential, in order to take the right response from the Google Places API search call. We only have to go to APIs&auth > Credentials tab.

Figure 5. Credentials Key
Figure 5. Credentials Key

We click the “Create new Key” button, and select the “Android Key” in order to make a Key that will both work from our Android Application and from our browser. We are going to do this, exclusively for our example scope.

Tip

If you want to publish an application to the Google Play Store, that uses any of these Google API calls, you should create an Android key, by using the SHA-1 key of your original keystore (not the debug one) of the application to be exported.

Figure 6. Create new Key
Figure 6. Create new Key

We are going to do this, exclusively for our application scope. So we have to provide our application’s name and package. We have also to fill the SHA-1 cerificate fingerprint.

Figure 7. Configure the allowed IPs
Figure 7. Configure the allowed IPs

If you are not familiar on how to get your SHA-1 cerificate fingerprint, the easiest way to reach this certificate, is inside your Eclipse IDE, from Window > Preferences > Android > Build.

Figure 8. SHA-1 cerificate fingerprint on Eclipse
Figure 8. SHA-1 cerificate fingerprint on Eclipse

2. Create a New Android Application Project

Tip

You may skip project creation and jump directly to the beginning of the example below.

Open Eclipse IDE and go to File → New → Project → Android Application Project.

Figure 9. Create a new Android project
Figure 9. Create a new Android project

Specify the name of the application, the project and the package and then click Next.

Figure 10. Create a new Android project name
Figure 10. Create a new Android project name

In the next window, the “Create Activity” option should be checked. The new created activity will be the main activity of your project. Then press Next button.

Figure 11. Configure the project
Figure 11. Configure the project

In “Configure Launcher Icon” window you should choose the icon you want to have in your app. We will use the default icon of android, so click Next.

Figure 12. Configure the launcher icon
Figure 12. Configure the launcher icon

Select the “Blank Activity” option and press Next.

Figure 13. Create the activity and select its type
Figure 13. Create the activity and select its type

You have to specify a name for the new Activity and a name for the layout description of your app. The .xml file for the layout will automatically be created in the res/layout folder. It will also be created a fragment layout xml, that we are not going to use in this project and you can remove it if you want. Then press Finish.

Figure 14. Create a new blank activity
Figure 14. Create a new blank activity

Here you can see, how will the structure of the project become when finished:

Figure 15. The tree of the project
Figure 15. The tree of the project

 

3. Importing Google Play Services in your project

In order to be able to work with Google Maps v2, we have to import the Google Play Services library in the project.

Tip

Google Maps v2 will work only on devices that do have Google Play Services. If your mobile device does not have Google Play Services you have to download and use the Google Play Services application from Google Play.

Download Google Play Services SDK. We have to launch Android SDK Manager and install the Google Play services package.

Figure 16. Launch Android SDK Manager
Figure 16. Launch Android SDK Manager

Figure 17. Download Google Play Services library
Figure 17. Download Google Play Services library

Figure 18. Import the library as an existing Android project
Figure 18. Import the library as an existing Android project

Figure 19. Import the library as an existing Android project
Figure 19. Import the library as an existing Android project

Figure 20. Import completed.

After downloading the Google Play Service package, just import this project into the main Android Google Maps v2 project.

 

3. Create the layout of the main Google Maps v2

We are going to make a simple layout xml for the AndroidGoogleMapsExample.java, that consists of a parent RelativeLayout and a child LinearLayout with vertical orientation, that includes a Google Map Fragment and a horizontal LinearLayout that includes 3 Buttons that lister to the corresponding actions.

Open res/layout/activity_main.xml, go to the respective xml tab and paste the following:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.javacodegeeks.androidgooglemapsexample.AndroidGoogleMapsActivity" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <fragment
            android:id="@+id/mapFragment"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            class="com.google.android.gms.maps.SupportMapFragment" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/button1"
                android:layout_width="0dp"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:onClick="startAnimation"
                android:text="Animate Marker" />

            <Button
                android:id="@+id/button2"
                android:layout_width="0dp"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:onClick="zoomToMarkers"
                android:text="Zoom to markers" />

            <Button
                android:id="@+id/button3"
                android:layout_width="0dp"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:onClick="animateBack"
                android:text="Animate back to position" />
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

4. Create the source code of the main AndroidGoogleMapsActivity

Open src/com.javacodegeeks.androidgooglemapsexample/AndroidGoogleMapsActivity.java file and paste the code below.

AndroidGoogleMapsActivity.java

package com.javacodegeeks.androidgooglemapsexample;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.javacodegeeks.androidgooglemapsexample.LatLngInterpolator.LinearFixed;

public class AndroidGoogleMapsActivity extends FragmentActivity {

	// Google Map
	private GoogleMap googleMap;
	private HashMap markersHashMap;
	private Iterator<Entry> iter;
	private CameraUpdate cu;
	private CustomMarker customMarkerOne, customMarkerTwo;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		try {
			// Loading map
			initilizeMap();
			initializeUiSettings();
			initializeMapLocationSettings();
			initializeMapTraffic();
			initializeMapType();
			initializeMapViewSettings();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		// initilizeMap();
	}

	private void initilizeMap() {

		googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();

		// check if map is created successfully or not
		if (googleMap == null) {
			Toast.makeText(getApplicationContext(), "Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
		}

		(findViewById(R.id.mapFragment)).getViewTreeObserver().addOnGlobalLayoutListener(
				new android.view.ViewTreeObserver.OnGlobalLayoutListener() {

					@Override
					public void onGlobalLayout() {
						if (android.os.Build.VERSION.SDK_INT >= 16) {
							(findViewById(R.id.mapFragment)).getViewTreeObserver().removeOnGlobalLayoutListener(this);
						} else {
							(findViewById(R.id.mapFragment)).getViewTreeObserver().removeGlobalOnLayoutListener(this);
						}
						setCustomMarkerOnePosition();
						setCustomMarkerTwoPosition();
					}
				});
	}

	void setCustomMarkerOnePosition() {
		customMarkerOne = new CustomMarker("markerOne", 40.7102747, -73.9945297);
		addMarker(customMarkerOne);
	}

	void setCustomMarkerTwoPosition() {
		customMarkerTwo = new CustomMarker("markerTwo", 43.7297251, -74.0675716);
		addMarker(customMarkerTwo);
	}

	public void startAnimation(View v) {
		animateMarker(customMarkerOne, new LatLng(40.0675716, 40.7297251));
	}

	public void zoomToMarkers(View v) {
		zoomAnimateLevelToFitMarkers(120);
	}

	public void animateBack(View v) {
		animateMarker(customMarkerOne, new LatLng(32.0675716, 27.7297251));
	}

	public void initializeUiSettings() {
		googleMap.getUiSettings().setCompassEnabled(true);
		googleMap.getUiSettings().setRotateGesturesEnabled(false);
		googleMap.getUiSettings().setTiltGesturesEnabled(true);
		googleMap.getUiSettings().setZoomControlsEnabled(true);
		googleMap.getUiSettings().setMyLocationButtonEnabled(true);
	}

	public void initializeMapLocationSettings() {
		googleMap.setMyLocationEnabled(true);
	}

	public void initializeMapTraffic() {
		googleMap.setTrafficEnabled(true);
	}

	public void initializeMapType() {
		googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
	}

	
	public void initializeMapViewSettings() {
		googleMap.setIndoorEnabled(true);
		googleMap.setBuildingsEnabled(false);
	}
	

	//this is method to help us set up a Marker that stores the Markers we want to plot on the map
	public void setUpMarkersHashMap() {
		if (markersHashMap == null) {
			markersHashMap = new HashMap();
		}
	}
	
	//this is method to help us add a Marker into the hashmap that stores the Markers
	public void addMarkerToHashMap(CustomMarker customMarker, Marker marker) {
		setUpMarkersHashMap();
		markersHashMap.put(customMarker, marker);
	}

	//this is method to help us find a Marker that is stored into the hashmap
	public Marker findMarker(CustomMarker customMarker) {
		iter = markersHashMap.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry mEntry = (Map.Entry) iter.next();
			CustomMarker key = (CustomMarker) mEntry.getKey();
			if (customMarker.getCustomMarkerId().equals(key.getCustomMarkerId())) {
				Marker value = (Marker) mEntry.getValue();
				return value;
			}
		}
		return null;
	}


	//this is method to help us add a Marker to the map
	public void addMarker(CustomMarker customMarker) {
		MarkerOptions markerOption = new MarkerOptions().position(
				new LatLng(customMarker.getCustomMarkerLatitude(), customMarker.getCustomMarkerLongitude())).icon(
				BitmapDescriptorFactory.defaultMarker());

		Marker newMark = googleMap.addMarker(markerOption);
		addMarkerToHashMap(customMarker, newMark);
	}
	
	//this is method to help us remove a Marker
	public void removeMarker(CustomMarker customMarker) {
		if (markersHashMap != null) {
			if (findMarker(customMarker) != null) {
				findMarker(customMarker).remove();
				markersHashMap.remove(customMarker);
			}
		}
	}

	//this is method to help us fit the Markers into specific bounds for camera position
	public void zoomAnimateLevelToFitMarkers(int padding) {
		LatLngBounds.Builder b = new LatLngBounds.Builder();
		iter = markersHashMap.entrySet().iterator();

		while (iter.hasNext()) {
			Map.Entry mEntry = (Map.Entry) iter.next();
			CustomMarker key = (CustomMarker) mEntry.getKey();
			LatLng ll = new LatLng(key.getCustomMarkerLatitude(), key.getCustomMarkerLongitude());
			b.include(ll);
		}
		LatLngBounds bounds = b.build();

		// Change the padding as per needed
		cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
		googleMap.animateCamera(cu);
	}

	//this is method to help us move a Marker.
	public void moveMarker(CustomMarker customMarker, LatLng latlng) {
		if (findMarker(customMarker) != null) {
			findMarker(customMarker).setPosition(latlng);
			customMarker.setCustomMarkerLatitude(latlng.latitude);
			customMarker.setCustomMarkerLongitude(latlng.longitude);
		}
	}

	//this is method to animate the Marker. There are flavours for all Android versions
	public void animateMarker(CustomMarker customMarker, LatLng latlng) {
		if (findMarker(customMarker) != null) {

			LatLngInterpolator latlonInter = new LinearFixed();
			latlonInter.interpolate(20,
					new LatLng(customMarker.getCustomMarkerLatitude(), customMarker.getCustomMarkerLongitude()), latlng);

			customMarker.setCustomMarkerLatitude(latlng.latitude);
			customMarker.setCustomMarkerLongitude(latlng.longitude);

			if (android.os.Build.VERSION.SDK_INT >= 14) {
				MarkerAnimation.animateMarkerToICS(findMarker(customMarker), new LatLng(customMarker.getCustomMarkerLatitude(),
						customMarker.getCustomMarkerLongitude()), latlonInter);
			} else if (android.os.Build.VERSION.SDK_INT >= 11) {
				MarkerAnimation.animateMarkerToHC(findMarker(customMarker), new LatLng(customMarker.getCustomMarkerLatitude(),
						customMarker.getCustomMarkerLongitude()), latlonInter);
			} else {
				MarkerAnimation.animateMarkerToGB(findMarker(customMarker), new LatLng(customMarker.getCustomMarkerLatitude(),
						customMarker.getCustomMarkerLongitude()), latlonInter);
			}
		}
	}

}

Let’s take a closer look:

	private void initilizeMap() {

		googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();

		if (googleMap == null) {
			Toast.makeText(getApplicationContext(), "Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
		}

		(findViewById(R.id.mapFragment)).getViewTreeObserver().addOnGlobalLayoutListener(
				new android.view.ViewTreeObserver.OnGlobalLayoutListener() {

					@Override
					public void onGlobalLayout() {
						// gets called after layout has been done but before display
						// so we can get the height then hide the view
						if (android.os.Build.VERSION.SDK_INT >= 16) {
							(findViewById(R.id.mapFragment)).getViewTreeObserver().removeOnGlobalLayoutListener(this);
						} else {
							(findViewById(R.id.mapFragment)).getViewTreeObserver().removeGlobalOnLayoutListener(this);
						}
						setCustomMarkerOnePosition();
						setCustomMarkerTwoPosition();
						// plotMarkers(markerList);
					}
				});
	}

With this method initilizeMap(), we set up our map in the Fragment. We use SupportMapFragment in order to make our map compatible with versions older than the Android version 4.0. Also by using the OnGlobalLayoutListener that is called after layout has been done, but before display, in order to avoid making any changes to the map, before the map is fully set up in our layout. Otherwise an error that says, that map is not ready yet, may appear.

	public void initializeUiSettings() {
		googleMap.getUiSettings().setCompassEnabled(true);
		googleMap.getUiSettings().setRotateGesturesEnabled(false);
		googleMap.getUiSettings().setTiltGesturesEnabled(true);
		googleMap.getUiSettings().setZoomControlsEnabled(true);
		googleMap.getUiSettings().setMyLocationButtonEnabled(true);
	}

With the method above, we initialize the map Ui settings, we set the compass, the gestures, the tilt gestures, the zoom controls and the button that centers us to our location spot.

	public void initializeMapLocationSettings() {
		googleMap.setMyLocationEnabled(true);
	}

With the method above, we enable the blue location spot, that shows our position on the map.

	public void initializeMapTraffic() {
		googleMap.setTrafficEnabled(true);
	}

With the method above, we enable the traffic lines layer on the map.

	public void initializeMapType() {
		googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
	}

With the method above, we set the Map Type to the GoogleMap.MAP_TYPE_NORMAL.

	
	public void initializeMapViewSettings() {
		googleMap.setIndoorEnabled(true);
		googleMap.setBuildingsEnabled(false);
	}

With the method above, we initialize the Map View settings, meaning the basic view map and buildings settings.

	public void zoomAnimateLevelToFitMarkers(int padding) {
		LatLngBounds.Builder b = new LatLngBounds.Builder();
		iter = markersHashMap.entrySet().iterator();

		while (iter.hasNext()) {
			Map.Entry mEntry = (Map.Entry) iter.next();
			CustomMarker key = (CustomMarker) mEntry.getKey();
			LatLng ll = new LatLng(key.getCustomMarkerLatitude(), key.getCustomMarkerLongitude());
			b.include(ll);
		}
		LatLngBounds bounds = b.build();

		// Change the padding as per needed
		cu = CameraUpdateFactory.newLatLngBounds(bounds, padding);
		googleMap.animateCamera(cu);
	}

With the above method, we want to zoom the map, at a zoom that we will be able to view every marker that we added on the map. So, this is method to help us fit an array of Markers into specific bounds for camera position.

5. Creating the source code of the helper class CustomMarker.java

We are going to create the CustomMarker.java in order to help us make multiple markers and store them in an array, so that we can use them in the AndroidGoogleMapsActivity. This is a helper class.

Open src/com.javacodegeeks.androidgooglemapsexample/CustomMarker.java file and paste the code below.

CustomMarker.java

package com.javacodegeeks.androidgooglemapsexample;

public class CustomMarker {

	private String id;
	private Double latitude;
	private Double longitude;

	public CustomMarker(String id, Double latitude, Double longitude) {

		this.id = id;
		this.latitude = latitude;
		this.longitude = longitude;
	}

	public CustomMarker() {
		this.id = "";
		this.latitude = 0.0;
		this.longitude = 0.0;
	}

	public String getCustomMarkerId() {
		return id;
	}

	public void setCustomMarkerId(String id) {
		this.id = id;
	}

	public Double getCustomMarkerLatitude() {
		return latitude;
	}

	public void setCustomMarkerLatitude(Double mLatitude) {
		this.latitude = mLatitude;
	}

	public Double getCustomMarkerLongitude() {
		return longitude;
	}

	public void setCustomMarkerLongitude(Double mLongitude) {
		this.longitude = mLongitude;
	}
}

As you can see below, we have added an id attribute in our helper class, in order to have an identifier for our CustomMarker. This will help us find the right marker that we have created and change, or remove it separately.

	public void setCustomMarkerId(String id) {
		this.id = id;
	}

6. Creating the source code of the helper class LatLngInterpolator.java

Open src/com.javacodegeeks.androidgooglemapsexample/LatLngInterpolator.java file and paste the code below.

LatLngInterpolator.java

package com.javacodegeeks.androidgooglemapsexample;

import static java.lang.Math.asin;
import static java.lang.Math.atan2;
import static java.lang.Math.cos;
import static java.lang.Math.pow;
import static java.lang.Math.sin;
import static java.lang.Math.sqrt;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;

import com.google.android.gms.maps.model.LatLng;

public interface LatLngInterpolator {
	public LatLng interpolate(float fraction, LatLng a, LatLng b);

	public class Linear implements LatLngInterpolator {
		@Override
		public LatLng interpolate(float fraction, LatLng a, LatLng b) {
			double lat = (b.latitude - a.latitude) * fraction + a.latitude;
			double lng = (b.longitude - a.longitude) * fraction + a.longitude;
			return new LatLng(lat, lng);
		}
	}

	public class LinearFixed implements LatLngInterpolator {
		@Override
		public LatLng interpolate(float fraction, LatLng a, LatLng b) {
			double lat = (b.latitude - a.latitude) * fraction + a.latitude;
			double lngDelta = b.longitude - a.longitude;

			if (Math.abs(lngDelta) > 180) {
				lngDelta -= Math.signum(lngDelta) * 360;
			}
			double lng = lngDelta * fraction + a.longitude;
			return new LatLng(lat, lng);
		}
	}

	public class Spherical implements LatLngInterpolator {

		@Override
		public LatLng interpolate(float fraction, LatLng from, LatLng to) {

			double fromLat = toRadians(from.latitude);
			double fromLng = toRadians(from.longitude);
			double toLat = toRadians(to.latitude);
			double toLng = toRadians(to.longitude);
			double cosFromLat = cos(fromLat);
			double cosToLat = cos(toLat);

			double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng);
			double sinAngle = sin(angle);
			if (sinAngle < 1E-6) {
				return from;
			}
			double a = sin((1 - fraction) * angle) / sinAngle;
			double b = sin(fraction * angle) / sinAngle;

			double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng);
			double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng);
			double z = a * sin(fromLat) + b * sin(toLat);

			double lat = atan2(z, sqrt(x * x + y * y));
			double lng = atan2(y, x);
			return new LatLng(toDegrees(lat), toDegrees(lng));
		}

		private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng) {

			double dLat = fromLat - toLat;
			double dLng = fromLng - toLng;
			return 2 * asin(sqrt(pow(sin(dLat / 2), 2) + cos(fromLat) * cos(toLat) * pow(sin(dLng / 2), 2)));
		}
	}
}

7. Creating the source code of the helper class MarkerAnimation.java

Open src/com.javacodegeeks.androidgooglemapsexample/MarkerAnimation.java file and paste the code below.

MarkerAnimation.java

package com.javacodegeeks.androidgooglemapsexample;

import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Property;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;

import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;

public class MarkerAnimation {

	static void animateMarkerToGB(final Marker marker, final LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
		final LatLng startPosition = marker.getPosition();
		final Handler handler = new Handler();
		final long start = SystemClock.uptimeMillis();
		final Interpolator interpolator = new AccelerateDecelerateInterpolator();
		final float durationInMs = 500;

		handler.post(new Runnable() {
			long elapsed;
			float t;
			float v;

			@Override
			public void run() {
				// Calculate progress using interpolator
				elapsed = SystemClock.uptimeMillis() - start;
				t = elapsed / durationInMs;
				v = interpolator.getInterpolation(t);

				marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));

				if (t < 1) {

					handler.postDelayed(this, 16);
				}
			}
		});
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	static void animateMarkerToHC(final Marker marker, final LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
		final LatLng startPosition = marker.getPosition();

		ValueAnimator valueAnimator = new ValueAnimator();
		valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float v = animation.getAnimatedFraction();
				LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, finalPosition);
				marker.setPosition(newPosition);
			}
		});
		valueAnimator.setFloatValues(0, 1);
		valueAnimator.setDuration(500);
		valueAnimator.start();
	}

	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	static void animateMarkerToICS(Marker marker, LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
		TypeEvaluator typeEvaluator = new TypeEvaluator() {
			@Override
			public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
				return latLngInterpolator.interpolate(fraction, startValue, endValue);
			}
		};
		Property property = Property.of(Marker.class, LatLng.class, "position");
		ObjectAnimator animator = ObjectAnimator.ofObject(marker, property, typeEvaluator, finalPosition);
		animator.setDuration(500);
		animator.start();
	}
}

8. Modifying the AndroidManifest.xml

In order to make our map visible, we should have access to the Internet. This must be specified in the manifest, so that, our application will be granted the permission to use the Internet connection, with INTERNET, ACCESS_NETWORK_STATE and WRITE_EXTERNAL_STORAGE. Also, a good idea is to give permission ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION for better Location results.

Also, in order to add and use the Google Play Services library, we have to add the specific meta-data tag in our xml. Also, we should not forget the API KEY meta-data tag in our xml, in order to get permission to use Google Maps.

The AndroidManifest.xml of our project is simple and contains the permissions:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javacodegeeks.androidgooglemapsexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="19" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!--
     The following two permissions are not required to use
     Google Maps Android API v2, but are recommended.
    -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidGoogleMapsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyAU9ShujnIg3IDQxtPrafaf7Q1qOvFVdwNmWc4" />
    </application>

</manifest>

9. Build, compile and run

When we build, compile and run our project, the main AndroidGoogleMapsExample should look like this:

Figure 21: This is how the main Activity with the Google maps Fragment looks like
Figure 21: This is how the main Activity with the Google maps Fragment looks like

Figure 22: This is how the Google Map v2 looks like after the first animation
Figure 22: This is how the Google Map v2 looks like after the first animation

Figure 23: This is how the Google Map v2 looks like after the second animation
Figure 23: This is how the Google Map v2 looks like after the second animation

Download the Eclipse Project

This was the example of Android Google Maps v2.

Download
You can download the full source code of this example here: AndroidGoogleMapsExample

References

Animating Markers by Chris Broadfoot on: http://gist.github.com/broady/6314689

Chryssa Aliferi

Chryssa is a Computer Science graduate from Athens University of Economic and Business. During her studies, Chryssa carried out a great variety of projects ranging from networking to software engineering. She is very keen on front end development especially on mobile technologies and web applications. She has worked as a junior Software Engineer in the telecommunications area and currently works as an Android Developer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Julian
6 years ago

I am getting errors after careful copying and pasting the code. Is Chryssa there or is this website no longer maintained?

Back to top button