Open Source & Free

16. Connecting the Location Service to the Map Form

Module 12: Creating an Uber Clone Transcript we discussed the location service class now let’s see how this maps into the ui back in the map form we can change the map player code which during markup just featured a fixed position car image we bind to the location service where we get a callback every time a driver comes into play we create a label for every car and set the icon with the right angle we keep the angle in a client property so when there is a change event we can check if the angle actually changed one important piece of information that might not be clear from the code is that the core image must be square we use the rotate method on the car image which assumes a square image otherwise it will appear cropped we place the new car where the user is located thanks to the map layout the change listener on the angle property automatically rotates the icon image in the right direction but it does that only if the angle changed to avoid performance penalty we update latitude and longitude separately but we need to guard against duplicate changes so we first test the existing value we can’t replace a constraint in the layout so we remove the component and add it back animate layout should still work in this case and it will move the car gracefully to its new position once all of this is done we should be able to see everything working right now we don’t have drivers in our database but we can add a fake driver by pushing an entry to the mysql database this will create a fake driver entry and allow you to see him when you log in assuming you configured the values in globals.java you should be able to run the server and client then activate the device using sms and see the driver i used the password from my account so i would be able to log in as the driver later you can just copy the same password value from your account as you already know the password

Codename One

17. Reverse Gecoding Google Webservice

Module 12: Creating an Uber Clone Transcript we finally have a client server application that works but we don’t have any real functionality to get to that point we need some web services WebServices from the Device? i chose to invoke the google web services from the device code instead of using our server to proxy the calls i did this because this is a mobile programming course not a server development course this makes sense for a simple project and is arguably faster as i connect directly to google however if i was building a real world application i would have directed all requests to our server and invoked google from there this might have a performance penalty but it’s worth it here are some of the advantages api keys would be stored on the server and would thus be more secure from theft we can cache queries and reduce api costs between users currently i can only cache calls per user but if lots of people are searching for the same things this can add up i can use analytics and statistics in the server code and notice patterns about user behavior and finally i can switch to a different company for the web service implementation to get a better deal if google discontinues its service i don’t have to ship an app update either Googles GIS Services we’ll use four google location-based web services to implement the functionality of this app with geocoding we provide an address or location and get back a location on the map this is useful when a driver receives a set of locations and need to know the actual map coordinates reverse geocoding is the exact opposite it provides the name of a given location this is useful for pointing a pin on the map and naming the location directions provides directions trip time etc we can get the points of the path and plot them out on the map the places api allows searching for a place similar to the geocoding api the auto complete version lets us type into a text field and see suggestions appear we’ll use it for the search functionality New Fields in Globals all of these apis require developer keys which you can obtain from their respective websites i’ve edited the globals class to include these new keys required by the three apis make sure to replace the dashes with the relevant keys you can get the keys by going to the directions geocoding and places websites and follow the process there we use the maps api geocode json url for reverse geocoding google provides this example for usage of the api it’s just a latitude longitude pair and your api key Reverse Geocoding - Result the result of that url look like this response json let’s go over two important pieces we need to get this result array from the response we only care about the first element and will discard the rest this is the only attribute we need at this time from this api now that we know what we are looking for let’s look at the code that accomplishes this SearchService i’ll use the search service class to encapsulate this functionality for each of these services there is an edge case where location isn’t ready yet when this method is invoked in this case i found it best to just do nothing usually it’s best to fail by throwing an exception but that is a valid situation to which i have a decent fallback option so i prefer doing nothing if we send two such calls in rapid succession i only need the last one so i’m canceling the previous request the reverse geocode api latitude long argument determines the location for which we are looking we get the past result as a map containing a hierarchy of objects the callback is invoked asynchronously when the response arrives this gets the result list from the json and extracts the first element from there we extract the one attribute we care about the formatted address entry and invoke the callback method with this result the places autocomplete api is a bit more challenging since this api is invoked as a user types we’ll need the ability to cancel a request just as we would with the geocoding calls caching is also crucial in this case so we must cache as much as possible to avoid overuse of the api and performance issues let’s start by reviewing the api url and responses the default sample from google wasn’t very helpful so i had to read the docs a bit and came up with this url the search is relevant to a specific location and radius otherwise it would suggest places from all over the world which probably doesn’t make sense for an uber style application notice the radius is specified in meters the input value is a the string for which we would like autocomplete suggestions Places Autocomplete - Result this request produces this json result all predictions are again within an array but this time we’ll need all of them the ui would require the text broken down so we need the main text and we’ll need the secondary text to we’ll also need the place id and the reason for this is a huge omission in this api notice it has no location information we will need the place id value to query again for the location SuggestionResult before we move on to the code will need a way to send the results back we can do that with a list of suggestion result entries this is a pretty trivial class and doesn’t require any explaining the class solves the issue of getting the location for a specific entry with the method get location i won’t go too much into the details of that code above since it’s very similar to the code we saw before we just get additional details about a place and parse the results notice that this is a part of the suggestion result class so we don’t invoke this unless we actually need the location of a place there is one last thing we need before we go into the suggestion method itself we need variables to cache the data and current request otherwise multiple incoming requests might collide and block the network we need the last suggestion request so we can cancel it the last suggestion value lets us distinguish duplicate values this can sometimes happen as an edit event might repeat a request that was already sent for example if a user types and deletes a character this can happen since we will wait two 500 milliseconds before sending characters the location cache reduces duplicate requests notice that this can grow to a level of a huge memory leak but realistically that would require a huge number of searches if this still bothers you we can have the cash map class that serializes extra data to storage

