package ox.augmented; import org.w3c.dom.Document; import android.content.Intent; import android.graphics.Color; import android.location.Location; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import app.akexorcist.gdaplibrary.GoogleDirection; import app.akexorcist.gdaplibrary.GoogleDirection.OnDirectionResponseListener; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks; import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener; import com.google.android.gms.location.LocationClient; import com.google.android.gms.location.LocationListener; import com.google.android.gms.location.LocationRequest; 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.MarkerOptions; /** * * Uses Android-GoogleDirectionAndPlaceLibrary <br> * Source: https://github.com/akexorcist/Android-GoogleDirectionAndPlaceLibrary * */ public class MapActivity extends FragmentActivity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener{ private double[] lats; private double[] longs; private String[] names; private int current; private GoogleMap map; private GoogleDirection gd; private Document mDoc; private LocationClient mLocationClient; private Button buttonRefreshRoute; private Button buttonDisplayRoute; private Button buttonAnimateRoute; private boolean displayingRoute = true; private LatLng myPosition =new LatLng(0,0);//won't actually be displayed as (0,0). Will be changed as soon as onLocationChanged is called. More efficient than setting to null and checking whether it has received data. private long lastTimeMapUpdated=0; private static final double MAX_DISTANCE = 30000;//30km . In meters. Crashes for long distances, e.g. Oxford-Bangalor private static final int MIN_REFRESH_PERIOD = 30000;//30s. In millisecond. Will request for new data automaticly only if MIN_REFRESH_PERIOD time has passed since the last update. @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); Intent intent = getIntent(); lats = intent.getDoubleArrayExtra("LATS"); longs = intent.getDoubleArrayExtra("LONGS"); names = intent.getStringArrayExtra("NAMES"); current = intent.getIntExtra("CURRENT", 0); gd = new GoogleDirection(this); gd.setOnDirectionResponseListener(new OnDirectionResponseListener() { public void onResponse(String status, Document doc, GoogleDirection gd) { mDoc = doc; map.addPolyline(gd.getPolyline(doc, 3, Color.RED)); } }); buttonRefreshRoute = (Button)findViewById(R.id.refreshRoute); buttonRefreshRoute.setOnClickListener(new OnClickListener() { public void onClick(View v) { redrawAllOnMap(); lastTimeMapUpdated = System.currentTimeMillis(); } }); buttonDisplayRoute = (Button)findViewById(R.id.displayRoute); buttonDisplayRoute.setOnClickListener(new OnClickListener() { public void onClick(View v) { displayingRoute = !(displayingRoute); redrawAllOnMap(); lastTimeMapUpdated = System.currentTimeMillis(); } }); buttonAnimateRoute = (Button)findViewById(R.id.animateRoute); buttonAnimateRoute.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (gd!=null && mDoc!=null){ gd.animateDirection(map, gd.getDirection(mDoc), GoogleDirection.SPEED_NORMAL , true, false, true, false, null, false, true, null); } else if (gd==null) Log.d("MapActivity", "gd==null"); else if (mDoc==null) Log.d("MapActivity", "mDoc==null"); } }); mapSetup(); drawRouteOnMap(); } private void mapSetup() { //map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); map = ((SupportMapFragment)getSupportFragmentManager() .findFragmentById(R.id.map)).getMap(); map.setMyLocationEnabled(true); poisSetup(); LatLng l = new LatLng(lats[current], longs[current]); map.moveCamera(CameraUpdateFactory.newLatLngZoom(l,16)); } private void poisSetup(){ for(int i = 0; i < names.length; i++){ Float hue = i < current ? BitmapDescriptorFactory.HUE_BLUE : i > current ? BitmapDescriptorFactory.HUE_MAGENTA : BitmapDescriptorFactory.HUE_GREEN; map.addMarker(new MarkerOptions() .position(new LatLng(lats[i], longs[i])) .title(names[i]) .icon(BitmapDescriptorFactory.defaultMarker(hue))); } } private void drawRouteOnMap(){ LatLng destPosition = new LatLng(lats[current], longs[current]); try { if (distance(myPosition.latitude, myPosition.longitude, destPosition.latitude, destPosition.longitude)<=MAX_DISTANCE){ gd.setLogging(true); gd.request(myPosition, destPosition, GoogleDirection.MODE_WALKING); } } catch(NullPointerException e){ e.printStackTrace(); } } private static final LocationRequest REQUEST = LocationRequest.create() .setInterval(5000) // 5 seconds .setFastestInterval(16) // 16ms = 60fps .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); @Override public void onLocationChanged(Location arg0) { long currentTime = System.currentTimeMillis(); if (currentTime-lastTimeMapUpdated>MIN_REFRESH_PERIOD){ //30 sec Location myLocation = mLocationClient.getLastLocation(); myPosition = new LatLng(myLocation.getLatitude(), myLocation.getLongitude()); redrawAllOnMap(); lastTimeMapUpdated=currentTime; } } @Override public void onConnectionFailed(ConnectionResult arg0) { // Do nothing } @Override public void onConnected(Bundle arg0) { mLocationClient.requestLocationUpdates( REQUEST, this); // LocationListener } @Override public void onDisconnected() { // Do Nothing } protected void onResume(){ super.onResume(); if (map==null) mapSetup(); setUpLocationClientIfNeeded(); mLocationClient.connect(); } public void onPause() { super.onPause(); if (mLocationClient != null) { mLocationClient.disconnect(); } } private void setUpLocationClientIfNeeded() { if (mLocationClient == null) { mLocationClient = new LocationClient( getApplicationContext(), this, // ConnectionCallbacks this); // OnConnectionFailedListener } } //possible only while no animation is running private void redrawAllOnMap(){ if (!gd.isAnimated()){ map.clear(); poisSetup(); if (displayingRoute) drawRouteOnMap(); } } public double distance (double lat_a, double lng_a, double lat_b, double lng_b ) { double earthRadius = 3958.75; double latDiff = Math.toRadians(lat_b-lat_a); double lngDiff = Math.toRadians(lng_b-lng_a); double a = Math.sin(latDiff /2) * Math.sin(latDiff /2) + Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) * Math.sin(lngDiff /2) * Math.sin(lngDiff /2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); double distance = earthRadius * c; int meterConversion = 1609; return Double.valueOf(distance * meterConversion); } }