├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── thecodecity │ │ └── mapsdirection │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── thecodecity │ │ │ └── mapsdirection │ │ │ ├── MapActivity.java │ │ │ └── directionhelpers │ │ │ ├── DataParser.java │ │ │ ├── FetchURL.java │ │ │ ├── PointsParser.java │ │ │ └── TaskLoadedCallback.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── map_activity.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── thecodecity │ └── mapsdirection │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 1.8 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.thecodecity.mapsdirection" 7 | minSdkVersion 22 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:26.1.0' 24 | implementation 'com.google.android.gms:play-services-maps:11.0.2' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:0.5' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/thecodecity/mapsdirection/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.thecodecity.mapsdirection", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 14 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/thecodecity/mapsdirection/MapActivity.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.Button; 9 | 10 | import com.google.android.gms.maps.GoogleMap; 11 | import com.google.android.gms.maps.MapFragment; 12 | import com.google.android.gms.maps.OnMapReadyCallback; 13 | import com.google.android.gms.maps.model.LatLng; 14 | import com.google.android.gms.maps.model.Marker; 15 | import com.google.android.gms.maps.model.MarkerOptions; 16 | import com.google.android.gms.maps.model.Polyline; 17 | import com.google.android.gms.maps.model.PolylineOptions; 18 | import com.thecodecity.mapsdirection.directionhelpers.FetchURL; 19 | import com.thecodecity.mapsdirection.directionhelpers.TaskLoadedCallback; 20 | 21 | /** 22 | * Created by Vishal on 10/20/2018. 23 | */ 24 | 25 | public class MapActivity extends AppCompatActivity implements OnMapReadyCallback, TaskLoadedCallback { 26 | private GoogleMap mMap; 27 | private MarkerOptions place1, place2; 28 | Button getDirection; 29 | private Polyline currentPolyline; 30 | 31 | @Override 32 | protected void onCreate(@Nullable Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.map_activity); 35 | getDirection = findViewById(R.id.btnGetDirection); 36 | getDirection.setOnClickListener(new View.OnClickListener() { 37 | @Override 38 | public void onClick(View view) { 39 | new FetchURL(MapActivity.this).execute(getUrl(place1.getPosition(), place2.getPosition(), "driving"), "driving"); 40 | } 41 | }); 42 | //27.658143,85.3199503 43 | //27.667491,85.3208583 44 | place1 = new MarkerOptions().position(new LatLng(27.658143, 85.3199503)).title("Location 1"); 45 | place2 = new MarkerOptions().position(new LatLng(27.667491, 85.3208583)).title("Location 2"); 46 | MapFragment mapFragment = (MapFragment) getFragmentManager() 47 | .findFragmentById(R.id.mapNearBy); 48 | mapFragment.getMapAsync(this); 49 | } 50 | 51 | @Override 52 | public void onMapReady(GoogleMap googleMap) { 53 | mMap = googleMap; 54 | Log.d("mylog", "Added Markers"); 55 | mMap.addMarker(place1); 56 | mMap.addMarker(place2); 57 | } 58 | 59 | private String getUrl(LatLng origin, LatLng dest, String directionMode) { 60 | // Origin of route 61 | String str_origin = "origin=" + origin.latitude + "," + origin.longitude; 62 | // Destination of route 63 | String str_dest = "destination=" + dest.latitude + "," + dest.longitude; 64 | // Mode 65 | String mode = "mode=" + directionMode; 66 | // Building the parameters to the web service 67 | String parameters = str_origin + "&" + str_dest + "&" + mode; 68 | // Output format 69 | String output = "json"; 70 | // Building the url to the web service 71 | String url = "https://maps.googleapis.com/maps/api/directions/" + output + "?" + parameters + "&key=" + getString(R.string.google_maps_key); 72 | return url; 73 | } 74 | 75 | @Override 76 | public void onTaskDone(Object... values) { 77 | if (currentPolyline != null) 78 | currentPolyline.remove(); 79 | currentPolyline = mMap.addPolyline((PolylineOptions) values[0]); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/thecodecity/mapsdirection/directionhelpers/DataParser.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection.directionhelpers; 2 | 3 | import com.google.android.gms.maps.model.LatLng; 4 | 5 | import org.json.JSONArray; 6 | import org.json.JSONException; 7 | import org.json.JSONObject; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by Vishal on 10/20/2018. 15 | */ 16 | 17 | public class DataParser { 18 | public List>> parse(JSONObject jObject) { 19 | 20 | List>> routes = new ArrayList<>(); 21 | JSONArray jRoutes; 22 | JSONArray jLegs; 23 | JSONArray jSteps; 24 | try { 25 | jRoutes = jObject.getJSONArray("routes"); 26 | /** Traversing all routes */ 27 | for (int i = 0; i < jRoutes.length(); i++) { 28 | jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs"); 29 | List path = new ArrayList<>(); 30 | /** Traversing all legs */ 31 | for (int j = 0; j < jLegs.length(); j++) { 32 | jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps"); 33 | 34 | /** Traversing all steps */ 35 | for (int k = 0; k < jSteps.length(); k++) { 36 | String polyline = ""; 37 | polyline = (String) ((JSONObject) ((JSONObject) jSteps.get(k)).get("polyline")).get("points"); 38 | List list = decodePoly(polyline); 39 | 40 | /** Traversing all points */ 41 | for (int l = 0; l < list.size(); l++) { 42 | HashMap hm = new HashMap<>(); 43 | hm.put("lat", Double.toString((list.get(l)).latitude)); 44 | hm.put("lng", Double.toString((list.get(l)).longitude)); 45 | path.add(hm); 46 | } 47 | } 48 | routes.add(path); 49 | } 50 | } 51 | 52 | } catch (JSONException e) { 53 | e.printStackTrace(); 54 | } catch (Exception e) { 55 | } 56 | return routes; 57 | } 58 | 59 | 60 | /** 61 | * Method to decode polyline points 62 | * Courtesy : https://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java 63 | */ 64 | private List decodePoly(String encoded) { 65 | 66 | List poly = new ArrayList<>(); 67 | int index = 0, len = encoded.length(); 68 | int lat = 0, lng = 0; 69 | 70 | while (index < len) { 71 | int b, shift = 0, result = 0; 72 | do { 73 | b = encoded.charAt(index++) - 63; 74 | result |= (b & 0x1f) << shift; 75 | shift += 5; 76 | } while (b >= 0x20); 77 | int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 78 | lat += dlat; 79 | 80 | shift = 0; 81 | result = 0; 82 | do { 83 | b = encoded.charAt(index++) - 63; 84 | result |= (b & 0x1f) << shift; 85 | shift += 5; 86 | } while (b >= 0x20); 87 | int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 88 | lng += dlng; 89 | 90 | LatLng p = new LatLng((((double) lat / 1E5)), 91 | (((double) lng / 1E5))); 92 | poly.add(p); 93 | } 94 | 95 | return poly; 96 | } 97 | } -------------------------------------------------------------------------------- /app/src/main/java/com/thecodecity/mapsdirection/directionhelpers/FetchURL.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection.directionhelpers; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.InputStreamReader; 11 | import java.net.HttpURLConnection; 12 | import java.net.URL; 13 | 14 | /** 15 | * Created by Vishal on 10/20/2018. 16 | */ 17 | 18 | public class FetchURL extends AsyncTask { 19 | Context mContext; 20 | String directionMode = "driving"; 21 | 22 | public FetchURL(Context mContext) { 23 | this.mContext = mContext; 24 | } 25 | 26 | @Override 27 | protected String doInBackground(String... strings) { 28 | // For storing data from web service 29 | String data = ""; 30 | directionMode = strings[1]; 31 | try { 32 | // Fetching the data from web service 33 | data = downloadUrl(strings[0]); 34 | Log.d("mylog", "Background task data " + data.toString()); 35 | } catch (Exception e) { 36 | Log.d("Background Task", e.toString()); 37 | } 38 | return data; 39 | } 40 | 41 | @Override 42 | protected void onPostExecute(String s) { 43 | super.onPostExecute(s); 44 | PointsParser parserTask = new PointsParser(mContext, directionMode); 45 | // Invokes the thread for parsing the JSON data 46 | parserTask.execute(s); 47 | } 48 | 49 | private String downloadUrl(String strUrl) throws IOException { 50 | String data = ""; 51 | InputStream iStream = null; 52 | HttpURLConnection urlConnection = null; 53 | try { 54 | URL url = new URL(strUrl); 55 | // Creating an http connection to communicate with url 56 | urlConnection = (HttpURLConnection) url.openConnection(); 57 | // Connecting to url 58 | urlConnection.connect(); 59 | // Reading data from url 60 | iStream = urlConnection.getInputStream(); 61 | BufferedReader br = new BufferedReader(new InputStreamReader(iStream)); 62 | StringBuffer sb = new StringBuffer(); 63 | String line = ""; 64 | while ((line = br.readLine()) != null) { 65 | sb.append(line); 66 | } 67 | data = sb.toString(); 68 | Log.d("mylog", "Downloaded URL: " + data.toString()); 69 | br.close(); 70 | } catch (Exception e) { 71 | Log.d("mylog", "Exception downloading URL: " + e.toString()); 72 | } finally { 73 | iStream.close(); 74 | urlConnection.disconnect(); 75 | } 76 | return data; 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/thecodecity/mapsdirection/directionhelpers/PointsParser.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection.directionhelpers; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.AsyncTask; 6 | import android.util.Log; 7 | 8 | import com.google.android.gms.maps.model.LatLng; 9 | import com.google.android.gms.maps.model.PolylineOptions; 10 | 11 | import org.json.JSONObject; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by Vishal on 10/20/2018. 19 | */ 20 | 21 | public class PointsParser extends AsyncTask>>> { 22 | TaskLoadedCallback taskCallback; 23 | String directionMode = "driving"; 24 | 25 | public PointsParser(Context mContext, String directionMode) { 26 | this.taskCallback = (TaskLoadedCallback) mContext; 27 | this.directionMode = directionMode; 28 | } 29 | 30 | // Parsing the data in non-ui thread 31 | @Override 32 | protected List>> doInBackground(String... jsonData) { 33 | 34 | JSONObject jObject; 35 | List>> routes = null; 36 | 37 | try { 38 | jObject = new JSONObject(jsonData[0]); 39 | Log.d("mylog", jsonData[0].toString()); 40 | DataParser parser = new DataParser(); 41 | Log.d("mylog", parser.toString()); 42 | 43 | // Starts parsing data 44 | routes = parser.parse(jObject); 45 | Log.d("mylog", "Executing routes"); 46 | Log.d("mylog", routes.toString()); 47 | 48 | } catch (Exception e) { 49 | Log.d("mylog", e.toString()); 50 | e.printStackTrace(); 51 | } 52 | return routes; 53 | } 54 | 55 | // Executes in UI thread, after the parsing process 56 | @Override 57 | protected void onPostExecute(List>> result) { 58 | ArrayList points; 59 | PolylineOptions lineOptions = null; 60 | // Traversing through all the routes 61 | for (int i = 0; i < result.size(); i++) { 62 | points = new ArrayList<>(); 63 | lineOptions = new PolylineOptions(); 64 | // Fetching i-th route 65 | List> path = result.get(i); 66 | // Fetching all the points in i-th route 67 | for (int j = 0; j < path.size(); j++) { 68 | HashMap point = path.get(j); 69 | double lat = Double.parseDouble(point.get("lat")); 70 | double lng = Double.parseDouble(point.get("lng")); 71 | LatLng position = new LatLng(lat, lng); 72 | points.add(position); 73 | } 74 | // Adding all the points in the route to LineOptions 75 | lineOptions.addAll(points); 76 | if (directionMode.equalsIgnoreCase("walking")) { 77 | lineOptions.width(10); 78 | lineOptions.color(Color.MAGENTA); 79 | } else { 80 | lineOptions.width(20); 81 | lineOptions.color(Color.BLUE); 82 | } 83 | Log.d("mylog", "onPostExecute lineoptions decoded"); 84 | } 85 | 86 | // Drawing polyline in the Google Map for the i-th route 87 | if (lineOptions != null) { 88 | //mMap.addPolyline(lineOptions); 89 | taskCallback.onTaskDone(lineOptions); 90 | 91 | } else { 92 | Log.d("mylog", "without Polylines drawn"); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/thecodecity/mapsdirection/directionhelpers/TaskLoadedCallback.java: -------------------------------------------------------------------------------- 1 | package com.thecodecity.mapsdirection.directionhelpers; 2 | 3 | /** 4 | * Created by Vishal on 10/20/2018. 5 | */ 6 | 7 | public interface TaskLoadedCallback { 8 | void onTaskDone(Object... values); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/map_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 |