Codename One

18. Directions and Places Google Web Services

Module 12: Creating an Uber Clone Transcript we can now move forward to the last two pieces of the search service class 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 however if it isn’t then we want to kill the last request which might still be queued and blocking us from going forward we check if an entry is already in the cache as users might type and revise a lot thus triggering significant web service cost overhead we clean the variable values and then invoke the response notice i use call serially 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 suggest locations will behave in a similar way whether the data is cached locally or not the request extracts the predictions array so we can construct the result list 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 verbus code with no actual benefit i extract the elements from the map and create the suggestion result entries then store the whole thing in cash followed by the on success call notice that this in this case i didn’t need the call serially since the response is already asynchronous the final web service api we will cover is the directions api which will allow 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 destination values as longitude latitude pair which is what we’ll actually do 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 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 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 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

Codename One

19. Auto Complete Location Search UI

Module 12: Creating an Uber Clone Transcript now that the basic infrastructure is out of the way we’ll start wiring it into the ui starting with search the initial search ui i did in the mock-up was very naive it just toggled the completion on and off the real uber app allows us to swipe the search ui down and then pick a location in a map using a pin this then updates the text field with the selected location alternatively if you type into the text field locations are suggested to you as you type there is a great deal of nuanced behavior in this ui so i only focused on the big ticket features the first big feature is the swipe down feature which allows us to swipe down the completion ui as we type the second is the actual completion ui where elements update as we type and finally the ability to point at a location on the map with a pin and select that location i didn’t implement a lot of the relatively easy features such as bookmarked locations or history in the search ui those should be trivial to fill in in order to implement these i moved most of the ui logic into separate classes specifically auto complete address input and completion container both of which i’ll discuss shortly a major feature of auto complete address input is its ability to fold slash unfold the completion container it accomplishes this by binding pointer listeners to the parent form and using them to implement the drag and drop behavior on the left you can see the search ui with completion suggestions appearing below when the suggestions are dragged down we can pick the location from the map as you can see on the right as the map is dragged the location name is updated into the text field i refactored some of the code from the map form class into the autocomplete address input class it made it easier to implement some of the related logic i chose to derive text field rather than encapsulated mostly due to convenience encapsulation would have worked just as well for this case with the exception of these last two variables every other variable here is in the service of the drag and drop logic we use the data change listener to send events to the completion logic however this callback can be very verbose and it’s sometimes invoked by set text the solution is a special version of set text that blocks this callback and reduces the noise in the completion code with the block change event variable the last focused text field is the one that now handles the completion so if the user was in the to text field everything typed will now impact the completion for two and vice versa pointer listeners on the form allow us to detect pointer events everywhere we bind them in the init component method and remove them in the de-initialize method this prevents a memory leak and a situation where pointer processing code keeps running and taking up cpu the initialize is invoked when a component is removed from the ui or its hierarchy is removed it’s also invoked when a different form is shown instead of the current form init component is invoked when a component is there it will be invoked if a component is added to an already showing form or if a parent form is shown you can rely on init component and de-initialize working in tandem they might be invoked multiple times in a valid situations for instance a dialogue shown on top of the form triggers a de-initialize on the components of the form followed by an init component when it’s disposed despite using the shorthand lambda syntax for event handling i need to keep a reference to the drag and release event objects so i can remove them later the dragged element is always the second element 0 is the first it can be dragged between the center location and the south location if this is indeed a drag operation we’d like to block the event from propagating onwards when a component is in the south we set its preferred size to 1 8 of the display height so it won’t peak up too much when it’s dragged up we just increase that size during drag components in the center ignore their preferred size and take up available space so we use margin to provide the drag effect this prevents a drag event on a different region of the form from triggering this event for instance if a user drags the map dragging just displayed a motion we now need to remove the component and place it where it should be we also reset the ui id so styling changes for instance margin unit type etc will reset to the default when we place the container in the south we set the preferred size and margin to match when we place it in the center we set the preferred size to null which will which is a special case that resets previous manual settings and restores the default the location of a text field uses strings but what we really care for care about is coordinates on the map which is why i store them here this is used both by the map pen logic and by the search logic we will use later

