package edu.purdue.app.map;
import java.util.List;
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.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;
import android.app.Fragment;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;
import edu.purdue.app.R;
public class GoogleMapFragment extends MapFragment {
private GMapFragmentLoadedListener listener;
/** Listener for when the google map is fully loaded */
public interface GMapFragmentLoadedListener {
void onGMapLoaded();
}
/** Creates the view for the fragment. We just let MapFragment do everything here. */
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
/** Called after onCreateView and onCreate when the activity has been fully instantiated. */
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Alert the listener that the gmap is loaded
if (listener != null) {
listener.onGMapLoaded();
}
}
/** Sets the listener for when the map is fully loaded. */
public void setGMapFragmentLoadedListener(GMapFragmentLoadedListener l) {
this.listener = l;
}
/** Adds a pin to the map and animates the camera to gracefully show that pin.
* @param toLoc The location of the pin you'd like to add
* @param label A label to include on the pin
* @param direction Pass true if you'd like to include a directions polyline to the location. */
public void addPinToMap(LatLng toLoc, String label, boolean directions) {
// Clear the map
GoogleMap gmap = getMap();
gmap.clear();
// Add the marker to the map
gmap.addMarker(new MarkerOptions()
.title(label)
.position(toLoc));
// If we want directions, get the polyline for the directions and put it on the map
// This is done on its own thread, so it will be put on the map whenever the thread is done executing
if (directions) {
addDirectionsToMap(toLoc);
}
// The layout bounds are set to include two LatLng points:
// The location of the user and the latlng of the point they selected
if (gmap.getMyLocation() != null) {
LatLng myloc = new LatLng(gmap.getMyLocation().getLatitude(), gmap.getMyLocation().getLongitude());
if (MapData.isNearPurdue(myloc.latitude, myloc.longitude)) {
Point p = new Point();
getActivity().getWindowManager().getDefaultDisplay().getSize(p);
LatLngBounds.Builder builder = LatLngBounds.builder();
builder.include(toLoc);
builder.include(myloc);
gmap.animateCamera(CameraUpdateFactory.newLatLngBounds(
builder.build(), p.x, p.y, 175));
} else {
// User is not near purdue, so only include the point selected
gmap.animateCamera(CameraUpdateFactory.newLatLngZoom(toLoc, MapData.PURDUE_CAMPUS_ZOOM + 0.5f));
}
} else {
// GPS is not available, so fall back to simpler functionality
gmap.animateCamera(CameraUpdateFactory.newLatLngZoom(toLoc, MapData.PURDUE_CAMPUS_ZOOM));
}
}
/** Synchronously adds a directions polyline to the gmap between the user's current location
* and toLoc. The directions are downloaded from the internet, so they are done synchronously and
* will appear on the map whenever they're done downloading.
* @param toLoc The destination point of the directions polyline */
private void addDirectionsToMap(final LatLng toLoc) {
// If GPS is not enabled, just return
final GoogleMap gmap = getMap();
if (gmap.getMyLocation() == null) {
return;
}
// gmap can only be accessed on the main UI thread, so get the user's current location here
final LatLng myLoc = new LatLng(gmap.getMyLocation().getLatitude(), gmap.getMyLocation().getLongitude());
// Check if they're connected to the internet. If so, then execute the thread to download walking data
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isNetworkAvailable = cm.getActiveNetworkInfo() != null;
if (isNetworkAvailable && cm.getActiveNetworkInfo().isConnected()) {
// Execute the thread
new Thread(new Runnable() {
public void run() {
// Download the directions and create an array of latlng points
GoogleMapDirections gmd = new GoogleMapDirections();
List<LatLng> dirPoints = gmd.getDirection(gmd.getDocument(myLoc, toLoc, GoogleMapDirections.MODE_WALKING));
final PolylineOptions line = new PolylineOptions().width(3).color(Color.RED);
for (LatLng point : dirPoints) {
line.add(point);
}
// Gmap is on the UI thread so we have to post it using a handler
Handler mainHandler = new Handler(getActivity().getMainLooper());
mainHandler.post(new Runnable() {
public void run() {
gmap.addPolyline(line);
}
});
}
}).start();
}
}
/** Adds a polyline to the map representing a route of latlng points */
public void addRouteToMap(List<LatLng> route) {
PolylineOptions line = new PolylineOptions().width(4).color(Color.GREEN);
for (LatLng point : route) {
line.add(point);
}
getMap().addPolyline(line);
}
}