SlideShare a Scribd company logo
1 of 12
Download to read offline
Creating an Uber Clone - Part XVIII
We can now move forward to the last two pieces of the SearchService class
public static void suggestLocations(String input, Location l,
SuccessCallback<List<SuggestionResult>> resultList) {
if(lastSuggestionRequest != null) {
if(lastSuggestionValue.equals(input)) {
return;
}
lastSuggestionRequest.kill();
}
List<SuggestionResult> lr = locationCache.get(input);
if(lr != null) {
lastSuggestionValue = null;
lastSuggestionRequest = null;
callSerially(() -> resultList.onSucess(lr));
return;
}
lastSuggestionValue = input;
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
SearchService
If the last request is this request which can happen as a user types and deletes etc. then we don't want to do anything... Let the last request finish
public static void suggestLocations(String input, Location l,
SuccessCallback<List<SuggestionResult>> resultList) {
if(lastSuggestionRequest != null) {
if(lastSuggestionValue.equals(input)) {
return;
}
lastSuggestionRequest.kill();
}
List<SuggestionResult> lr = locationCache.get(input);
if(lr != null) {
lastSuggestionValue = null;
lastSuggestionRequest = null;
callSerially(() -> resultList.onSucess(lr));
return;
}
lastSuggestionValue = input;
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
SearchService
However, if it isn't then we want to kill the last request which might still be queued and blocking us from going forward
public static void suggestLocations(String input, Location l,
SuccessCallback<List<SuggestionResult>> resultList) {
if(lastSuggestionRequest != null) {
if(lastSuggestionValue.equals(input)) {
return;
}
lastSuggestionRequest.kill();
}
List<SuggestionResult> lr = locationCache.get(input);
if(lr != null) {
lastSuggestionValue = null;
lastSuggestionRequest = null;
callSerially(() -> resultList.onSucess(lr));
return;
}
lastSuggestionValue = input;
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
SearchService
We check if an entry is already in the cache as users might type and revise a lot thus triggering significant webservice cost overhead
public static void suggestLocations(String input, Location l,
SuccessCallback<List<SuggestionResult>> resultList) {
if(lastSuggestionRequest != null) {
if(lastSuggestionValue.equals(input)) {
return;
}
lastSuggestionRequest.kill();
}
List<SuggestionResult> lr = locationCache.get(input);
if(lr != null) {
lastSuggestionValue = null;
lastSuggestionRequest = null;
callSerially(() -> resultList.onSucess(lr));
return;
}
lastSuggestionValue = input;
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
SearchService
We clean the variable values and then invoke the response. Notice I use callSerially in this case to defer the response to the next cycle. If we call back immediately we
might delay the input code which is currently in place. By shifting the callback to the next EDT cycle we guarantee that suggestLocations will behave in a similar way
whether the data is cached locally or not
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
getAsJsonMap(callbackMap -> {
Map data = callbackMap.getResponseData();
if(data != null) {
List<Map> results = (List<Map>)data.get("predictions");
if(results != null && results.size() > 0) {
ArrayList<SuggestionResult> resultSet = new ArrayList<>();
for(Map currentResult : results) {
Map structured_formatting = (Map)
currentResult.get("structured_formatting");
String mainText = (String)
structured_formatting.get("main_text");
String secondaryText = (String)
structured_formatting.get("secondary_text");
String description = (String)
currentResult.get("description");
String placeId = (String)currentResult.get("place_id");
resultSet.add(new SuggestionResult(mainText,
secondaryText, description, placeId));
}
SearchService
The request extracts the predictions array so we can construct the result list
lastSuggestionRequest = Rest.
get("https://maps.googleapis.com/maps/api/place/autocomplete/json").
queryParam("input", input).
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
getAsJsonMap(callbackMap -> {
Map data = callbackMap.getResponseData();
if(data != null) {
List<Map> results = (List<Map>)data.get("predictions");
if(results != null && results.size() > 0) {
ArrayList<SuggestionResult> resultSet = new ArrayList<>();
for(Map currentResult : results) {
Map structured_formatting = (Map)
currentResult.get("structured_formatting");
String mainText = (String)
structured_formatting.get("main_text");
String secondaryText = (String)
structured_formatting.get("secondary_text");
String description = (String)
currentResult.get("description");
String placeId = (String)currentResult.get("place_id");
resultSet.add(new SuggestionResult(mainText,
secondaryText, description, placeId));
}
SearchService
We iterate over the entries, notice I discard the generic context which is legal in Java but might produce a warning. I could have used a more elaborate syntax that would
have removed the warning but that would have created more verbose code with no actual benefit
queryParam("location", l.getLatitude() + "," + l.getLongitude()).
queryParam("radius", "50000").
queryParam("key", GOOGLE_PLACES_KEY).
getAsJsonMap(callbackMap -> {
Map data = callbackMap.getResponseData();
if(data != null) {
List<Map> results = (List<Map>)data.get("predictions");
if(results != null && results.size() > 0) {
ArrayList<SuggestionResult> resultSet = new ArrayList<>();
for(Map currentResult : results) {
Map structured_formatting = (Map)
currentResult.get("structured_formatting");
String mainText = (String)
structured_formatting.get("main_text");
String secondaryText = (String)
structured_formatting.get("secondary_text");
String description = (String)
currentResult.get("description");
String placeId = (String)currentResult.get("place_id");
resultSet.add(new SuggestionResult(mainText,
secondaryText, description, placeId));
}
locationCache.put(input, resultSet);
resultList.onSucess(resultSet);
}
SearchService
I extract the elements from the map and create the SuggestionResult entries then store the whole thing in cache followed by the onSuccess call. Notice that in this case I
didn't need the callSerially since the response is already asynchronous
https://maps.googleapis.com/maps/api/directions/json?
origin=Toronto&destination=Montreal&key=API_KEY
Directions API
The final webservice API we will cover is the directions API which will allows us to set the path taken by the car on the map. The directions API is challenging. It returns
encoded data in a problematic format.

This is the sample query from Google. Notice we can give the origin and destinations values as a longitude latitude pair which is what we’ll actually do.
{
"geocoded_waypoints" : [
... trimmed ...
],
"routes" : [
{
"bounds" : {
... trimmed ...
},
"legs" : [
{
"distance" : {
... trimmed ...
},
"duration" : {
... trimmed ...
},
... trimmed ...
"steps" : [
{
... trimmed ...
}
}
... trimmed ...
],
"overview_polyline" : {
"points" : "e`miGhmocNiI`CeFmHaAmIgDai@mNiw@qJqq@{GyFwBp@ag@fLoVpRcr@vI}d@oIg[ePa`@ax@kC_w@mV}h@af@iPa]y_@mq@xZehFje@{r@jCeDgf@}AgfBs]kiCmrAkuJog@gxAoo|
DoIm_CdX_{A_Gcb@ad@aw@mnB_pDe_D}rIcnBa_NmRuyBvBcmBnAydC_{Bu_Oe@ktBdt@qiBhL}w@eSylD}i@coIi_AcxCm[maDga@__IsiAuiJmbEyzZagBwvMkSypEkT_~C_cAk_H|Y{fB_P{qC}l@q_C{S_i@yA}
dAwj@mkB{^}jCbVi|DzUqoAkjA_`Lku@g_Lye_Dud@ilDwh@ufBeh@}hBgT{jAkm@wv@mm@s}DcMw`A_z@ifAeU{w@kRuaCieAsrEiw@uvAku@{vDez@_kCgCyqAoB}gBwXkw@om@q}AweBizEamAs`DuSwfA}
e@ctC_iAukH}hBqsKc|@_iDowAyrJ_B_v@lY}eBgEajByh@skH{`Dkzc@k]_vCeu@yuCyF_uAgBe_Bsa@mxBaDmfCiTasFmMqcJw]sgRsVaeScNggBxdA_tDdw@gxGr@kuAy[w{@qj@_iCi|
@orEyd@o`Aaj@yn@knAsvDmn@msJmm@kvOal@o~Cmf@{cGjJazDcp@w_EgxAw~EcnA_}E^y`E}f@swDoPmt@wn@ofAuc@gtAmu@mvAiu@{{@km@qrAgd@}j@ie@_RuoBwr@svBi`BcmB_kB}sBmzBqc@kz@sTihBjGkpA}
@gc@eo@kgBeVuPuoA`C_g@uPol@_|@_dA}`BgeAgd@s^}a@_w@isBidAi~AytAyvBihB_fDmvAojB_zIkaL{t@sdAuWirAgZonAohDuzFyaAkbBon@_k@spAi|@}aHgoMi{EqiJw`Di}H{uDuiMc|EytOevAe~D}|
@gQcTiQczBonHesAcrE}~Eo|PwqAalF{_@gmCyAcq@`TqbAzw@atCzLsrAbBehGkFmoAa}jAc]qqAiCmoBaMajDeSowAsdCyeIy`FmqMsrAigDwi@ir@ch@s~Auz@cvC}vBcvHeSgl@e_@oTq`AcxBkfBsaEwt@u}
CizDevJwfA}bDsqA_bBinCgvD{{HwqVwyA_`Ckc@sg@_i@ymAaXkp@mEo`Bej@}_DebA{aAeYay@eiBc|Ho`@mrE}aAueGun@gpDpIy{GaFg~@lB}rEdD_rDv]klBwAqk@aY_t@{lAmwCsdAshBkaO_x@}
bAuv@ipAmLeZqIcBeKLqIpIqEkF"
},
"summary" : "ON-401 E",
"warnings" : [],
"waypoint_order" : []
}
],
"status" : "OK"
Directions API
The response is a bit large so I trimmed a lot of it to give you a sense of what we are looking for. 

The one thing that matters to us from the response is the overview_polyline entry which seems like a bunch of gibberish but it isn't. This is a special notation from Google
that encodes the latitude/longitude values of the entire trip in a single string. This encoding is described by Google in their map documentation
// Based on https://github.com/scoutant/polyline-decoder/
private static List<Coord> decodePolyline(String str) {
ArrayList<Coord> resultPath = new ArrayList<>();
int index = 0;
int lat = 0, lng = 0;
while (index < str.length()) {
int b, shift = 0, result = 0;
do {
b = str.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = str.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
Coord p = new Coord((double) lat / 1E5, (double) lng / 1E5);
resultPath.add(p);
}
return resultPath;
}
Polyline Decoder
Being lazy I found someone who already implemented the algorithm in Java and his code worked "as is”. I won't go into the code since it's mostly just bitwise shifting to
satisfy the requirements from Google. The method signature is the only thing that matters. It takes an encoded String and returns the path matching that string as a list of
coordinates that we will be able to add into the map shortly.
public static void directions(Location l, Location destination, DirectionResults response) {
Rest.get("https://maps.googleapis.com/maps/api/directions/json").
queryParam("origin", l.getLatitude() + "," + l.getLongitude()).
queryParam("destination", destination.getLatitude() + "," + destination.getLongitude()).
queryParam("mode", "driving").
queryParam("key", GOOGLE_DIRECTIONS_KEY).
getAsJsonMap(callbackMap -> {
Map data = callbackMap.getResponseData();
if(data != null) {
List results = (List)data.get("routes");
if(results != null && results.size() > 0) {
Map firstResult = (Map)results.get(0);
Map overview_polyline = (Map)firstResult.get("overview_polyline");
List<Coord> polyline = decodePolyline((String)
overview_polyline.get("points"));
List legs = (List)firstResult.get("legs");
Map firstLeg = (Map)legs.get(0);
Map distance = (Map)firstLeg.get("distance");
Map duration = (Map)firstLeg.get("duration");
response.onDirectionResult(polyline,
Util.toIntValue(duration.get("value")),
(String)distance.get("text"));
}
}
});
}
DirectionResults
Now that this is all out of the way the directions method is relatively simple. This method is just another REST call that doesn't include anything out of the ordinary. We
extract the overview_polyline value and pass it to the callback response.

More Related Content

Similar to Creating an Uber Clone - Part XVIII - Transcript.pdf

Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner codeMite Mitreski
 
When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)Sylvain Hallé
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman500Tech
 
Creating a Facebook Clone - Part XXVII.pdf
Creating a Facebook Clone - Part XXVII.pdfCreating a Facebook Clone - Part XXVII.pdf
Creating a Facebook Clone - Part XXVII.pdfShaiAlmog1
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applicationsSteve Smith
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page ApplicationsSteve Smith
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015NAVER / MusicPlatform
 
You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017名辰 洪
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScriptkvangork
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascriptkvangork
 
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxassignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxssuser562afc1
 
Creating an Uber Clone - Part XV.pdf
Creating an Uber Clone - Part XV.pdfCreating an Uber Clone - Part XV.pdf
Creating an Uber Clone - Part XV.pdfShaiAlmog1
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScriptLuis Atencio
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montageKris Kowal
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxEleanor McHugh
 

Similar to Creating an Uber Clone - Part XVIII - Transcript.pdf (20)

Google Guava for cleaner code
Google Guava for cleaner codeGoogle Guava for cleaner code
Google Guava for cleaner code
 
When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)When RV Meets CEP (RV 2016 Tutorial)
When RV Meets CEP (RV 2016 Tutorial)
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman
 
Creating a Facebook Clone - Part XXVII.pdf
Creating a Facebook Clone - Part XXVII.pdfCreating a Facebook Clone - Part XXVII.pdf
Creating a Facebook Clone - Part XXVII.pdf
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
서버 개발자가 바라 본 Functional Reactive Programming with RxJava - SpringCamp2015
 
You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
 
Object-Oriented JavaScript
Object-Oriented JavaScriptObject-Oriented JavaScript
Object-Oriented JavaScript
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxassignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
 
Creating an Uber Clone - Part XV.pdf
Creating an Uber Clone - Part XV.pdfCreating an Uber Clone - Part XV.pdf
Creating an Uber Clone - Part XV.pdf
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
 
Angular2 rxjs
Angular2 rxjsAngular2 rxjs
Angular2 rxjs
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Bindings: the zen of montage
Bindings: the zen of montageBindings: the zen of montage
Bindings: the zen of montage
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfShaiAlmog1
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 

Recently uploaded

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 

Recently uploaded (20)

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 

Creating an Uber Clone - Part XVIII - Transcript.pdf

  • 1. Creating an Uber Clone - Part XVIII We can now move forward to the last two pieces of the SearchService class
  • 2. public static void suggestLocations(String input, Location l, SuccessCallback<List<SuggestionResult>> resultList) { if(lastSuggestionRequest != null) { if(lastSuggestionValue.equals(input)) { return; } lastSuggestionRequest.kill(); } List<SuggestionResult> lr = locationCache.get(input); if(lr != null) { lastSuggestionValue = null; lastSuggestionRequest = null; callSerially(() -> resultList.onSucess(lr)); return; } lastSuggestionValue = input; lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). SearchService If the last request is this request which can happen as a user types and deletes etc. then we don't want to do anything... Let the last request finish
  • 3. public static void suggestLocations(String input, Location l, SuccessCallback<List<SuggestionResult>> resultList) { if(lastSuggestionRequest != null) { if(lastSuggestionValue.equals(input)) { return; } lastSuggestionRequest.kill(); } List<SuggestionResult> lr = locationCache.get(input); if(lr != null) { lastSuggestionValue = null; lastSuggestionRequest = null; callSerially(() -> resultList.onSucess(lr)); return; } lastSuggestionValue = input; lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). SearchService However, if it isn't then we want to kill the last request which might still be queued and blocking us from going forward
  • 4. public static void suggestLocations(String input, Location l, SuccessCallback<List<SuggestionResult>> resultList) { if(lastSuggestionRequest != null) { if(lastSuggestionValue.equals(input)) { return; } lastSuggestionRequest.kill(); } List<SuggestionResult> lr = locationCache.get(input); if(lr != null) { lastSuggestionValue = null; lastSuggestionRequest = null; callSerially(() -> resultList.onSucess(lr)); return; } lastSuggestionValue = input; lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). SearchService We check if an entry is already in the cache as users might type and revise a lot thus triggering significant webservice cost overhead
  • 5. public static void suggestLocations(String input, Location l, SuccessCallback<List<SuggestionResult>> resultList) { if(lastSuggestionRequest != null) { if(lastSuggestionValue.equals(input)) { return; } lastSuggestionRequest.kill(); } List<SuggestionResult> lr = locationCache.get(input); if(lr != null) { lastSuggestionValue = null; lastSuggestionRequest = null; callSerially(() -> resultList.onSucess(lr)); return; } lastSuggestionValue = input; lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). SearchService We clean the variable values and then invoke the response. Notice I use callSerially in this case to defer the response to the next cycle. If we call back immediately we might delay the input code which is currently in place. By shifting the callback to the next EDT cycle we guarantee that suggestLocations will behave in a similar way whether the data is cached locally or not
  • 6. lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). getAsJsonMap(callbackMap -> { Map data = callbackMap.getResponseData(); if(data != null) { List<Map> results = (List<Map>)data.get("predictions"); if(results != null && results.size() > 0) { ArrayList<SuggestionResult> resultSet = new ArrayList<>(); for(Map currentResult : results) { Map structured_formatting = (Map) currentResult.get("structured_formatting"); String mainText = (String) structured_formatting.get("main_text"); String secondaryText = (String) structured_formatting.get("secondary_text"); String description = (String) currentResult.get("description"); String placeId = (String)currentResult.get("place_id"); resultSet.add(new SuggestionResult(mainText, secondaryText, description, placeId)); } SearchService The request extracts the predictions array so we can construct the result list
  • 7. lastSuggestionRequest = Rest. get("https://maps.googleapis.com/maps/api/place/autocomplete/json"). queryParam("input", input). queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). getAsJsonMap(callbackMap -> { Map data = callbackMap.getResponseData(); if(data != null) { List<Map> results = (List<Map>)data.get("predictions"); if(results != null && results.size() > 0) { ArrayList<SuggestionResult> resultSet = new ArrayList<>(); for(Map currentResult : results) { Map structured_formatting = (Map) currentResult.get("structured_formatting"); String mainText = (String) structured_formatting.get("main_text"); String secondaryText = (String) structured_formatting.get("secondary_text"); String description = (String) currentResult.get("description"); String placeId = (String)currentResult.get("place_id"); resultSet.add(new SuggestionResult(mainText, secondaryText, description, placeId)); } SearchService We iterate over the entries, notice I discard the generic context which is legal in Java but might produce a warning. I could have used a more elaborate syntax that would have removed the warning but that would have created more verbose code with no actual benefit
  • 8. queryParam("location", l.getLatitude() + "," + l.getLongitude()). queryParam("radius", "50000"). queryParam("key", GOOGLE_PLACES_KEY). getAsJsonMap(callbackMap -> { Map data = callbackMap.getResponseData(); if(data != null) { List<Map> results = (List<Map>)data.get("predictions"); if(results != null && results.size() > 0) { ArrayList<SuggestionResult> resultSet = new ArrayList<>(); for(Map currentResult : results) { Map structured_formatting = (Map) currentResult.get("structured_formatting"); String mainText = (String) structured_formatting.get("main_text"); String secondaryText = (String) structured_formatting.get("secondary_text"); String description = (String) currentResult.get("description"); String placeId = (String)currentResult.get("place_id"); resultSet.add(new SuggestionResult(mainText, secondaryText, description, placeId)); } locationCache.put(input, resultSet); resultList.onSucess(resultSet); } SearchService I extract the elements from the map and create the SuggestionResult entries then store the whole thing in cache followed by the onSuccess call. Notice that in this case I didn't need the callSerially since the response is already asynchronous
  • 9. https://maps.googleapis.com/maps/api/directions/json? origin=Toronto&destination=Montreal&key=API_KEY Directions API The final webservice API we will cover is the directions API which will allows us to set the path taken by the car on the map. The directions API is challenging. It returns encoded data in a problematic format. This is the sample query from Google. Notice we can give the origin and destinations values as a longitude latitude pair which is what we’ll actually do.
  • 10. { "geocoded_waypoints" : [ ... trimmed ... ], "routes" : [ { "bounds" : { ... trimmed ... }, "legs" : [ { "distance" : { ... trimmed ... }, "duration" : { ... trimmed ... }, ... trimmed ... "steps" : [ { ... trimmed ... } } ... trimmed ... ], "overview_polyline" : { "points" : "e`miGhmocNiI`CeFmHaAmIgDai@mNiw@qJqq@{GyFwBp@ag@fLoVpRcr@vI}d@oIg[ePa`@ax@kC_w@mV}h@af@iPa]y_@mq@xZehFje@{r@jCeDgf@}AgfBs]kiCmrAkuJog@gxAoo| DoIm_CdX_{A_Gcb@ad@aw@mnB_pDe_D}rIcnBa_NmRuyBvBcmBnAydC_{Bu_Oe@ktBdt@qiBhL}w@eSylD}i@coIi_AcxCm[maDga@__IsiAuiJmbEyzZagBwvMkSypEkT_~C_cAk_H|Y{fB_P{qC}l@q_C{S_i@yA} dAwj@mkB{^}jCbVi|DzUqoAkjA_`Lku@g_Lye_Dud@ilDwh@ufBeh@}hBgT{jAkm@wv@mm@s}DcMw`A_z@ifAeU{w@kRuaCieAsrEiw@uvAku@{vDez@_kCgCyqAoB}gBwXkw@om@q}AweBizEamAs`DuSwfA} e@ctC_iAukH}hBqsKc|@_iDowAyrJ_B_v@lY}eBgEajByh@skH{`Dkzc@k]_vCeu@yuCyF_uAgBe_Bsa@mxBaDmfCiTasFmMqcJw]sgRsVaeScNggBxdA_tDdw@gxGr@kuAy[w{@qj@_iCi| @orEyd@o`Aaj@yn@knAsvDmn@msJmm@kvOal@o~Cmf@{cGjJazDcp@w_EgxAw~EcnA_}E^y`E}f@swDoPmt@wn@ofAuc@gtAmu@mvAiu@{{@km@qrAgd@}j@ie@_RuoBwr@svBi`BcmB_kB}sBmzBqc@kz@sTihBjGkpA} @gc@eo@kgBeVuPuoA`C_g@uPol@_|@_dA}`BgeAgd@s^}a@_w@isBidAi~AytAyvBihB_fDmvAojB_zIkaL{t@sdAuWirAgZonAohDuzFyaAkbBon@_k@spAi|@}aHgoMi{EqiJw`Di}H{uDuiMc|EytOevAe~D}| @gQcTiQczBonHesAcrE}~Eo|PwqAalF{_@gmCyAcq@`TqbAzw@atCzLsrAbBehGkFmoAa}jAc]qqAiCmoBaMajDeSowAsdCyeIy`FmqMsrAigDwi@ir@ch@s~Auz@cvC}vBcvHeSgl@e_@oTq`AcxBkfBsaEwt@u} CizDevJwfA}bDsqA_bBinCgvD{{HwqVwyA_`Ckc@sg@_i@ymAaXkp@mEo`Bej@}_DebA{aAeYay@eiBc|Ho`@mrE}aAueGun@gpDpIy{GaFg~@lB}rEdD_rDv]klBwAqk@aY_t@{lAmwCsdAshBkaO_x@} bAuv@ipAmLeZqIcBeKLqIpIqEkF" }, "summary" : "ON-401 E", "warnings" : [], "waypoint_order" : [] } ], "status" : "OK" Directions API The response is a bit large so I trimmed a lot of it to give you a sense of what we are looking for. The one thing that matters to us from the response is the overview_polyline entry which seems like a bunch of gibberish but it isn't. This is a special notation from Google that encodes the latitude/longitude values of the entire trip in a single string. This encoding is described by Google in their map documentation
  • 11. // Based on https://github.com/scoutant/polyline-decoder/ private static List<Coord> decodePolyline(String str) { ArrayList<Coord> resultPath = new ArrayList<>(); int index = 0; int lat = 0, lng = 0; while (index < str.length()) { int b, shift = 0, result = 0; do { b = str.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = str.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; Coord p = new Coord((double) lat / 1E5, (double) lng / 1E5); resultPath.add(p); } return resultPath; } Polyline Decoder Being lazy I found someone who already implemented the algorithm in Java and his code worked "as is”. I won't go into the code since it's mostly just bitwise shifting to satisfy the requirements from Google. The method signature is the only thing that matters. It takes an encoded String and returns the path matching that string as a list of coordinates that we will be able to add into the map shortly.
  • 12. public static void directions(Location l, Location destination, DirectionResults response) { Rest.get("https://maps.googleapis.com/maps/api/directions/json"). queryParam("origin", l.getLatitude() + "," + l.getLongitude()). queryParam("destination", destination.getLatitude() + "," + destination.getLongitude()). queryParam("mode", "driving"). queryParam("key", GOOGLE_DIRECTIONS_KEY). getAsJsonMap(callbackMap -> { Map data = callbackMap.getResponseData(); if(data != null) { List results = (List)data.get("routes"); if(results != null && results.size() > 0) { Map firstResult = (Map)results.get(0); Map overview_polyline = (Map)firstResult.get("overview_polyline"); List<Coord> polyline = decodePolyline((String) overview_polyline.get("points")); List legs = (List)firstResult.get("legs"); Map firstLeg = (Map)legs.get(0); Map distance = (Map)firstLeg.get("distance"); Map duration = (Map)firstLeg.get("duration"); response.onDirectionResult(polyline, Util.toIntValue(duration.get("value")), (String)distance.get("text")); } } }); } DirectionResults Now that this is all out of the way the directions method is relatively simple. This method is just another REST call that doesn't include anything out of the ordinary. We extract the overview_polyline value and pass it to the callback response.