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

setLocationShared Not working #406

Closed
canadaka opened this issue Aug 8, 2018 · 20 comments
Closed

setLocationShared Not working #406

canadaka opened this issue Aug 8, 2018 · 20 comments

Comments

@canadaka
Copy link

canadaka commented Aug 8, 2018

Description:
As I also mentioned here #173 (comment) the setLocationShared function does not work.

On iOS it just has no effect, location permission dialog still appears and users location still recorded. On Android I get an error, depending on how I use it.

If I call the function like this, I get an error.

window.plugins.OneSignal
        .startInit(ONE_SIGNAL_APP_ID)
        .setLocationShared(false)
        .iOSSettings({kOSSettingsKeyAutoPrompt: false})
        .handleNotificationOpened(notificationOpenedCallback)
        .endInit();

Android Error:

08-08 10:20:40.170: D/PluginManager(23211): exec() call to unknown plugin: setLocationShared
08-08 10:20:40.173: D/SystemWebChromeClient(23211): file:///android_asset/www/cordova.js: Line 313 : Error in Error callbackId: setLocationShared1526920980 : TypeError: callback.fail.apply is not a function
08-08 10:20:40.174: I/chromium(23211): [INFO:CONSOLE(313)] "Error in Error callbackId: setLocationShared1526920980 : TypeError: callback.fail.apply is not a function", source: file:///android_asset/www/cordova.js (313)

If I instead call the function after separately, I don't get that error, but my location is still recorded, when I look at the OneSignal users dashboard. I deleted all users before building the app.
window.plugins.OneSignal.setLocationShared(false);

However calling the setLocationShared function separately like above on iOS I get the following error in the Xcode log.

ERROR: Plugin ‘setLocationShared’ not found, or is not a CDVPlugin. Check your plugin mapping in config.xml

Environment
Plugin: 2.4.1
Cordova: 7.1.0
Ionic CLI Version: 2.2.3
Ionic App Lib Version: 2.2.1

@canadaka
Copy link
Author

canadaka commented Aug 8, 2018

I cannot get Xcode device logs, I think that is only populated if there is a crash?

But here is some more logging from the Xcode console with logLevel set to 6.

window.plugins.OneSignal.setLogLevel({logLevel: 6, visualLevel: 2});

window.plugins.OneSignal
       .startInit(ONE_SIGNAL_APP_ID)
       .iOSSettings({kOSSettingsKeyAutoPrompt: false})
       .handleNotificationOpened(notificationOpenedCallback)
       .endInit();

window.plugins.OneSignal.setLocationShared(false);
018-08-08 12:29:52.368835-0700 [1197:2160161] Called init with app ID: [APPID_REMOVED_FOR_PRIVACY]
2018-08-08 12:29:52.368936-0700 [1197:2160161] DEBUG: Downloading iOS parameters for this application
2018-08-08 12:29:52.374434-0700 [1197:2160161] VERBOSE: Firing registerForRemoteNotifications
2018-08-08 12:29:52.376611-0700 [1197:2160161] ERROR: Plugin ‘setLocationShared’ not found, or is not a CDVPlugin. Check your plugin mapping in config.xml.
2018-08-08 12:29:52.376716-0700 [1197:2160161] Loading Settings
2018-08-08 12:29:52.378947-0700 [1197:2160161] VERBOSE: oneSignalDidRegisterForRemoteNotifications:deviceToken:
2018-08-08 12:29:52.379075-0700 [1197:2160161] INFO: Device Registered with Apple: [TOKEN_REMOVED_FOR_PRIVACY]
2018-08-08 12:29:52.379123-0700 [1197:2160161] VERBOSE: updateDeviceToken:onSuccess:onFailure:

Curious, if I don't call setLogLevel on its own line, it doesn't work.

I'm a bit confused if these functions are supposed to be called between startInit and endInit or should be called before or after that? I've tried both in my trial and error process.

@canadaka
Copy link
Author

canadaka commented Aug 8, 2018

I have found the problem! It's a bug in the OneSignal.js file.

https://github.com/OneSignal/OneSignal-Cordova-SDK/blob/master/www/OneSignal.js#L229-L235

The OneSignal.prototype.setLocationShared functions usage of cordova.exec is missing the 2nd function argument, which is the error callback. Should be:

OneSignal.prototype.setLocationShared = function(shared) {
   cordova.exec(function(){}, function(){}, "OneSignalPush", "setLocationShared", [shared]);
};

I tested this fix on Android and setLocationShared seems to work now, if I call it AFTER endInit. No error in logs and the user in the OneSignal dashboard has no location.

