tinycreative / react-native-intercom

React Native wrapper for Intercom.io
MIT License
405 stars 279 forks source link

[Question] How is setupAPN() supposed to get the deviceToken? #23

Closed ryankask closed 5 years ago

ryankask commented 8 years ago

I see that the library includes setupAPN(deviceToken). How is the deviceToken supposed to find its way into the JS environment?

It's not an issue because you can just add [Intercom setDeviceToken:deviceToken]; but wanted to know if there was an alternative way or if it's there for API parity.

kristojorg commented 8 years ago

I am also wondering this. My users are not registered with intercom until within the JS env, so calling [Intercom setDeviceToken:deviceToken] throws an error:

[Intercom] ERROR - Tried to update user attributes, but no user has been registered yet.

If I have the devicetoken in JS then I can set device token manually once they're registered. Where do I get that variable?

ryankask commented 8 years ago

@kristojorg The flow I am using is:

In JS:

Intercom.registerIdentifiedUser({ userId: 'bob' }).then(Intercom.registerForPush);

In AppDelegate.m you have the following which may be called if the user allows push messages after being asked because of the last line above:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [Intercom setDeviceToken:deviceToken];
}

Hopefully this works for you.

jplethier commented 8 years ago

@ryankask I am using this flow too after the login, but before the login I have a UnidentifiedUser registered, and after login, seems that intercom is not setting the push token for the logged user.

This flows worked nicely for you?

rogchap commented 8 years ago

Not that I've tried yet, but you could setup your app to use the PushNotificationManager as described in the docs: http://facebook.github.io/react-native/docs/pushnotificationios.html

Then you could use the setupAPNin your JS:

PushNotificationIOS.addEventListener('register', Intercom.setupAPN);

Would this work??

jplethier commented 8 years ago

Can the problem be that I am using only the user email to register this as identified user on intercom? I follow the instructions to setup the app to use PushNotificationIOS of react-native too. The problem that I am having is not with push register, but to register an user for push after log in. When I register an unidentified user for intercom before log in, this user has push enabled. After login, I use the user email to register an identified user on intercom, and I need to enable push to this identified user.

Here is where the lib is not working as I expect. I already try to use like @ryankask suggested before, and I tried to put the Intercom.registerForPush to execute inside then, like this

Intercom.registerIdentifiedUser({email: 'email'})
    .then(() => {
        Intercom.registerForPush();
    });
browniefed commented 8 years ago

This may be because their is a fix in master but not published yet.

ryankask commented 8 years ago

@rogchap Thank you. I completely forgot about PushNotificationIOS and that explains how that would work.

I'll close this issue because @jplethier's issue appears to be resolved by a recent commit.

jplethier commented 8 years ago

@ryankask what commit? Is it published on a recent version? The last commit in master is mine, and it is not about push notifications registration on intercom, it is just to fixe the register identified user with email.

browniefed commented 8 years ago

@jplethier ah nevermind then. I actually don't use this plugin or react native. So I assumed incorrectly. Reopening so this thread can continue.

ryankask commented 8 years ago

Surprised to hear you don't use React Native. Your RN animation book is very helpful!

@jplethier Sorry for closing this prematurely. Have you tried calling reset() before registerIdentifiedUser()?

I'm not using Intercom for logged out users. If the reset() call doesn't work, trying removing registerUnidentifiedUser() and see if it works for logged in users only. That would match what I'm doing.

I realised that the code sample I wrote above was wrong. I interact with Intercom in a redux saga and removed the yield statements so the code above was broken. I've changed it for future reference.

rogchap commented 8 years ago

This might be (and might not be) related: APNS is only available in Production according to Intercom docs. How do you test this if you can't use the test APNS?

rogchap commented 8 years ago

OK... I've tried using the setupAPN function and it encodes the string wrongly:

[Intercom setDeviceToken:[deviceToken dataUsingEncoding:NSUTF8StringEncoding]];

So this is a bug and will not work (trust me, I've tried!). I'm not sure what the right encoding is to use.

Best to use:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [Intercom setDeviceToken:deviceToken];
}
javiercr commented 7 years ago

I think @rogchap is right. If you use react-native-push-notification (based in PushNotificationIOS) to register for remote notifications, and later use the resulting token to call setupAPN, you will probably run into problems as the encoding from String to NSData doesn't seem to match the encoding on PushNotificationIOS:

+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  NSMutableString *hexString = [NSMutableString string];
  NSUInteger deviceTokenLength = deviceToken.length;
  const unsigned char *bytes = deviceToken.bytes;
  for (NSUInteger i = 0; i < deviceTokenLength; i++) {
    [hexString appendFormat:@"%02x", bytes[i]];
  }
  [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
                                                      object:self
                                                    userInfo:@{@"deviceToken" : [hexString copy]}];
}

As @rogchap suggested, if you call [Intercom setDeviceToken:deviceToken] directly from didRegisterForRemoteNotificationsWithDeviceToken it seems to work because it avoids the encoding problem. However this solution is not ideal, as in our case we would prefer to set the token (call setupAPN after the user logs in), while keeping the registration for the token handed by PushNotificationIOS (before the login).