Package Versions:
"react": "~15.4.0-rc.4",
"react-native": "0.40.0",
"react-native-onesignal": "^3.0.4"
Current Behavior
I've followed the Usage Instructions to the letter.
Expected Behavior
Callbacks should be called regardless of whether the app is loaded from the background or cold-started.
Thoughts?
Edit: I just tried upgrading to 0.41.2 to be in sync with the example project. Problem persists.
Edit 2: This is my setup right now: https://gist.github.com/maxcodes/6d4657b4253e72e2be6fd391416f6cf3
Alright, I managed to get a workaround working. This is obviously a hack, so I'll leave this open to see what we can do about this.
From this comment I found the places where the native code (android and ios) emits the event. Then, I tried adding a delay before sending the event, as suggested here.
Android path: node_modules/react-native-onesignal/android/src/main/java/com/geektime/rnonesignalandroid/RNOneSignal.java
Leave the notifyNotificationOpened method like this:
// make sure you have this at the top of the file
import android.os.Handler;
private void notifyNotificationOpened(Bundle bundle) {
try {
Handler handler = new Handler();
// don't forget to add the "final" keyword here
final JSONObject jsonObject = new JSONObject(bundle.getString("result"));
handler.postDelayed(new Runnable() {
@Override
public void run() {
sendEvent("remoteNotificationOpened", RNUtils.jsonToWritableMap(jsonObject));
}
}, 1500);
} catch(Throwable t) {
t.printStackTrace();
}
}
iOS path: node_modules/react-native-onesignal/ios/RCTOneSignal/RCTOneSignal.m
Change the handleRemoteNotificationOpened to this:
- (void)handleRemoteNotificationOpened:(NSString *)result {
NSError *jsonError;
NSData *objectData = [result dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
double delayInSeconds = 1.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[curRCTBridge.eventDispatcher sendAppEventWithName:@"remoteNotificationOpened" body:json];
});
}
You can try adjusting the delay to whatever works for you (the smaller the delay the better). This worked for me, I hope it helps someone else too 馃
+1
I've created a branch with these changes, feel free to use it in the meantime.
https://github.com/maxcodes/react-native-onesignal/tree/delay
package.json
"react-native-onesignal": "git+https://github.com/maxcodes/react-native-onesignal.git#delay"
Thanks @maxcodes, this workaround works well enough for our needs 馃槃
Thanks @maxcodes, but for me only works for iOS, not for Android devices, any idea?
@jlopez90 try increasing the delay?
@maxcodes wow, that's awesome, saved my ass, thanks! Are there any plans add this fix to master?
Thanks @maxcodes increasing the delay worked!
@maxcodes Would it be possible to update your fork, so we can use it with RN0.47? No worries if you don't have time, just an open question.
@avishayil Are there any plans for fixing this on master? This would be really helpful, and would take the burden of @maxcodes from maintaining a fork. Pinging you since I saw you had most commits on this project, but feel free to pass through to other maintainers if that's more appropriate.
This workaround appears to be a little unstable: if the start of the application takes more time ? (old devices for example)
We can use:
Android: onReactContextInitialized override from ReactInstanceEventListener to send the event when the app is started
iOS: didFinishLaunchingWithOptions function
But I'm not very confortable with native codes for now, I don't even know if it's possible to do it like this
EDIT: this guy did a workaround too, he moved 'opened' listener outside any callback and it works !
There is no official way to fix it?
@GertjanReynaert I tried updating it a while back but I'm not too familiar with either Java or Obj-C, and I got stumped because upstream namespaced the names of the events.
@danieloprado something that we noticed recently is that this may be a symptom of your app taking too long to boot. For us, we were invoking the OneSignal listener in the componentDidMount of the main scene. However, the scene would wait for a very long query to get executed before mounting, so that's why the event is getting fired but not caught. See if you have a similiar situation and consider delaying the slow components to mount after the main scene has mounted.
TL;DR: It might be an implementation issue.
I hope that helps!
Just a heads up that I've posted a pretty lengthy comment at https://github.com/geektimecoil/react-native-onesignal/issues/332#issuecomment-341326624 discussing this problem.
I was having the same issue but adding OneSignal.configure({}); before declaring the listener functions solved it for me.
We have solved this problem by changing the /node_modules/react-native-onesignal/index.js. The problem is that OneSignal received the message before we add the opened listener. What we do is that we try listen before we start OneSignal and cache the message before we add opened listener.
'use strict';
import { NativeModules, NativeAppEventEmitter, NetInfo, Platform } from 'react-native';
import invariant from 'invariant';
var DEVICE_NOTIF_RECEIVED_EVENT = 'OneSignal-remoteNotificationReceived';
var DEVICE_NOTIF_OPENED_EVENT = 'OneSignal-remoteNotificationOpened';
var DEVICE_NOTIF_REG_EVENT = 'OneSignal-remoteNotificationsRegistered';
var DEVICE_IDS_AVAILABLE = 'OneSignal-idsAvailable';
// ---------- CHANGE HERE --------------------
var openedHandler = false;
var lastOpenResult = false;
NativeAppEventEmitter.addListener(
DEVICE_NOTIF_OPENED_EVENT,
(result) => {
console.log(result);
if (openedHandler !== false) {
console.log("Got the result after the register");
openedHandler(result);
} else {
console.log("Got the result before register");
lastOpenResult = result;
}
}
);
// -------------------------------------
var RNOneSignal = NativeModules.OneSignal;
const _notifHandlers = new Map();
function handleConnectionStateChange(isConnected) {
if (!isConnected) return;
OneSignal.configure();
NetInfo.isConnected.removeEventListener('connectionChange', handleConnectionStateChange);
}
NetInfo.isConnected.fetch().then(isConnected => {
if (isConnected) return OneSignal.configure();
NetInfo.isConnected.addEventListener('connectionChange', handleConnectionStateChange);
}).catch((...args) => console.warn("Error: ", args));
export default class OneSignal {
static addEventListener(type: any, handler: Function) {
// Listen to events of notification received, opened, device registered and IDSAvailable.
invariant(
type === 'received' || type === 'opened' || type === 'registered' || type === 'ids',
'OneSignal only supports `received`, `opened`, `registered`, and `ids` events'
);
var listener;
if (type === 'received') {
listener = NativeAppEventEmitter.addListener(
DEVICE_NOTIF_RECEIVED_EVENT,
(notification) => {
handler(notification);
}
);
} else if (type === 'opened') {
// ---------- CHANGE HERE --------------------
openedHandler = handler;
if (lastOpenResult !== false) handler(lastOpenResult);
console.log("Register the open event");
// ------------------------------------------------
} else if (type === 'registered') {
listener = NativeAppEventEmitter.addListener(
DEVICE_NOTIF_REG_EVENT,
(notifData) => {
handler(notifData);
}
);
} else if (type === 'ids') {
listener = NativeAppEventEmitter.addListener(
DEVICE_IDS_AVAILABLE,
(ids) => {
handler(ids);
}
);
}
_notifHandlers.set(type, listener);
}
/// .....
}
Most helpful comment
Alright, I managed to get a workaround working. This is obviously a hack, so I'll leave this open to see what we can do about this.
From this comment I found the places where the native code (android and ios) emits the event. Then, I tried adding a delay before sending the event, as suggested here.
Android path:
node_modules/react-native-onesignal/android/src/main/java/com/geektime/rnonesignalandroid/RNOneSignal.javaLeave the
notifyNotificationOpenedmethod like this:iOS path:
node_modules/react-native-onesignal/ios/RCTOneSignal/RCTOneSignal.mChange the
handleRemoteNotificationOpenedto this:You can try adjusting the delay to whatever works for you (the smaller the delay the better). This worked for me, I hope it helps someone else too 馃