Codename One

20. Search Completion Container

Module 12: Creating an Uber Clone Transcript we’ll continue the search ui implementation as we step into the completion container class the completion container tries to coordinate the two instances of the autocomplete address input class by providing a single class that handles the completion ui most of the code in this class should be very familiar and some of it is refactored code from the map form while other code relates to the suggest suggest location api we implemented earlier the name of the class is misleading completion container is not a container here instead of deriving i encapsulated the ui logic and tried to expose only the business logic event dispatches allow us to broadcast events using the add remove listener observer style api we use this dispatcher to broadcast an event when a user presses a completion button this method is invoked when completion is in progress it invokes the web service call to request completion suggestions for a given string we fill up the container with buttons if one of the buttons is pressed we fetch the location from the web service and fill it into the autocomplete address input we then fire the event dispatcher to process the actual selection in the ui we have two types of entries here one with only one line of text and one with two lines of text this is mostly in place to fit the ui ids correctly with the right underline behavior this method is invoked externally to clear up the content of the completion ui and show the clean set of initial options history is positioned here so we could later fill this with actual search history etc this method constructs and animates the completion ui into place notice that we place the content in a container which we wrap up in a border layout this allows us to manipulate the preferred size without breaking the scrolling behavior of the child container in order to accomplish the design for the buttons i had to add the where to button line to uiid it uses grey text on a transparent background padding aligns with the text above we keep the top padding to zero so it won’t drift away from the first line in the where to button margin is zero as usual we have an underline here instead of the underline of the first line of text we use a slightly smaller font but the standard main light font nevertheless

Codename One

21. Plotting the Route On the Map - Setup

Module 12: Creating an Uber Clone Transcript next we’ll bring these changes into the map form class which handles the actual heavy lifting of search first we need to add a couple of members to the class some of these variables really exist in the method body i just move them into the class level i’m skipping that code since it’s pretty trivial we use map container to place a pin and position it we can track map position events using this object we need the last focused entry so we can set the text in the text field when the user drags the map to point at a location the listener is important for cleanup to prevent multiple listener instances that way we always have at most one the timer instance allows us to cancel it we use it to delay web service requests so we don’t send them too frequently the where to button we need to hide it when the search ui is showing and show it again when it’s done we place a lot of elements in that layer on top of the map it’s pretty useful indicates whether we are in the navigation mode or in another mode such as map or browse mode this is important as we can’t enter navigation mode twice Code now that we have these variables in place let’s look at the code we created and placed a new layer for the pin image placement this allows us to drag the completion container down and see the pin image on the map that also means we can remove it easily once we exit the search ui i refactored the text fields to use this new api and set the location to the current location be to the default normally a user wouldn’t enter the origin address only the destination so using the current location makes sense Map i’m using name my current location method to fetch the name of the location of origin the map listener is used for the point location on the map functionality if i drag the map it will fetch the location from there and set it to the last focused text field however we wait 500 millisecond seconds before doing that so we don’t send too many web service requests we cancel the timer if there is one that’s already in the waiting stage this used to be if layer dot get component count is greater than one but that doesn’t make sense anymore as the completion container is always there only folded or expanded so i check if the completion container is in the center or the south when a button is pressed in the search completion we get an event to begin navigation at which point we ask for directions and enter navigation mode i’ll discuss the whole navigation mode in the route section i use animation completion event to show the completion bar which also has an animation in place one thing i neglected to mention in the map is the map listener which we bind using this new method this prevents duplicate map listeners and allows us to easily clear the selection

Codename One

22. Plotting the Route On the Map - to/from Tags

