package com.cs3370.android.whereisderek; import android.Manifest; import android.annotation.SuppressLint; import android.content.pm.PackageManager; import android.graphics.Color; import android.location.Location; import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.util.Log; import android.widget.Toast; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationCallback; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationResult; import com.google.android.gms.location.LocationServices; 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.OnMapReadyCallback; 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; import com.google.android.gms.maps.model.PolylineOptions; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class MapsActivity extends FragmentActivity implements OnMapReadyCallback { private final int REQUEST_LOCATION_PERMISSIONS = 0; private GoogleMap mMap; private static final int LOCATION_REQUEST = 500; ArrayList listPoints; private FusedLocationProviderClient mClient; private LocationRequest mLocationRequest; private LocationCallback mLocationCallback; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); // Obtain the SupportMapFragment and get notified when the map is ready to be used. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this); listPoints = new ArrayList<>(); // Create location request mLocationRequest = new LocationRequest(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Create location callback mLocationCallback = new LocationCallback() { @Override public void onLocationResult(LocationResult locationResult) { if (locationResult != null) { for (Location location : locationResult.getLocations()) { updateMap(location); } } } }; mClient = LocationServices.getFusedLocationProviderClient(this); } /** * Manipulates the map once available. * This callback is triggered when the map is ready to be used. * This is where we can add markers or lines, add listeners or move the camera. In this case, * we just add a marker near Sydney, Australia. * If Google Play services is not installed on the device, the user will be prompted to install * it inside the SupportMapFragment. This method will only be triggered once the user has * installed Google Play services and returned to the app. */ private void updateMap(Location location){ LatLng curLoc = new LatLng(location.getLatitude(), location.getLongitude()); listPoints.add(curLoc); MarkerOptions markerOptions = new MarkerOptions(); markerOptions.position(curLoc); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)); mMap.addMarker(markerOptions); LatLng derekLoc = new LatLng(47.478950, -94.834060); listPoints.add(derekLoc); markerOptions = new MarkerOptions(); markerOptions.position(derekLoc); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)); mMap.addMarker(markerOptions); Log.d("list", "" + listPoints); if(listPoints.size() >= 2) { //Create the URL to get request from first marker to second marker String url = getRequestUrl(listPoints.get(0), listPoints.get(1)); Log.d("url", "" + url); TaskRequestDirections taskRequestDirections = new TaskRequestDirections(); taskRequestDirections.execute(url); } } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; mMap.getUiSettings().setZoomControlsEnabled(true); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST); return; } mMap.setMyLocationEnabled(true); } private String getRequestUrl(LatLng origin, LatLng dest) { //Value of origin String str_origin = "origin=" + origin.latitude + "," + origin.longitude; //Value of destination String str_dest = "destination=" + dest.latitude + "," + dest.longitude; //Set value enable the sensor String sensor = "sensor=false"; //Mode for find direction String mode; if (distance(origin.latitude, dest.latitude, origin.longitude, dest.longitude, 0, 0) > 1609) { mode = "mode=driving"; }else { mode = "mode=walking"; } //Build the full param String param = str_origin + "&" + str_dest + "&" + sensor + "&" + mode; //Output format String output = "json"; //api key String apiKey = "&key=AIzaSyA2ge3xTYUPagFuMb5cWtR2Sk5aoNMDir0"; //Create url to request String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + param + apiKey; return url; } public static double distance(double lat1, double lat2, double lon1, double lon2, double el1, double el2) { final int R = 6371; // Radius of the earth double latDistance = Math.toRadians(lat2 - lat1); double lonDistance = Math.toRadians(lon2 - lon1); double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); double distance = R * c * 1000; // convert to meters double height = el1 - el2; distance = Math.pow(distance, 2) + Math.pow(height, 2); return Math.sqrt(distance); } private String requestDirection(String reqUrl) throws IOException { String responseString = ""; InputStream inputStream = null; HttpURLConnection httpURLConnections = null; try { URL url = new URL(reqUrl); httpURLConnections = (HttpURLConnection) url.openConnection(); httpURLConnections.connect(); //Get the response result inputStream = httpURLConnections.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); StringBuffer stringBuffer = new StringBuffer(); String line = ""; while ((line = bufferedReader.readLine()) != null) { stringBuffer.append(line); } responseString = stringBuffer.toString(); bufferedReader.close(); inputStreamReader.close(); }catch (Exception e) { e.printStackTrace(); }finally { if (inputStream != null) { inputStream.close(); } httpURLConnections.disconnect(); } return responseString; } @SuppressLint("MissingPermission") @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case LOCATION_REQUEST: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mMap.setMyLocationEnabled(true); } break; } } @Override public void onPause() { super.onPause(); mClient.removeLocationUpdates(mLocationCallback); } @SuppressLint("MissingPermission") @Override public void onResume() { super.onResume(); if (hasLocationPermission()) { mClient.requestLocationUpdates(mLocationRequest, mLocationCallback, null); } } private boolean hasLocationPermission() { // Request fine location permission if not already granted if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, REQUEST_LOCATION_PERMISSIONS); return false; } return true; } public class TaskRequestDirections extends AsyncTask { @Override protected String doInBackground(String...strings) { String responseString = ""; try { responseString = requestDirection(strings[0]); }catch (IOException e) { Log.d("exc", "exception caught"); e.printStackTrace(); } return responseString; } @Override protected void onPostExecute(String s) { Log.d("what", "is s " + s); super.onPostExecute(s); //Parse json here TaskParser taskParser = new TaskParser(); taskParser.execute(s); } } public class TaskParser extends AsyncTask>>> { @Override protected List>> doInBackground(String...strings) { JSONObject jsonObject = null; List>> routes = null; try { jsonObject = new JSONObject(strings[0]); DirectionsParser directionsParser = new DirectionsParser(); routes = directionsParser.parse(jsonObject); }catch (JSONException e) { e.printStackTrace(); } return routes; } @Override protected void onPostExecute(List>> lists) { //Get list route and display it into the map Log.d("lists", "here it is " + lists); ArrayList points = null; PolylineOptions polylineOptions = null; for(List> path : lists) { points = new ArrayList(); polylineOptions = new PolylineOptions(); for (HashMap point : path) { double lat = Double.parseDouble(point.get("lat")); double lng = Double.parseDouble(point.get("lng")); points.add(new LatLng(lat, lng)); } polylineOptions.addAll(points); polylineOptions.width(15); polylineOptions.color(Color.BLUE); polylineOptions.geodesic(true); } if (polylineOptions != null) { mMap.addPolyline(polylineOptions); }else { Log.d("hey", "is this on"); Toast.makeText(getApplicationContext(), "Direction not found", Toast.LENGTH_SHORT).show(); } } } }