-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dynamic offline routing to NavigationView #1829
Conversation
d3e64e0
to
655e842
Compare
Codecov Report
@@ Coverage Diff @@
## master #1829 +/- ##
============================================
+ Coverage 32.14% 33.61% +1.46%
- Complexity 964 1015 +51
============================================
Files 248 254 +6
Lines 8577 8696 +119
Branches 651 660 +9
============================================
+ Hits 2757 2923 +166
+ Misses 5572 5513 -59
- Partials 248 260 +12 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This absolutely needs field testing.
Yeah, this definitely needs a bunch of testing.
I've left some comments to discuss / look at before merging here.
|
||
import java.util.HashMap; | ||
|
||
class ConnectivityStatusMap extends HashMap<Integer, Boolean> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about adding a HashMap
as a property / create a wrapper so creating a custom one extending from HashMap
is not necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to be internal, right? Can this be refactored later if/as needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Straightforward refactor, took care of it 👍
} | ||
|
||
private boolean isConnectionFast(int type, int subType) { | ||
if (type == ConnectivityManager.TYPE_WIFI) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be careful here because you could be connected to a Wi-Fi but that doesn't mean to have connectivity e.g. you could be connected to a hotspot and don't have connection until you log in.
I believe we should implement something similar as with mobile connectivity. Maybe 👀 Wi-Fi strength?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good to think about as an improvement but can possibly be deferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a wifi strength "checker" to address this
Per conversation with @kevinkreiser, our own timeout mechanism may make sense when offline is present with online calls. I.e. wait no longer than 5 seconds before cancelling the online call and looking at offline for the route. |
...ation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationViewModel.java
Show resolved
Hide resolved
@@ -377,11 +369,9 @@ public void onProgressChange(Location location, RouteProgress routeProgress) { | |||
private OffRouteListener offRouteListener = new OffRouteListener() { | |||
@Override | |||
public void userOffRoute(Location location) { | |||
if (hasNetworkConnection()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the offRouteListener
only getting fired now when the device is online? This doesn't cause any issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Connectivity checks are now done in NavigationViewRouter
with the ConnectivityStatusProvider
, so this check was no longer necessary / would block the new logic.
|
||
void findRouteWith(NavigationRoute.Builder builder) { | ||
if (!isConfigured) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we give an error if not configured?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good catch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we throw an exception here? As it is, this would be a somewhat silent failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually won't call this method if this class isn't configured https://github.com/mapbox/mapbox-navigation-android/pull/1829/files#diff-29009b5750e50557cd5e8a7fd79a46f7R80. So we may not need this check at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let's remove it altogether then.
...ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/OfflineRouteFoundCallback.java
Show resolved
Hide resolved
class RouteComparator { | ||
|
||
private static final int FIRST_ROUTE = 0; | ||
private static final int ONE_ROUTE = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adjust naming for consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistent with what exactly? Sorry not following the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just understood what that meant, sorry I thought they were both referring to indexes. Maybe SIZE_ONE_ROUTE
would be more explicit for the second field?
void compare(@NonNull DirectionsResponse response, @Nullable DirectionsRoute chosenRoute) { | ||
if (isValidRoute(response)) { | ||
List<DirectionsRoute> routes = response.routes(); | ||
DirectionsRoute bestRoute = routes.get(FIRST_ROUTE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could move the initialization to the call to obtainMostSimilarRoute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted the naming in RouterComparator
to be more clear 👍
} | ||
} | ||
|
||
private DirectionsRoute obtainMostSimilarRoute(List<DirectionsRoute> routes, DirectionsRoute currentBestRoute, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels redundant with findMostSimilarRoute
, if you don't pass in the first route you could just get rid of this method and call the other one.
int routeIndex = 0; | ||
String chosenRouteLegDescription = obtainRouteLegDescriptionFrom(chosenRoute); | ||
int minSimilarity = Integer.MAX_VALUE; | ||
for (int index = 0; index < routes.size(); index++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could make this a for each (for(DirectionsRoute route: routes)
) and instead of routeIndex
keep track of the route
392d0a7
to
1df0c85
Compare
|
||
import timber.log.Timber; | ||
|
||
class NavigationViewOfflineRouter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a lot of objects called routers
, since this seems to only take care of making sure that the offline router is properly configured, can we try to name it to make that apparent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I completely follow regarding sole responsibility of configuration, findRouteWith
is also finding new offline routes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I understand what you are saying. Can we call this a wrapper
or something? Since it is acting mostly as a wrapper for the routers.
1df0c85
to
10deec9
Compare
@danesfeder can you describe the architecture of the Routers/RouteFetchers? That might make it easier to understand some of your choices |
@devotaaabel sure thing!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, my existing comments are style NITs I guess. Will approve after field testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than a minor comment I think this is good to go. Let's test it out and 👀 how it looks like.
Great work here @danesfeder 💪
|
||
void findRouteWith(NavigationRoute.Builder builder) { | ||
if (!isConfigured) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let's remove it altogether then.
10deec9
to
636a03e
Compare
636a03e
to
27053bb
Compare
Description
This PR adds two
NavigationViewOptions
that will allow for initialization of offline routing within theNavigationView
. The view will then detect connectivity when it's time to find a route and use either online or offline based on the current state of the device.What's the goal?
The goal is to encapsulate the offline logic within the
NavigationView
soRouteListener#allowRerouteFrom
is no longer the go-to for offline with theNavigationView
.How is it being implemented?
For this initial implementation, the view will not worry about downloading data. The two view options are
String
s: routing tile offline path and the version of that data. This means this data will already be on the device prior to initialization of the view.When searching for a new route, the logic is as follows:
So we will fallback to offline if we don't find a fast connection. Otherwise, we will try the slow connection with online as a last resort.
connectivityStatus.isConnectedFast()
is based on the mobile connection subtype (EDGE
,LTE
for example).WIFI
always returns true.How has this been tested?
Checklist
SNAPSHOT
upstream dependencies if needed)Activity
example in the test app showing the new feature implemented