Module 12: Creating an Uber Clone Transcript with that out of the way search should work but how does it display the result for that we need to add additional features to the map form that address these capabilities before we go into that let’s check out what that means Ride Booking UI the ride booking ui plots the path of the ride on the map and includes two tags one pointing at your current location and one on the destination the first tag is divided to a time indication and name the latter only contains the name notice that the elements have rounded rectangle shape with a pointy end on one side to point at the position within the path Tags let’s start with creating these tags the tag code itself is trivial it’s just a label or a container with some details nothing special except for one important detail the black and white border in order to implement the unique shape of the tag i created a new border class notice i used the preferred width of the west component to determine the black section this is done in the black line position method before we go any further i’d like to make one point clear i would have used a nine piece border if this were a real application i would have just cut a nine piece border and moved on however since the point is teaching i chose to do this the hard way UI IDs before we get into the black and white border there are a few ui ids we need to define the navigation label uid is the black on white label that appears in the tag the only unique thing about it is the relatively small amount of padding so the tag doesn’t take up too much space the margin is predictably zero and the font is slightly smaller than usual the navigation minute label ui id is the white on black minute value it’s center aligned it has zero padding below to keep the text and number close together but has similar padding on the other side either sides to match the navigation label it has zero margin and it has a smaller font size than usual although not a tiny font the navigation minute disk label uid is used for the text below that the text with the word min it derives from navigation minute label and has an even smaller font size than that Border that these are out of the way let’s take a look at the border notice we can just subclass the border class just like we can implement painters etc this provides a similar path for customization but is sometimes more flexible most of this code is based on the built-in round wrecked border class drawing this type of border is pretty expensive so we draw onto an image and place that image in cache within the component using put client property we use this value as the key the black line position is used in the version of this border that’s partially black here we create the border image that we will cache for the given component since a shadow is set on the border and that can take up some processing power to speed this up we have two versions of the method fast and slow we call the fast one and invoke the slow one asynchronously to update the border we do a shadow effect by drawing a gradient with varying alpha degrees then blurring that out if we have a cached version of the border image we will just use that as the background of the component assuming the size of the component didn’t change otherwise we create that image and update it later with the slower version that includes the gradient shadow effect we create the shape of the component if it’s the one with the black line we place the corner in the top right otherwise we place it in the bottom left we can now fill out the shape as part of the image creation code if we have a black line we do the fill operation twice with different clip sizes to create that effect

Codename One

23. Plotting the Route On the Map - Completion

Module 12: Creating an Uber Clone Transcript finally after all the buildup let’s draw the path on the map form we’ve had quite a bit of code and it brought us to the point where the navigation ui should function as expected this is implemented in the enter navigation mode method which i mentioned before as you might recall it it’s invoked when clicking an entry in the search results this method is invoked from a callback on navigation we have the coordinates of the path to display on the map as the arguments to the method as you may recall these coordinates are returned by the directions method the first thing we do is remove the existing search ui from the form and animate it out due to the way events are chained this method can be invoked more than once in some unique cases this works around that behavior we convert the path to an array and add it to the map this uses native path plotting for these coordinates i could have used a painter or something similar and might still use it later on i move the camera to show the entire path within the form i create the two tags and add them to the ui notice that the from tag has a right alignment also notice i used the trimmed string method to limit the string length i’ll cover that method soon the back behavior is just a button style to look like a command it invokes the exit navigation mode method which we will get to shortly this is the ui to approve the taxi we are ordering i used a white container with the form uiid on the south portion of the form as a layer Trimming before i continue i also use the trimmed string method in the code before to trim the tag components there isn’t much to say about this method we rely on the fact that addresses usually have a comma after them if the string is missing that or is too long we have special cases for those this guarantees a string of decent length for the tag elements Exit Navigation the one last missing piece of the code is the exit navigation mode call which just removes all the elements and sets the invisible pieces back to visible it’s pretty trivial UI we also have a few ui ids of note mentioned in the code the first is ride title which is the title area for the ride ui it’s pretty much a label so it has black over transparent colors but it’s centered it has the same padding as a label zero margin and same font margin separator is a separator that has marginal margins on the side which we use in the ride dialog other separators in the app reach the edge of their parent container it has a couple of pixels of padding in the bottom to leave room for the separator it has the margin to keep it away from the edges of the parent container and it features a standard underline border the black button is just a standard white over black button with center text alignment as is common with buttons it’s got some padding but not too much so it won’t look huge it’s got some margin so it won’t literally touch the things next to it and to compensate over smaller padding it uses a subtool round wrecked effect that just is just barely noticeable at 0.2 millimeters and it’s got a slightly larger regular font instead of the typical smaller light font once all of this is done we can just see navigation work and appear on the map as expected

