-
Notifications
You must be signed in to change notification settings - Fork 91
Workflow example
Chain of events that occur on app loading without user interaction.
On app start, the UI for the MainFragment
is created inflating the correspondent XML files and setting the listeners for the buttons, gestures and map. Before adding the listeners to the map, the map should be retrieved, this can fail because [Play Services are not correctly configured in the device] (http://developer.android.com/google/play-services/setup.html#ensure).
If this fails all UI interface is disabled with setEnabled
method for all button views and disabling the options menu and an intent is send to Goolge Play services that will a display a dialog to update the services. Also in the blank a map a button will appear to make the update. When the app returns to foreground (presumably coming for a successful installation of Play Services) the map is retrieved again and if this is done OK all gets re-enabled. This way the app never is in a failure state.
Selected server on last app usage is retrieved from the database and the bounds are drawn in the map. Map is centered to the center of the selected server.
Previously selected tiles are restored to the map and max zoom level is set to avoid problems zooming too much with custom tiles.
At this point the previous state of the app if is not a fresh start is restored. This is performed with [saved Instance bundle] (http://developer.android.com/training/basics/activity-lifecycle/recreating.html#RestoreState) received in onActivityCreated, if this bundle is null it means that is a fresh start and a field that allows the rest of the app to be aware of this is set.
Note that this part will be repeated each time the app comes from the background, because the method is triggered in onStart method, part of the [Android lifecycle] (http://developer.android.com/guide/components/fragments.html#Lifecycle).
-
A connection to LocationClient is requested in OnStart method of the fragment, setting this fragment to receive the callbacks derived from the connection.
-
OnConnectionFailed method will be activated if the connection fails, an intent to Play Services will be sent and that activity will take care of the problem.
-
OnConnected method will be triggered on a normal execution. This method can behave of several ways depending on what is the state of the app:
-
No server is selected:
ServerSelector
task will be always executed and will try to autodetect a server if the preference is checked and a valid user's location is obtained. -
Server is selected and autodetect is enabled:
- User not in server bounds and clearly changed his position or it's the first time that the server is trying to be detected, hence last position checked for servers is null: the app will try to autodetect a server.
- Otherwise:
ServerSelector
task won't be triggered because will be a pointless disruption for the user.
-
Server is selected and autodetect is disabled. In this case this will be only executed at first start because if the server is not changing there is no point in changing the camera from the position set by the user. First start is detect checking if [saved Instance bundle] (http://developer.android.com/training/basics/activity-lifecycle/recreating.html#RestoreState) is null.
- User in server bounds: camera will be moved to user's location so he will see his location in the map (it's marked as a blue dot/arrow and [provided by Maps APi] (http://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html#setMyLocationEnabled(boolean)).
- User not in server bounds: camera will be centered in server center and a marker will be set to this center to be set as default start location. This way the user can directly move the marker and will not have as default start a location an useless, for him, "MyLocation".
-
The main parameters to be set are start/end location, date & time to travel and travel mode & type.
There are three different ways to do this:
- User starts typing.
- A listener for the text box detects that the text has been changed and sets a field to inform of this for the correspondent text box. There is another field to don't trigger this process if the text box was changed by the app.
- The user finish typing hence he clicks in the other text box (or changes the focus in an other way) or presses done button. `Task
- Geocoding is triggered for the text contents.
- Geocoding result are obtained,
GeocodingTask
has finished his exection and passes the control to the callback class that were passed,MainFragment
:- More than one result: before the task passes the control launches a dialog showing all the locations to select the preferred location. Once is selected last location is passed to the
MainFragment
. - No results: an empty list will be passed to the callback.
- One result : obtained address is passed to the
MainFragment
through the callback.
- More than one result: before the task passes the control launches a dialog showing all the locations to select the preferred location. Once is selected last location is passed to the
- Callback for geocoding is executed. If there were no result an error message is shown, otherwise:
- Sets the start/end location field.
- Sets the text box to display the result to the user.
- Adds, moves the marker to the new position.
- Camera is centered to the new location or to an area to fit start and end locations if is not the first location entered.
- User taps or long taps in the map:
- Tap: a marker will be set for the text box that has the focus.
- Long tap: we can choose between start/end marker
- The app receives the marker position.
- Marker is inside bounds, marker is set:
- Selected marker is moved or added to the selected location.
- Text box location is updated to marker coordinates.
- A toast is displayed to inform the user.
- Preference key to control if "MyLocation" is set as origin or destination is disabled if necessary.
- If preference key of "Intelligent Markers" is set to enable, reverse-geocoding will be triggered to the position of the marker.
- Marker is outsutide bounds: an error toast is displayed.
- Marker is inside bounds, marker is set:
- If geocoding was requested:
- Geocoding result is closer than a defined constant to marker coordinates: result is accepted.
- Marker is moved to the received location.
- Location start/end field is updated.
- Text box is updated to the received address.
- Geocoding result is not close enough: result not accepted:
- Whatever, text box is updated with "Marker close to [geocoding result]", although geocoding location want be used.
- Geocoding result is closer than a defined constant to marker coordinates: result is accepted.
Three options can be selected:
-
Current location: travel from user's current location obtained from Location Client.
- User's location is not available: no changes will be performed
-
Contact address: and intent is sent requesting the system contact's app all contacts with an address set.
- If a contact is selected
MyActivity
, as is the attached activity, will handle the situation in itsonActivityResult
method:- Address will be set as text box contents.
- Geocoding will be triggered to obtain the location for that address (using the task and same procedure previously described).
- If a contact is selected
-
Point on map: text box whose menu was clicked is selected and a helping message is set as text box hint. Then a point will be added following the use case of the previous section.
Date and time are set in a dialog that is triggered by a "clock" button in the main UI. This dialog is implemented by a Fragment class, following latest Android guidelines, called DateTimeDialog
.
The UI consists in two [pickers] (http://developer.android.com/guide/topics/ui/controls/pickers.html) to choose date and time and a [spinner] (http://developer.android.com/guide/topics/ui/controls/spinner.html) to choose whether the desired date will be used to set the arrival or the departure time.
-
User clicks on the button.
-
App listener for the button, which is located in
MainFragment
, is called:- Fragment is created removing previous instances if any.
- A bundle is attached to the new fragment to pass the initial hour. This is used to display the dialog next time with the date&time the user has entered, because it is store in
MainFragment
. Firs time will be actual time. - Method to show the [Dialog Fragment] (http://developer.android.com/reference/android/app/DialogFragment.html) is called.
-
DateTimeDialog receives the control flow and initializes the date and time to the values of the bundle. Received date and time are also used to set the minimum date to choose.
-
User selects the preferred date and time and press OK.
-
DateTimeDialog OK button listener receives the signal:
- Retrieves the data from the pickers and the spinner.
- Obatins the activity
MyActivity
for intercommunication with the other fragment and calls the public method of the activityonDateComplete
.
-
MyActivity
callsonDateComplete
in the callback class that was defined previouslyMainFragment
. -
MainFragment
sets the fields that hold date, time and arriveBy value of the spinner. This values will be used to initialize next timeDateTimeDialog
and to be included in the request when it's triggered.