My solution to the coding challenge

Hi,

Here is my solution to the challenge.

A few words of explanation and details:

Compilation
-
Integrate into Android Studio with the default options and use Gradle to build. Requires buildTools 21.1.1 (latest as of 21/11/2014)

Structure
-
The application is structured like so
- The `SearchFragment` is responsible for providing the Activity with the origin and destination cities
- The Activity is simply receiving these and passing them to the `WebView` fragment to let it handle the result display
- The `SearchFragment` in turn delegates the retrieval of the current location to the `LocationFragment`. This operation being mandatory for the rest of the application, this is represented by a popup that dims the entire interface and displays a progress spinner
- The search for destination is done by using an `AutoCompleteTextView` with the `CityAdapter` that queries the server as the user types, to offer the most accurate suggestions available

UI
-
The UI is largely copied on the mobile website, with a few differences
- The search button is disabled until the user selects a valid city, in order to be sure that we have a valid `city_url` field.
- The origin field is not editable, as it is set by the user's location.
- In landscape mode, the two cities field are arranged in an horizontal fashion to avoid extra-long half-empty textfields, but the search button is still below, to ensure sufficient width for the city names.

Dependencies
-
2 external libraries are used
- Google Services for Location. It is the recommended way to obtain the user location, being faster than the Android framework Location API. It also have a Geofencing API that would be useful in the future to react with the user getting to the bus station, on the bus, at their destination...
- Retrofit (http://square.github.io/retrofit/) is a very clear and efficient library for accessing REST services, but not only. It takes care of the network connection and of the unmarshalling of the objects. It relies on Gson for JSON parsing.

Devices
-
This application was tested on 2 devices on both orientations
- Low-end Android 4.2 phone, 800x480, 4" screen
- Basic Nexus 7 (Android 4.3 tablet), 1280x800, 7" screen

Possible and future improvements
-
- I wanted to integrate the zendesk mobile SDK, but it is still in beta, and I have not received an invitation yet. If I receive it in the next days I will add it, but I will not be able to push it to github because of the Beta NDA.
- On larger tablets, a two-pane layout could offer a better experience, however the `WebView` integration is such a layout is not optimal, because of external links and of the handling of the navigation and the back button.
- Allowing the user to enter an origin point could be a good addition. It would also require that the user be able to be located again.
- The destination field requires that the user actually selects an item in the list, to ensure that there is no ambiguity regarding the city. Automatically selecting an item when he query is specific enough could enhance the experience, but could also be confusing. For example, `Ott` matches `Ottawa` and `Otter Rapids`. A typo would immediately select one instead of the other, forcing the user to delete many characters. A solution to that problem would be to not select the match, but to pre-select it, allowing the user to delete only the last entered character to get back to the previous situation, but at the same time to view the entire city name.

NB
-
The `WebView` rendering on the low resolution (800x480) device I have used to take the screenshot is not very good. It is. however, the same rendering as on the mobile website. (c.f. the screenshot under `extras`). The screenshot taken on the tablet looks much better

I have noticed that the `search` query does not appear to be filtering by connectivity to `origin`. For example
    curl 'https://busbud-napi-prod.global.ssl.fastly.net/search?lang=en&limit=5&origin_id=375dd5879001acbd84a4683dede3a6fb' -H 'X-Busbud-Token: GUEST_9f_femkwS4-6kOX6V5qjPg'

Defines `Longueil` as origin, and returns `Terrebonne`, which are not connected.

Final word
-
This challenge was fun to do and I hope to publish an actual Busbud application in a near future! Please let me know if you have any question, or if there is any improvement that you would like to see in this app.

Simon