Unfortunately on iOS the location permission dialog still pops up!!! Which is what i'm trying to avoid. There is no longer an error in the console logs. But the users location is still saved to the OneSignal Dashboard, so it appears setLocationShared is being ignored on iOS even when being called successfully.

Here is some logs from iOS after fixing the cordova.exec function.

2018-08-08 13:29:27.173666-0700 [1346:2184957] Called init with app ID: [APPID_REMOVED_FOR_PRIVACY]
2018-08-08 13:29:27.173799-0700 [1346:2184957] DEBUG: Downloading iOS parameters for this application
2018-08-08 13:29:27.177905-0700 [1346:2184957] VERBOSE: Firing registerForRemoteNotifications
2018-08-08 13:29:27.181534-0700 [1346:2184957] VERBOSE: oneSignalDidRegisterForRemoteNotifications:deviceToken:
2018-08-08 13:29:27.181646-0700 [1346:2184957] INFO: Device Registered with Apple: [TOKEN_REMOVED_FOR_PRIVACY]
2018-08-08 13:29:27.181696-0700 [1346:2184957] VERBOSE: updateDeviceToken:onSuccess:onFailure:
2018-08-08 13:29:27.231104-0700 [1346:2185160] VERBOSE: network response (OSRequestGetIosParams): {
   “uses_provisional_auth” = 0;
}
2018-08-08 13:29:27.313232-0700 [1346:2184957] VERBOSE: oneSignalApplicationWillResignActive

@Nightsd01
Copy link
Contributor

@canadaka Good catch, the callback was indeed missing. Unfortunately this project has never had any tests so it's difficult for us to catch stuff like this.

Otherwise, note that setLocationShared is not an init builder method, you would want to call it separately. I would suggest calling it before you call startInit, not after.

@canadaka
Copy link
Author

canadaka commented Aug 9, 2018

I have tried before and after, neither have any affect on iOS. The location permission still pops up and the users lat/lng location is still saved.

@Nightsd01
Copy link
Contributor

@canadaka Can you try this: remove/uninstall our SDK from your project and let me know if your app still immediately prompts the user for location permission.

There are some plugins that will automatically prompt for location permission, so we'll want to make sure.

Otherwise: please make sure that setLocationShared(false) is before you call init, and completely uninstall/reinstall the app and let me know if it still occurs.

Also, please note that calling setLocationShared(false) does not delete previous location data. So if a user had location enabled in the past, disabling it will NOT remove that data.

@Nightsd01
Copy link
Contributor

Nightsd01 commented Aug 9, 2018

There is only two ways our SDK will send location data:

  1. Your app calls promptLocation
  2. Your app has location enabled in Info.plist and doesn't call setLocationShared(false) before calling init().

Our docs do not mention this, so I've updated the setLocationShared() docs to be a bit clearer.

@canadaka
Copy link
Author

canadaka commented Aug 9, 2018

Thanks for the responses.

  1. I have removed and reinstalled the plugin many times. I've also deleted all Cordova platforms and plugins and re-built app from scratch.
  2. I do have other plugins that prompt for location permission, I mentioned it in the linked post above. cordova-background-geolocation is the plugin we use. In my testing scenario I have a version of our app installed where I've already granted the app location access via that plugin. I then upgrade the app to the version that includes the OneSignal plugin. Where it prompts for location permission again, even though it's already given to the app. The same upgraded version of the app works fine with no prompt if the OneSignal plugin is not included.
  3. I have tried the setLocationShared(false) before and after Init. I also just did a totally fresh install and build of the app with it before. The location permission prompt still appeared.
  4. Each time I do a test, I delete the users from the OneSignal Dashboard, so I know the user data being saved is new.

I just installed the Cordova demo app and no location prompt appeared. So it seems it's a conflict when the app has other plugins requesting permission.

Notice the difference in the dialog from my app to the demo one, no do not allow.

img_20180808_181807
img_20180808_185431

@canadaka
Copy link
Author

canadaka commented Aug 9, 2018

I just thought of something. My app via the cordova-background-geolocation plugin has location permission for While Using the App. Which really is what any app should only require!

But maybe OneSignal is checking/requesting for the Always Allow location permission and that's why the prompt comes up.

@Nightsd01
Copy link
Contributor

@canadaka Even if I install both our plugin and cordova-background-geolocation, I still don't see it asking for location permission unless I specifically call OneSignal.promptLocation().

If you keep OneSignal in your project but remove the cordova-background-geolocation does the issue still occur?

@canadaka
Copy link
Author

Slight tangent from the iOS issues.

