Tuesday, January 27, 2015

Google Maps Android Marker Clustering


Overview

By clustering your markers, you can put a large number of markers on a map without making the map hard to read. The marker clustering utility helps you manage multiple markers at different zoom levels. To be precise, the 'markers' are actually 'items' at this point, and only become 'Markers' when they're rendered. But for the sake of clarity, this document will name them 'markers' throughout. When a user views the map at a high zoom level, the individual markers show on the map. When the user zooms out, the markers gather together into clusters, to make viewing the map easier. The marker clustering utility is part of the Google Maps Android API Utility Library. If you haven't yet set up the library, follow the setup guide before reading the rest of this page.

Step1:

In Eclipse goto File ⇒ New ⇒ Android Application Project

Step2:Downloading Google Maps Android API Utility Library.

https://developers.google.com/maps/documentation/android/utility/

Step3: Add a simple marker clusterer.

Here is a summary of the steps required:

  1. Implement ClusterItem to represent a marker on the map. The cluster item returns the position of the marker as a LatLng object.
  2. Add a new ClusterManager to group the cluster items (markers) based on zoom level.
  3. Set the map's OnCameraChangeListener() to the ClusterManager, since ClusterManager implements the listener.
  4. If you want to add specific functionality in response to a marker click event, set the map's OnMarkerClickListener() to the ClusterManager, since ClusterManager implements the listener.
  5. Feed the markers into the ClusterManager.

MyItem.java



package com.example.clustering;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterItem;
public class MyItem implements ClusterItem {
private final LatLng mPosition;
public MyItem(double lat, double lng) {
mPosition = new LatLng(lat, lng);
}
@Override
public LatLng getPosition() {
return mPosition;
}
}


MyItemReader.java



package com.example.clustering;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MyItemReader {
private static final String REGEX_INPUT_BOUNDARY_BEGINNING = "\\A";
public List read(InputStream inputStream) throws JSONException {

List items = new ArrayList();
String json = new Scanner(inputStream).useDelimiter(REGEX_INPUT_BOUNDARY_BEGINNING).next();
JSONArray array = new JSONArray(json);
for (int i = 0; i < array.length(); i++) {

JSONObject object = array.getJSONObject(i);
double lat = object.getDouble("lat");
double lng = object.getDouble("lng");
items.add(new MyItem(lat, lng));
}
return items;

}
}


Step4:

MainActivity.java


package com.example.clustering;
import java.io.InputStream;
import java.util.List;
import org.json.JSONException;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.example.googlemapclustering.R;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.clustering.ClusterManager;
public class MainActivity extends Activity {
GoogleMap map;
private ClusterManager mClusterManager;
@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
map.setMyLocationEnabled(true);
map.getUiSettings().setZoomGesturesEnabled(true);
map.moveCamera(CameraUpdateFactory.zoomTo(13.2f));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));
mClusterManager = new ClusterManager(this, map);
mClusterManager = new ClusterManager(MainActivity.this, map);
map.setOnCameraChangeListener(mClusterManager);
map.setOnInfoWindowClickListener(mClusterManager);
map.setInfoWindowAdapter(mClusterManager.getMarkerManager());
map.setOnMarkerClickListener(mClusterManager);
try {

readItems();
} catch (JSONException e) {
Toast.makeText(this, "Problem reading list of markers.", Toast.LENGTH_LONG).show();
}
}
private void readItems() throws JSONException {
InputStream inputStream = getResources().openRawResource(R.raw.radar_search);
List items = new MyItemReader().read(inputStream);
mClusterManager.addItems(items);
}
}



Step5:

activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout >



Step6:


res -> raw ->radar_search.json
Sample lat,lng
[
{ "lat" : 51.5145160, "lng" : -0.1270060 },
{ "lat" : 51.5064490, "lng" : -0.1244260 },
{ "lat" : 51.5097080, "lng" : -0.1200450 },
{ "lat" : 51.5090680, "lng" : -0.1421420 },
{ "lat" : 51.4976080, "lng" : -0.1456320 },
{ "lat" : 51.5046150, "lng" : -0.1473780 },
]


Step7:

AndroidManifest.xml


Declare google play service in manifest.xml


<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="API Key" />

Map permission


<permission
android:name="com.google.maps.android.utils.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />

uses permission:


<uses-permission android:name="com.google.maps.android.utils.permission.MAPS_RECEIVE" />
<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" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />




Screenshot:




Devarajan M is a Software Engineer at Span Technology Services

7 comments:

  1. Hi can you send utility library as eclipse project? please any one help me.

    ReplyDelete
  2. The guide should not be used as an extensive look into Google AdWords and its capabilities, and the following guide does not guarantee sales.Edkent Media

    ReplyDelete
  3. By sifting through undesirable impressions, negative catchphrases can assist you with arriving at the most fitting possibilities, lessen your expense per-click (CPC), and increment your ROI.
    Google Ads Expert

    ReplyDelete
  4. A lot of people worked themselves into a lather over new privacy rules that Google rolled out at the beginning of this month. how to scratch email address from google

    ReplyDelete
  5. Out of so many features in Google Analytics, I think the ability to identify the Source / Medium to your website is one of the best website tools. Based on the data shown, you can find out if your marketing efforts have been paid off or not. This can provide a solid reference for your next decision making in enhancing your website performance.Lead generation website

    ReplyDelete