OneSignal / react-native-onesignal

React Native Library for OneSignal Push Notifications Service
Other
1.57k stars 374 forks source link

IOS - Frozen white screen after opening the notification from the killed state #119

Closed Adesh closed 7 years ago

Adesh commented 7 years ago

Notifications work correctly while opening it when the app is in the background state. However doing the same when the app is killed makes the UI unresponsive and the white screen appears. (in android everything works perfectly)

OneSignal.configure({
  onIdsAvailable: function(device) {
    console.log('UserId', device.userId);
    console.log('PushToken', device.pushToken);
  },
  onNotificationOpened: (message, data, isActive)=>{      
      return recursiveCheck(_data);
  },
}); 

recursiveCheck: function(_data){
  if(this.navigator)
    return this.doDeepLink(_data);
  return setTimeout(()=>recursiveCheck(_data),500);
}
stillalive commented 7 years ago

+1 on this issue.

@Adesh you found any workarounds?

Adesh commented 7 years ago

@stillalive not yet.

congnguyen91 commented 7 years ago

I think the device event isn't called because listener events doesn't add when app kill & open again (guess). Should check if listener events have been added or not..

congnguyen91 commented 7 years ago

When app killed: Maybe the thread setBridge function in RCTOneSignal.m doesn't run. remoteNotificationOpened / handleRemoteNotificationReceived doesn't fire => handle something in didReceiveRemoteNotification

avishayil commented 7 years ago

Please try upgrading to version 2 and see if the problem persists?

congnguyen91 commented 7 years ago

@avishayil it still occurs on version 2.0.0

avishayil commented 7 years ago

Can you please set up an example project which the issue persists?

congnguyen91 commented 7 years ago

Thanks you very much @avishayil . I created a refresh project and it works now. Then I try to remove a line by line in my code. I found the problems => OneSignal.sendTag("userId", userId); in componentDidMount.

class PushNotificationsController extends React.Component {
  ....
  componentDidMount () {
    const { userId, dispatch } = this.props;
    OneSignal.configure({
      onIdsAvailable: (device) => {
        this.setState({oneSignalId: device.userId});
      },
      onNotificationReceived: (notification) => {
        if (notification.isAppInFocus) {
          this.processPushType(notification.payload.additionalData, notification.payload.body, notification.isAppInFocus);
        }
      },
      onNotificationOpened: (openResult) => {
        const { notification } = openResult;
        this.processPushType(notification.payload.additionalData, notification.payload.body, notification.isAppInFocus);
      }
    });
   // OneSignal.sendTag("userId", userId); 
   if (Platform.OS === 'android') {
      OneSignal.inFocusDisplaying(0);
   }
  }
  ...
  render () {
     return <View />; // null;
  }
}
avishayil commented 7 years ago

@congnguyen91 Glad you sorted it out! Are you able to use sendTag outside componentDidMount?

congnguyen91 commented 7 years ago

Yes, I am @avishayil . I don't know what happen But the first screen contains a map view which should finish loading before do something like routing to second screen. I guess that some function of OneSignal need prepare something. Maybe it lacks of condition for running these functions.

I appreciate that this module has used 'autoregister' before. I suggest that it should remove asking permission when init or add another option. When Notification feature is used, It asks permission automatically.

- (id)initWithLaunchOptions:(NSDictionary *)launchOptions appId:(NSString *)appId settings:(NSDictionary*)settings {

    [OneSignal setValue:@"react" forKey:@"mSDKType"];
//    [OneSignal initWithLaunchOptions:launchOptions
//                               appId:appId
//          handleNotificationReceived:^(OSNotification* notification) {
//              [self handleRemoteNotificationReceived:[notification stringify]];
//          }
//          handleNotificationAction:^(OSNotificationOpenedResult *result) {
//              if (!curRCTBridge)
//                  coldStartOSNotificationOpenedResult = result;
//              else
//                  [self handleRemoteNotificationOpened:[result stringify]];
//          }
//          settings:settings];

    return self;
}
congnguyen91 commented 7 years ago

I found a problems. if request permission isn't accepted => 'OneSignal.configure' doesn't return result of 'onIdsAvailable'. So I think You should add a warning whether the configure failed or not. Another option is we can return a promise after requestPermission then we can config

requestPermission(permission).then((result) => {
OneSignal.configure({
        onIdsAvailable: (device) => {

        },
        onNotificationReceived: (notification) => {

        },
        onNotificationOpened: (openResult) => {

        }
      });
})
avishayil commented 7 years ago

Don't forget iOS will request permissions by default at the first run - but you can request the permissions later if you like. If you want, you have checkPermissions function which returns a callback, to use before calling configure:

let pushPermissions;
OneSignal.checkPermissions((permissions) => {
    pushPermissions = permissions;
});
if (pushPermissions == 'something valid') {
    OneSignal.configure({
        ...
    });
}
hounsellal commented 7 years ago

I can't figure this out either. Same problem but anyone have an idea the general reason why it gets frozen at the white screen when someone opens a notification after the app has been killed?

Screon commented 7 years ago

I see LaunchScreen after OneSignal was initialised and nothing helped. Main thread is waiting for something...

screen shot 2017-05-10 at 15 29 43
[OneSignal initWithLaunchOptions:launchOptions
                               appId:@"id"
          handleNotificationReceived:^(OSNotification *notification) {
              NSString *title = notification.payload.title;
              NSString *body = notification.payload.body;
              if (title && body) {
                  [UIAlertView showWithTitle:title message:body];
              }
          }
            handleNotificationAction:^(OSNotificationOpenedResult *result) {}
                            settings:@{kOSSettingsKeyInFocusDisplayOption: @(OSNotificationDisplayTypeNone)}
     ];
rwkyyy commented 7 years ago

same problem here, can't find a proper solution for it, anyone managed to solve it? or a workaround?

Screon commented 7 years ago

@rwkyyy I found that it can be when user deny push notifications or on simulator. If you start check if pushs is allowed before OneSignal configure it will work

rwkyyy commented 7 years ago

@Screon I have the push notifications allowed (real device - testflight), but if the app is killed, it will just open a white screen 😓

Screon commented 7 years ago

@rwkyyy even if you comment OneSignal initWithLaunchOptions? Try to completely turn it off. May be OneSignal is not your problem.

dprogramming commented 7 years ago

I'm having the same issue. Anything that can solve it?

rwkyyy commented 7 years ago

@Screon I don't have any iniWithLaunchOptions 😕

andrei-ciucardel commented 7 years ago

In my case, the problem was from OneSignal.configure(); function. I used OneSignal.addEventListener(); function instead.

rwkyyy commented 7 years ago

@nanokid same here, can confirm that.

dprogramming commented 7 years ago

For me it appeared to have something to do with some navigation in the app. Removing OneSignal.configure() fixed the issue for you?

andrei-ciucardel commented 7 years ago

Yes, this resolved my issue

dprogramming commented 7 years ago

Thanks @nanokid, that's quite curious though!

andrei-ciucardel commented 7 years ago

@dprogramming, I hope this is useful for you

dprogramming commented 7 years ago

I didn't have a chance to try it yet, but I hope so too! I already found a workaround, but it's quite ugly, so if this works I can change that. Thank you very much!

maxcodes commented 7 years ago

For anyone that comes here via Google, OneSignal.configure is no longer valid, use addEventListener like the README says. 👍