Codename One

24. Hailing in the Client - Showing a Beacon

Module 12: Creating an Uber Clone Transcript now that we have a path on the map we can move forward to the hailing process the hailing process is relatively simple we tint the ui show a beacon and during that time we ask the server for a call we can start by adding an event handler to the black button from the enter navigation mode method we are effectively coloring the pin layer to create the tint effect we added a new blink dot class to implement the pausing blue dot effect another new api the hail ride method in location service allows us to hail a ride notice i don’t show anything when the ride is hailed i’ll add that workflow with the driver app later there is one uid we need to cover here and it’s the searching dialog ui id technically this ui element isn’t a dialog it is a label but it looks like a dialog padding is pretty standard for label we have some margin on the sides to space it out from the edges most uii of this ui id is pretty standard except for the use of the special mode of the round wrecked border the top only mode allows only the top portion to be rounded and the bottom appears square usually we use it to combine two borders together with different colours or ui ids in this case we give the component a feel of peaking from the bottom of the form the font is the standard font just like any other label the blinker.class is pretty trivial i could have used an animated gif but instead i just did this this is mostly for transparency we don’t really use the uid here i use low level animations here so the best practice is to register remove with init component slash the initialize the motion class represents a timed motion between values which allows us to animate a value from point x to point y in this case i’m just growing the circle using the value notice only the animate method mutates values as the paint method can be invoked more than once per cycle in theory the drawing logic is mostly hard-coded i would have used the shape api to get a more refined effect but it would have made things more complicated

Codename One

25. Hailing in the Client - Networking and Sending Push Messages

Module 12: Creating an Uber Clone Transcript next we’ll go into the underlying business logic portion of the hailing process on the client up until now i kept hailing as a vague process i think uber probably has a far more elaborate system than the one i developed in an hour but this should work fine for most cases healing includes the following phases we mark what we are interested that we are interested in hailing in the location service websocket code the server checks which drivers are available in the area and returns to us their push keys we send push notifications to the available drivers as time moves on we expand the circle of search for drivers in order to do this i had to make some changes to the websocket protocol in the location service class but first we need some additional variables in the globals class i’ll go into more details on those values in the next chapter but for now we need the variables only all of these apis require developer keys which you can obtain from their respective websites i’ve edited the globals class to include these new keys required by the three apis right now we can leave these all blank and get to them later let’s move to the location service class and the variables i had to add when a driver accepts our hail the server sends a special message indicating that the hail was accepted previously we had two modes for polling the server for searching and not searching i added a third mode that allows us to disable hailing i’ve made the location service into a singleton this these represent whether we are hailing and if so to what radius we use a motion object to get a growing radius that will stretch over time to encapsulate a wider region for hailing our source and destination values which we need to broadcast a hail when we send a push notification to a car we need to make sure we didn’t already notify it the unique id of the driver we’ve found this is the callback we invoke when a driver is found now that these are out of the way let’s look at the other things that need doing we changed the way we handle communication protocol by and we added some additional details first we need to ignore location changes when doing hailing which we can do by adding that condition next we need to change the protocol a little bit this was previously limited to 0 only and now we check if we are in hailing mode during hailing mode the radius of search grows over time we send the from two values as utf-8 encoded strings which allows us to communicate locale specific locations when we turn off healing in the server it’s a one-time thing after it’s off we can go back to the regular mode this isn’t likely as this is a ram based stream we also need to handle message reception code this is a new special case that provides us with details on the driver that picked up the right we are provided with the driver id card and name notice we need the final user variable since car might change and the value that can change can’t be passed to an inner class or lambda in java this is a list of push keys who we should not notify i added a push token to the driver details so we can send a push message to a specific driver if the car wasn’t notified yet add it to the list of cars that we should notify we send the push message in a batch to speed this up we send push type 3 which includes a data payload the first section and a visual payload which you can see after the semicolon before we can compile that code we need to add a push token attribute to the user class finally we have the hail ride method which is relatively simple there isn’t much we need to cover here it just initializes the variables and starts the motion object for the expanding radius this should conclude the client side of the hailing process and now we need to address the server side

Codename One