Skip to content
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

Make location provider optional #502

Merged
merged 9 commits into from
Oct 5, 2017
Merged

Conversation

Guardiola31337
Copy link
Contributor

@Guardiola31337 Guardiola31337 commented Jul 12, 2017

Per mapbox-gl-native/#9403 we're removing location dependencies on the map SDK. They'll be pulled in from here (MAS), so this PR addresses that.

  • Bundle default LocationEngine implementations for Android core, LOST, and Google Play Services backends
  • Add LOST and Google Play Services to build.gradle as optional dependencies
  • At runtime, detect whether LOST or Google Play Services are available
  • Let the developer set a priority preference for location provider backend (i.e. if more than one provider is available, be able to set one as preferred)

Am I missing something? @mapbox/android

👀 @zugaldia @tobrun for review

@zugaldia
Copy link
Member

@Guardiola31337 So excited to see this happening.

Copy link
Member

@tobrun tobrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great so far, just one remark on LocationSourceProvider

private void initLocationSourceDictionary(Context context) {
locationSourceDictionary = new HashMap<>(3);
locationSourceDictionary.put("Google Play Services", GoogleLocationEngine.getLocationEngine(context));
locationSourceDictionary.put("Lost", LostLocationEngine.getLocationEngine(context));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

above doesn't seem to validate if it's in the classpath or not

@Guardiola31337
Copy link
Contributor Author

  • GoogleLocationEngine is not working properly (not receiving location changes)
  • Add LocationEngineChainSupplier remaining tests
  • Add LocationEngineProvider tests

@Guardiola31337
Copy link
Contributor Author

Guardiola31337 commented Sep 26, 2017

Let the developer set a priority preference for location provider backend (i.e. if more than one provider is available, be able to set one as preferred)

Usage:

LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
locationEngine = locationEngineProvider.obtainAvailableLocationEngines()
  .get(LocationEngineProvider.GOOGLE_PLAY_SERVICES);
if (locationEngine == null) {
  locationEngine = locationEngineProvider.obtainAvailableLocationEngines()
    .get(LocationEngineProvider.ANDROID);
}

What do you think @zugaldia?

GoogleLocationEngine is not working properly (not receiving location changes)

We should revisit the provider strategy. I run some tests and the problem was that when you set the priority to HIGH_ACCURACY we're using the GPS_PROVIDER and this provider takes some time to start receiving location updates (indoors takes forever). I tried to change the priority to LOW_POWER or BALANCED_POWER_ACCURACY and it worked. Maybe we could add timeout timers so if we don't get any updates on a specific provider and timer elapses use a different provider. Another option to explore is using Criteria as previously suggested.

Add LocationEngineChainSupplier remaining tests

Not necessary anymore. LocationEngineChainSupplier was removed.

Add LocationEngineProvider tests

LocationEngine classes are full of static methods and singletons which make adding tests difficult. I guess this could wait until we rewrite those classes.

@Guardiola31337
Copy link
Contributor Author

Guardiola31337 commented Sep 27, 2017

23b50d9 adds/fixes new APIs to get LocationEngines through LocationEngineProvider:

  • obtainBestLocationEngineAvailable() which returns the best LocationEngine available:
    • Return: GoogleLocationEngine, LostLocationEngine or AndroidLocationEngine
    • Criteria: GOOGLE_PLAY_SERVICES > LOST > ANDROID
    • @NonNull ~> If GoogleLocationEngine and LostLocationEngine aren't available AndroidLocationEngine is always returned
    • Usage:
LocationEngineProvider locationEngineProvider = new LocationEngineProvider(context);
locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
  • obtainLocationEngineBy(LocationEngine.Type type) which returns the LocationEngine by type or null if not available:
    • Options: LocationEngine.Type types (GOOGLE_PLAY_SERVICES, LOST, ANDROID, MOCK)
    • @Nullable ~> If the location engine you're asking for is not available a null is returned
    • Usage:
LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
locationEngine = locationEngineProvider.obtainLocationEngineBy(LocationEngine.Type.GOOGLE_PLAY_SERVICES);
if (locationEngine == null) {
  locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
}

Or directly requesting ANDROID location engine which won't be null (always available):

LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
locationEngine = locationEngineProvider.obtainLocationEngineBy(LocationEngine.Type.GOOGLE_PLAY_SERVICES);
if (locationEngine == null) {
  locationEngine = locationEngineProvider.obtainLocationEngineBy(LocationEngine.Type.ANDROID);
}

That ☝️ allows you to:

LocationEngineProvider locationEngineProvider = new LocationEngineProvider(this);
locationEngine = locationEngineProvider.obtainLocationEngineBy(LocationEngine.Type.ANDROID);

Could be useful/interesting in some use cases.


  • Add javadoc to public methods and classes (documentation)

Apart from ☝️ this PR is ready for review.

👀 @zugaldia @tobrun

@Guardiola31337 Guardiola31337 changed the title [WIP] Make location provider optional Make location provider optional Sep 27, 2017
@Guardiola31337 Guardiola31337 force-pushed the pg-location-optional branch 2 times, most recently from 678a54a to 23b50d9 Compare September 29, 2017 10:44
Copy link
Member

@zugaldia zugaldia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, none of them blocking the PR. Can't wait to start using the new APIs.

@@ -59,6 +59,11 @@ dependencies {
// Google Play Services
compile rootProject.ext.dep.gmsLocation

// LOST
compile(rootProject.ext.dep.lost) {
exclude group: 'com.google.guava'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we upgrade the dependency to the latest LOST that Guava exclusion is no longer necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested the sample app with lost 3.0.3 (atm latest version) and I found that it wasn't working properly so I'd rather keep lost 1.1.1 until lostzen/lost#241 gets fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Guardiola31337 I'd actually argue the opposite. With this PR the developer now has the freedom to switch location providers if they don't meet their needs. I think that all that lostzen/lost#241 shows is that LOST fails under certain scenarios. I'd still upgrade to the latest version of LOST and leave it up to the developer decide if that scenario is a blocker for them.

*/
private synchronized void buildAndroidLocationEngine() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is synchronized no longer needed?

Copy link
Contributor Author

@Guardiola31337 Guardiola31337 Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zugaldia
Don't like to answering with a question but I'm pretty sure you have more context:
Why was synchronized in the first place? Why getLocationEngine() from AndroidLocationEngine, LostLocationEngine and GoogleLocationEngine need to be synchronized?

BTW, I've tested it and I didn't find any issues so apparently is working as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Guardiola31337 For thread safety, did your tests include that scenario (i.e. multi-threading)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Guardiola31337 just seeing this is an Activity, I though this was part of the library, thanks for pointing that out. Nevermind.


// LOST
provided(rootProject.ext.dep.lost) {
exclude group: 'com.google.guava'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: let's update to the latest version. If the latest version is an issue to the developer, now they have a mechanism to switch to a different provider.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -90,7 +90,7 @@
<item>Mock</item>
<item>Android</item>
<item>Lost</item>
<item>Google Play Services</item>
<item>Google_Play_Services</item>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this necessary to match the new Type enum? If so, 👍 .

@zugaldia zugaldia requested a review from cammace October 2, 2017 14:23
@zugaldia
Copy link
Member

zugaldia commented Oct 2, 2017

@tobrun @cammace It'd be great if you could give this PR a pass before merging to make sure there're no concerns on the Maps/Navigation side.

@Guardiola31337 Guardiola31337 force-pushed the pg-location-optional branch 5 times, most recently from d3584da to 2ec7c2d Compare October 4, 2017 19:51
@Guardiola31337
Copy link
Contributor Author

2f856d6 and 2ec7c2d addressed your comments @zugaldia

Ready for a second round of 👀

Copy link
Contributor

@cammace cammace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this won't affect Navigation much, we do fall back on the LOST location engine currently in case a user doesn't pass in a location engine. This change I believe will require us to bring the LOST dependency directly into the nav sdk?


import java.lang.ref.WeakReference;

/**
* Sample LocationEngine using Google Play Services
*/
public class GoogleLocationEngine extends LocationEngine implements
class GoogleLocationEngine extends LocationEngine implements
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs to be public inorder not to break the API

@@ -31,7 +28,7 @@
private WeakReference<Context> context;
private GoogleApiClient googleApiClient;

public GoogleLocationEngine(Context context) {
private GoogleLocationEngine(Context context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to remain public to not break API

@@ -17,20 +15,25 @@
/**
* Sample LocationEngine using the Open Source Lost library
*/
public class LostLocationEngine extends LocationEngine implements LocationListener {
class LostLocationEngine extends LocationEngine implements
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to remain public to not break API


private static LocationEngine instance;

private WeakReference<Context> context;
private LostApiClient lostApiClient;

public LostLocationEngine(Context context) {
private LostLocationEngine(Context context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to remain public to not break API

@Guardiola31337
Copy link
Contributor Author

Guardiola31337 commented Oct 5, 2017

@cammace

Looks like this won't affect Navigation much, we do fall back on the LOST location engine currently in case a user doesn't pass in a location engine. This change I believe will require us to bring the LOST dependency directly into the nav sdk?

Lost dependency is not needed anymore we could use:

LocationEngineProvider locationEngineProvider = new LocationEngineProvider(context);
locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();

which will return the best location engine available.

Further information on how to use the new APIs 👉 #502 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants