radarlabs / react-native-radar

React Native module for Radar, the leading geofencing and location tracking platform
https://radar.com
Apache License 2.0
170 stars 32 forks source link

geofencing not working on android, not tested in ios yet #46

Closed hasan642 closed 5 years ago

hasan642 commented 6 years ago

when i try to track user, an error has returned "Error: ERROR_LOCATION", and if result has returned has no user id or and geofences. that is my code: componentDidMount() { Radar.trackOnce().then((result) => { console.log('result is', result) // do something with result.location, result.events, result.user.geofences }).catch((err) => { console.log('err is', err) // optionally, do something with err }); } any solution plz?

noahtallen commented 5 years ago

I've been getting several ERROR_LOCATIONs recently as well using trackOnce on Android. iOS is working fine

russellcullen commented 5 years ago

@hasanal1995 @noahtallen - mind sharing some more details?

noahtallen commented 5 years ago

SDK versions:

We use background tracking a ton to detect the places users go to. Then trackOnce is used to get coordinates for the map, which happens when screen opens and when the user taps a "refresh" button.

I'm not sure about reproduction steps. It seems to be recent, and related possibly to a more recent version of the SDK, since I updated it in the past week or so. For instance, on my test Android device right now, it always returns ERROR_LOCATION and no coordinates are getting picked up, even with high accuracy tracking turned on, and location tracking turned on.

Interestingly, iOS works fine. From our impressions over the past 3-4 months, iOS seems to detect locations much more reliably than on Android. We have maybe 40-50 users on both platforms right now.

russellcullen commented 5 years ago

Thanks for the details, this is definitely not intended behavior. What device are you using to test? We're not able to reproduce ERROR_LOCATION consistently on our side on real device or emulator. Although on emulator we do see the error occasionally.

For clarity, it's worth noting the situations in which you would normally expect ERROR_LOCATION:

Do you know if you're seeing the error after a 20s timeout vs immediately?

noahtallen commented 5 years ago

It's the Moto E4 on wifi without a cell plan. But it usually works fine for GPS detection. We also see it in emulator and typically just have to send the coordinates to get it to work. Recently it has been more of a struggle than usual. Sorry we don't have a lot of details about it! On Dec 4, 2018, 10:42 AM -0500, Russell Cullen notifications@github.com, wrote:

Thanks for the details, this is definitely not intended behavior. What device are you using to test? We're not able to reproduce ERROR_LOCATION consistently on our side on real device or emulator. Although on emulator we do see the error occasionally. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

russellcullen commented 5 years ago

Not a problem! Debugging this stuff is hard. Your emulator behavior is consistent with what we see - the emulator won't get a fresh location fix sometimes and manually sending the coordinates forces a refresh in location manager.

For your E4, are you seeing the error immediately? This would be indicative of location services not being enabled (although that doesn't sound likely in this case). And similarly - are you seeing good behavior with background tracking? If the issue is with the phone finding a fresh fix, I would expect background tracking to be less accurate as well.

noahtallen commented 5 years ago

The appear seems to occur after about 10 seconds - I think there's a timeout in place. However, I've double and triple checked that location services are turned on - in fact, I implemented a custom native module so we can make sure that users know if they need to turn it on just to be safe. There are a few real-world users that appear to be struggling with a similar issue, but I don't have data from the device to verify if it's the same issue. I'm fairly certain it is.

Basically we had a loading indicator display if there were no coordinates in the redux state (this only happens when the user first logs in, since the coordinates are persisted after that). Once coordinates appear, the indicator goes away. But a few new users reported that the loading indicator never went away. Testing it myself, it seems as if it hits a 10 second timeout and then ERROR_LOCATION appears, and so the indicator keeps going. I think Radar is initialized correctly JS side, since it works fine on iOS and all that code is shared.

As for background - I don't know with this specific device. Since it doesn't have a phone plan, I only use it for local debugging. However, another person on the team has a similar device - Moto G6, I believe? They have a similar issue, and also report that background tracking isn't working very well either.

Overall, we've noticed that iOS is significantly better at detecting locations than Android, even when different people go to the same location. I've never really had any concrete evidence of what was going wrong, though.

Is there anything we can do to gather more data which could be useful in solving this?

russellcullen commented 5 years ago

This is very helpful, much thanks!

The Android system uses network as well as GPS info to give more accurate fixes but this also means that without a cell tower connection getting an initial location fix may take longer than we expect.

We're still trying to narrow down the exact issue here as we haven't seen anything this unreliable ourselves. That being said, I'm going to do some investigation on how we can provide a more reliable and timely location fix for trackOnce, especially for the initial location fix as you described for your case.

I think the most helpful data right now would be all anecdotal if possible - so just more conditions in which you see this error consistently. Thanks again!

noahtallen commented 5 years ago

That would be fantastic! I know that one user who reported this was on a Pixel 2. They were a new user on the latest version of our app, and the app never resolved coordinates after they logged in. I don't know for sure, but based on my own testing, I think that the LOCATION_ERROR would have occurred, causing the indefinite loading screen they experienced. At least, the coordinates have not been updated since then either, since the presence of coordinates dictates whether the loading indicator appears.

russellcullen commented 5 years ago

We've done extensive testing on a Pixel 2 as one of our in-house test devices so this is surprising to hear. Would you mind sharing your ordering of trackOnce, startTracking and permissions calls? Or even a test project where you can reproduce this semi-consistently?

noahtallen commented 5 years ago

Absolutely. This could certainly be an error on our part with configuration. Here is what happens as a user creates an account. I think this could probably be cleaned up a bit.

  1. Initial create account and data load from backend. As this is happening, we navigate to a loading screen which asks for location permissions. We do not allow the user past this screen unless location is enabled. There is a lot of custom code here (including a few native modules) to make sure we get reliable location permissions (and since Android & iOS have differences in how they handle permissions.)
export function openSystemZonderSettings () {
  if (Platform.OS === 'android') {
    NativeModules.OpenSettings.openLocationSettings(data => { console.log(data) })
  } else if (Platform.OS === 'ios') {
    Linking.openURL('app-settings:')
  }
}

export function getPermissionStatus (): Promise<LocationPermissionStates> {
  if (Platform.OS === 'ios') {
    return NativeModules.LocationRequest.getLocationPermissionStatus()
  } else {
    return Radar.getPermissionsStatus()
  }
}

export function setPermissionToAlways (): Promise<boolean> {
  if (Platform.OS === 'ios') {
    return getPermissionStatus()
      // $FlowFixMe because we know these three results will return on iOS
      .then((status: 'GRANTED' | 'DENIED' | 'UNKNOWN') => {
        if (status === 'UNKNOWN') {
          Radar.requestPermissions(true)
          return false
        } else if (status === 'DENIED') {
          Alert.alert(
            'Enable Location',
            'Zonder won\'t work without location services turned on! To enable location, open the Settings Menu and enable "Always On" location for Zonder.',
            [
              { text: 'Cancel', onPress: () => {}, style: 'cancel' },
              { text: 'Settings', onPress: openSystemZonderSettings }
            ])
          return false
        } else {
          return true
        }
      })
  } else if (Platform.OS === 'android') {
    return PermissionsAndroid.request('android.permission.ACCESS_FINE_LOCATION')
      .then((status: 'granted' | 'denied' | 'never_ask_again') => {
        if (status === 'never_ask_again' || status === 'denied') {
          Alert.alert(
            'Enable Location',
            'Zonder won\'t work without location services turned on! To enable location, open the Settings Menu and enable "Always On" location for Zonder.',
            [
              { text: 'Cancel', onPress: () => {}, style: 'cancel' },
              { text: 'OK', onPress: openSystemZonderSettings }
            ])
          return false
        } else {
          return true
        }
      })
  }
}
  1. On componentDidMount of the root of our signed-in navigation stack, setup location handling with this function:
    function initializeGeolocation (userId: string, email: string) {
    Radar.setPlacesProvider(provider)
    Radar.setUserId(userId)
    Radar.setDescription(email)
    Radar.startTracking()
    }
  2. Directly after the call to this function, we set up a redux-saga eventChannel which funnels Radar events into sagas. We do this to ensure that we get events even when the react components unmount - though this may be unneeded. I'm not sure the best way to handle JS events in the background, but this seems to work ok, at least on iOS:

    export function createLocationChannel () {
    return eventChannel((emitter: (input: RadarEvents) => void) => {
    const onRadarEvent = (result: RadarOnEvent) => {
      result.events.forEach((event: RadarEvents) => {
        emitter(event)
      })
    }
    
    Radar.on('events', onRadarEvent)
    
    const unsubscriber = (): void => {
      Radar.off('events')
    }
    
    return unsubscriber
    })
    }
  3. When the user navigates to the tab bar with the map, we call this code in the componentDidMount of that tab bar component. This is mounted after the user taps on the tab bar, so the screen is not initially mounted when the user enters the app until then. This is where the ERROR_LOCATION comes from:
    Radar.trackOnce()
      .then(({ location }: {location: RadarLocation}) => {
        fetchNearby(location) // Calls Facebook Graph API to get nearby places
        updateCoords(location) // Sends coords to redux state
      })
noahtallen commented 5 years ago

I will try to set up a test project later, but I'm pretty crunched for time this week. I know it will be hard to test without that, though!

russellcullen commented 5 years ago

Thanks this is extremely helpful! I know a sample project is a lot of work so I appreciate the effort, but this should be enough for us to investigate for now, no rush on that!

noahtallen commented 5 years ago

Here is more anecdotal evidence from our CEO:

So the location bugs that I'm detecting currently are sporadic non-detections that don't follow any pattern of use. The main issue is that people go to places and are not detected at any place at all (not even wrong ones or nearby places)

  1. They use the SCAN button multiple times, it does not work

(Note, this scan button calls trackOnce, the same code in item 5 above.)

  1. Their dot on the Zonder Map is detecting the person at the correct location.

(this comes from react-native-maps)

  1. The correct location can be right on or next to the current location dot, but the person does not get anything detected.

(This would be a nearby place, which we get through a call to the facebook graph API)

  1. Sometimes a person doesn't get locations for a while, and then later gets locations.
  2. No error message appears in the location log.
  3. I haven't yet fully observed this happening on an iOS device, it seems to be mostly Android. (but not certain)
  4. Another person with a different phone, sitting in the same location (Map dot for the two people are even in the same location on the app) gets credit for a location, while the first person does not. I've seen it on Samsung S8, and Google Pixels
russellcullen commented 5 years ago

Hey, just a quick update. We're testing some significant improvements to the Android native implementation of trackOnce and currently targeting a 2.1.3 sdk release. Likely to release end of this week or early next. I'll close this thread once that update goes live, and will be looking forward to your feedback after the fact. Thanks again!

noahtallen commented 5 years ago

This is very exciting! What are some of the improvements?

russellcullen commented 5 years ago

We've basically tuned our location request intervals to be more aggressive for the trackOnce use case.

Previously, if background tracking was also enabled at the same time we would piggy-back on the location requests we already had running. Now we will explicitly make a new, more aggressive, location request for trackOnce.

Stay tuned!

russellcullen commented 5 years ago

Just released a new version of Android SDK https://github.com/radarlabs/radar-sdk-android/releases/tag/2.1.3 with these changes!

No need to change anything on the React Native side, the next time you build gradle should automatically pull in the latest version. Please let us know if you see any issues with this new version, closing this issue in the meantime.

noahtallen commented 5 years ago

I did a really brief test, and it was able to lock onto a location much more quickly. Thanks for the update!

noahtallen commented 5 years ago

@coolbrow I just wanted to say that after several days of using the update on more devices, performance is way better on the track once call. I haven't noticed any issues with it at all. We really appreciate the work you guys do to resolve issues we encounter!

russellcullen commented 5 years ago

That's great to hear! We appreciate the feedback and, as always, please let us know if you run into any other issues!