So we've had the OneSignal plugin installed on our Android app the past week and users locations (32k) are being saved to the Dashboard, even though I set setLocationShared to false.

window.plugins.OneSignal.setLocationShared(false);

window.plugins.OneSignal
.startInit(ONE_SIGNAL_APP_ID)
.iOSSettings({kOSSettingsKeyAutoPrompt: false})
.handleNotificationOpened(notificationOpenedCallback)
.endInit();

I think if the app already has location permission via another plugin, Onesignal just goes ahead and saves users locations with their Onesignal data? Not what I'd expect setLocationShared config to do. I would except it to both prevent the prompt for location permission and to not save location data with the users session.

@Dave-Osborne
Copy link

I can confirm that location data is definitly being shared as described above (although works as expected on Android).

This would suggest that the iOS code is ignoring the value sent to setLocationShared.

We are in urgent need of this fixing, are you able to advise on how long until a new release is available?

Thanks,
Dave.

@Nightsd01
Copy link
Contributor

Hi @Dave-Osborne we recently fixed a bug in the setLocationShared method, an update should be coming shortly.

@canadaka I’ll Be investigating this one android today

@canadaka
Copy link
Author

Ok after some more debugging I think I found a way to fix the issue of the location permission prompt from appearing on an app upgrade.

If our app's plist file contains LOCATION_ALWAYS_USAGE_DESCRIPTION parameter then the OneLocation will as for location permission. If I manually remove it from the upgrade build, no permission is prompted!

We removed LOCATION_ALWAYS_USAGE_DESCRIPTION from our apps config.xml but the cordova-background-geolocation is inserting a default string on build. So we're working on a post-build script to remove that parameter from the plist after each build.

Doing some more testing, to confirm 100% but looks promising.

@canadaka
Copy link
Author

We have the plugin running on a Testflight iOS version, and even with setLocationShared = false, our locations are being saved.

What we would really want, is first for the setLocationShared to work. And 2nd for a manual function we could call to update a users/device location when we choose too.

@Nightsd01
Copy link
Contributor

@canadaka @Dave-Osborne I still can't reproduce this issue, even when I add cordova-background-geolocation as well.

Are you absolutely certain that your app never calls OneSignal.promptLocation()? Can you please check your codebase just to make sure?

Even better - can you modify our Cordova plugin OneSignal.js and add a log statement to the promptLocation() function, just to make sure it never gets called?

@canadaka
Copy link
Author

promptLocation exists no where in our codebase.

On both iOS and Android, the app already has location permission from the OS. Our app is pretty much useless without this permission, so users will have granted our app this permission before we add OneSignal.

We fixed the issue with the app asking for location permission a 2nd time here #406 (comment)

Now the outstanding issue is a users location is still saved even if setLocationShared is set to false.
It seems that if the app in general has location permission via other means, then OneSignal collects location, regardless of the setLocationShared setting. So the OneSignal plugin needs to check its own setLocationShared before collecting location data, regardless if the app has permission to use a devices location services.

@Nightsd01
Copy link
Contributor

Nightsd01 commented Aug 23, 2018

@canadaka I see what you're saying. I was under the impression we were still talking about the SDK inappropriately requesting location permission.

I have done some testing and I am definitely able to reproduce this issue. It looks like the SDK is inappropriately sending the location even when setLocationShared(false) is called, not just in Cordova but in our native iOS SDK itself. This is definitely a regression bug.

This is an important issue - I'll be updating our SDK and releasing an update within the next 24 hours. I'll also add some tests to ensure it doesn't happen going forward. Thanks for bringing this to our attention!

@Nightsd01
Copy link
Contributor

As an update, we just fixed the issue (it was actually an issue with our native iOS SDK) and we'll be releasing a Cordova SDK update to fix this issue shortly, here is the PR

@Nightsd01
Copy link
Contributor

This issue should now be resolved in the new update (2.4.3).

We've made a minor fix in iOS to resolve this issue, however this week we intend to make more comprehensive changes to the SDK to ensure location data can never be sent if setLocationShared(false) is called, to ensure an issue like this can't happen again. Thanks for the bug report!

@canadaka
Copy link
Author

canadaka commented Sep 6, 2018

So the solution we did to stop our app for asking for location permission a 2nd time, looks like it might not work in future.

"Missing Purpose String in Info.plist File. Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSLocationAlwaysUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting spring 2019, all apps submitted to the App Store that access user data will be required to include a purpose string.If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy)." 

We fixed the permission ask by removing any LOCATION_ALWAYS_USAGE_DESCRIPTION from our info.plist file, but will need to add one again in the future!
#406 (comment)

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

No branches or pull requests

3 participants