Closed diego-paired closed 3 years ago
+1.
java.lang.NullPointerException: at com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java:4) at java.lang.reflect.Method.invoke (Method.java) at com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:147) at com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:21) at com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java) at android.os.Handler.handleCallback (Handler.java:873) at android.os.Handler.dispatchMessage (Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java) at android.os.Looper.loop (Looper.java:224) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:37) at java.lang.Thread.run (Thread.java:764)
Howdy Diego, Thank you for reporting this issue.
Can you please include the code you're using? Also can you please provide environment info (e.g: device make and model, OS, etc...)?
Cheers
Howdy Diego, Thank you for reporting this issue.
Can you please include the code you're using? Also can you please provide environment info (e.g: device make and model, OS, etc...)?
Cheers
Thanks for your reply.
It's being reported on our Google Play console at the rate of about 50 crashes per week, I don't have any way to reproduce it.
Same here.
info Fetching system and libraries information... System: OS: macOS 10.15.7 CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz Memory: 36.86 MB / 8.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 10.22.0 - ~/.nvm/versions/node/v10.22.0/bin/node Yarn: 1.22.4 - /usr/local/bin/yarn npm: 6.14.6 - ~/.nvm/versions/node/v10.22.0/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Managers: CocoaPods: 1.10.0 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2 Android SDK: API Levels: 23, 25, 26, 28, 29 Build Tools: 28.0.3, 29.0.2, 29.0.3 Android NDK: Not Found IDEs: Android Studio: 3.6 AI-192.7142.36.36.6308749 Xcode: 11.6/11E708 - /usr/bin/xcodebuild Languages: Java: 1.8.0_242 - /usr/bin/javac Python: 2.7.16 - /usr/bin/python npmPackages: @react-native-community/cli: Not Found react: 16.13.1 => 16.13.1 react-native: 0.63.3 => 0.63.3 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
"react-native": "0.63.3", "react-native-onesignal": "^4.0.1",
Fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'org.json.JSONObject com.onesignal.OSDeviceState.toJSONObject()' on a null object reference
com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java:239) java.lang.reflect.Method.invoke (Method.java) com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:372) com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:151) com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java) android.os.Handler.handleCallback (Handler.java:883) android.os.Handler.dispatchMessage (Handler.java:100) com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java:27) android.os.Looper.loop (Looper.java:241) com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:226) java.lang.Thread.run (Thread.java:919)
Please provide a code snippet in order to facilitate reproduction.
Cheers
@rgomezp
The error occur in OneSignal.getDeviceState() call:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
The exception is:
Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'org.json.JSONObject com.onesignal.OSDeviceState.toJSONObject()' on a null object reference
com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java:239)
java.lang.reflect.Method.invoke (Method.java)
com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java:372)
com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java:151)
com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java)
android.os.Handler.handleCallback (Handler.java:883)
android.os.Handler.dispatchMessage (Handler.java:100)
com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java:27)
android.os.Looper.loop (Looper.java:241)
com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:226)
java.lang.Thread.run (Thread.java:919)
The OneSignal and React Native packages are:
"react-native": "0.63.3",
"react-native-onesignal": "^4.0.1",
The react native info:
info Fetching system and libraries information...
System:
OS: macOS 10.15.7
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Memory: 36.86 MB / 8.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 10.22.0 - ~/.nvm/versions/node/v10.22.0/bin/node
Yarn: 1.22.4 - /usr/local/bin/yarn
npm: 6.14.6 - ~/.nvm/versions/node/v10.22.0/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.10.0 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API Levels: 23, 25, 26, 28, 29
Build Tools: 28.0.3, 29.0.2, 29.0.3
Android NDK: Not Found
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6308749
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
Languages:
Java: 1.8.0_242 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.13.1 => 16.13.1
react-native: 0.63.3 => 0.63.3
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found
Getting same issue.
"react-native": "^0.63.4", "react-native-onesignal": "^4.0.3"
I upgraded from "react-native-onesignal": "^3.9.3" to "react-native-onesignal": "^4.0.3". I am getting crashes now. I have updated the init code same as above. I added freshly.
... let device = await OneSignal.getDeviceState(); ...
From Play Store Crash Log
java.lang.NullPointerException: at com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java) at java.lang.reflect.Method.invoke (Method.java) at com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java) at com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java) at com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java) at android.os.Handler.handleCallback (Handler.java:739) at android.os.Handler.dispatchMessage (Handler.java:95) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java) at android.os.Looper.loop (Looper.java:148) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java) at java.lang.Thread.run (Thread.java:818)
Firebase Crash log
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'org.json.JSONObject com.onesignal.g0.a()' on a null object reference at com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState(RNOneSignal.java:4) at java.lang.reflect.Method.invoke(Method.java)
Howdy, Thank you for the information, but if someone could provide a code example that would be most helpful. This
const getDeviceState = async () => { const deviceState = await OneSignal.getDeviceState(); console.log({ deviceState }); }
doesn't quite provide enough information to reproduce. What we need is some more context as to how and where this is being used.
E.g: how does the call to getDeviceState
relate to the OneSignal initialization? or what RN lifecycle function is this being called in?
Please make sure to provide all the context necessary to resolve this since the stack traces provided don't quite provide what we need.
I suspect this might be happening if getDeviceState
is called too quickly. Can you try moving getDeviceState
to a point in your code that is guaranteed to run after OneSignal initialization completes? e.g: put it in the callback to the subscription change observer.
Remember that getDeviceState
captures a snapshot at the time it is called. For that reason do not cache the state, but rather re-get it as needed.
@rgomezp
Hi, in the App.tsx, our entry point, we have:
const oneSignalIntialize = async () => {
OneSignal.setAppId('xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx');
}
const App = () => {
useEffect(() => {
oneSignalIntialize();
}, []);
return (
<LoginFlow />
);
}
After the login flow, if this was succeed, we have a welcome screen:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
const WelcomeScreen = () => {
useEffect(() => {
getDeviceState();
}, []);
return (
<Components />
);
}
Hi @renatobentorocha , Thank you for sharing the code with us! The useEffect hook here may be called to initialize the SDK within the main App component. This is essentially an async call that gets called as soon as the component is mounted, but there's no state that checks if the initialization has been completed. You can use the useState hook to add a state to check for the init status before rendering the Welcome screen. Another recommendation, as suggested by @rgomezp , would be to run it in the callback to the addSubscriptionObserver (sorry for me speaking too quickly on the deprecated getPermissionSubscriptionState earlier), which would guarantee that the SDK has been successfully initialized before accessing the device state. Let us know if this helps resolving the issue, Thanks
Hi @tyang1 Thanks by attention, but the one-signal docs for that callback (getPermissionSubscriptionState) say:
I will test with addSubscriptionObserver
and will let you know what happen
Getting this also. Don’t know how to reproduce. @rgomezp perhaps it’s a threading issue? This happens randomly, but quite a lot. We see many traces for in our crash report
Howdy, I don't think this is a threading issue as the stack traces point to it more likely occurring at the wrapper level. This could certainly be a bug. We just need reliable reproduction steps to move forward with a resolution.
It is interesting @renatobentorocha that you report it is happening 98% in background.
@oferRounds @dijinshopwise is this something you are also seeing?
+1
@rgomezp follow the code:
async componentDidMount() {
this._isMounted = true
/* O N E S I G N A L S E T U P */
OneSignal.setAppId('***********************************')
OneSignal.setLogLevel(0, 0)
OneSignal.setRequiresUserPrivacyConsent(false)
/* O N E S I G N A L H A N D L E R S */
OneSignal.setNotificationWillShowInForegroundHandler(notifReceivedEvent => {
let notification = notifReceivedEvent.getNotification()
const buttonOk = {
text: 'OK', onPress: () => {
notifReceivedEvent.complete()
},
}
Alert.alert(notification.title, notification.body, [buttonOk])
if (notification.additionalData) {
//
}
})
OneSignal.setNotificationOpenedHandler(notification => {
//
})
OneSignal.disablePush(true)
const deviceState = await OneSignal.getDeviceState()
if (Platform.OS === 'ios' && !deviceState.isSubscribed) {
OneSignal.promptForPushNotificationsWithUserResponse(function(accepted) {
//
});
}
// ...
}
I downgrade to old version and Google Play warns about same error.
com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState
Any suggestion? Any temporary solution?
We're still receiving hundreds of these crashes, any news?
@diego-paired our temporary workaround was to delay the call to getDeviceState()
after OneSingal init (we added 2 seconds delay)
@diego-paired our temporary workaround was to delay the call to
getDeviceState()
after OneSingal init (we added 2 seconds delay)
thanks for the tip
Hi @renatobentorocha , Thank you for sharing the code with us! The useEffect hook here may be called to initialize the SDK within the main App component. This is essentially an async call that gets called as soon as the component is mounted, but there's no state that checks if the initialization has been completed. You can use the useState hook to add a state to check for the init status before rendering the Welcome screen. Another recommendation, as suggested by @rgomezp , would be to run it in the callback to the addSubscriptionObserver (sorry for me speaking too quickly on the deprecated getPermissionSubscriptionState earlier), which would guarantee that the SDK has been successfully initialized before accessing the device state. Let us know if this helps resolving the issue, Thanks
@diego-paired @dan-developer
I followed the @rgomezp suggestion and the crashes, for now, stopped occur.
OneSignal.addSubscriptionObserver(() => {
OneSignal.getDeviceState().then((deviceState) => {
console.log({deviceState})
});
});
Using the test app, added this code to a button:
Situation 1
let getDeviceStateButton = this.renderButtonView(
"Get Device State",
isExternalUserIdLoading || isPrivacyConsentLoading,
() => {
console.log("Attempting to get device state");
this.setState({ isExternalUserIdLoading: true }, () => {
// OneSignal getDeviceState
let deviceState = OneSignal.getDeviceState();
console.log("deviceState: ", deviceState);
console.log("deviceState.isSubscribed: ", deviceState.isSubscribed);
this.setState({ isExternalUserIdLoading: false, isSubscribed: deviceState.isSubscribed });
console.log("this.state.isSubscribed after calling setState: ", this.state.isSubscribed);
console.log("deviceState.userId: ", deviceState.userId)
});
});
Log shows:
2021-03-25 20:06:14.589544-0700 jonexample[751:27269] [javascript] Attempting to get device state
2021-03-25 20:06:14.645290-0700 jonexample[751:27269] [javascript] 'deviceState: ', { _U: 0, _V: 0, _W: null, _X: null }
2021-03-25 20:06:14.647385-0700 jonexample[751:27269] [javascript] 'deviceState.isSubscribed: ', undefined
2021-03-25 20:06:14.647768-0700 jonexample[751:27269] [javascript] 'this.state.isSubscribed after calling setState: ', undefined
2021-03-25 20:06:14.647897-0700 jonexample[751:27269] [javascript] 'deviceState.userId: ', undefined
However when using the example code provided in the componentDidMount:
Situation 2
async componentDidMount(){
const deviceState = await OneSignal.getDeviceState();
this.setState({ isSubscribed : deviceState.isSubscribed});
console.log("componentDidMount deviceState: ", deviceState);
console.log("componentDidMount deviceState.isSubscribed: ", deviceState.isSubscribed);
console.log("componentDidMount deviceState.userId: ", deviceState.userId);
}
The log shows:
2021-03-25 20:14:46.521099-0700 jonexample[1326:55465] [javascript] 'componentDidMount deviceState: ', { userId: '92aa2978-3f53-454e-b1a6-652c43f0dba4',
2021-03-25 20:14:46.521328-0700 jonexample[1326:55465] [javascript] 'componentDidMount deviceState.isSubscribed: ', true
2021-03-25 20:14:46.521435-0700 jonexample[1326:55465] [javascript] 'componentDidMount deviceState.userId: ', '92aa2978-3f53-454e-b1a6-652c43f0dba4'
@rgomezp is scenario 1 expected behavior?
@diego-paired @renatobentorocha @dan-developer could y'all share your examples or confirm if both above situations is what you see?
Please be detailed in how you are using this method and include steps for us to reproduce.
@jfishman1 Take a look at the documentation. You will see that getDeviceState
is an asynchronous function so make sure to await on it, or to use a then
.
Regardless, it appears there's a good opportunity to handle this in the SDK to avoid these crashes. Thanks for surfacing. We will explore what changes can be made to more seamlessly handle these.
Digging into this a bit further, it appears that the most likely cause of this is the native side is trying to get the device state before the context has loaded.
if (appContext == null) {
logger.error("OneSignal.initWithContext has not been called. Could not get OSDeviceState");
return null;
}
To confirm, please look for OneSignal.initWithContext has not been called. Could not get OSDeviceState
in your native logcat (e.g: open Android Studio).
In the meantime, it seems we can add a check in the Android bridge to prevent a full on crash.
Regardless, please note: We still recommend only getting the device state via the subscription change observer to ensure you're not getting the device state too early
Thanks for your patience y'all.
From #1085:
Instead of delaying the device state getter via a timer, try putting the getDeviceState
function call in the subscription observer. This way, you will know that it is subscribed. e.g:
OneSignal.addSubscriptionObserver(async (event) => {
this.OSLog("OneSignal: subscription changed:", event);
if (event.to.isSubscribed) {
const state = await OneSignal.getDeviceState();
// do something with the device state
}
});
Update: this is now fixed in the latest version 4.0.7
I updated to the latest 4.0.7 repo. I am not sure if I am asking on the right place but on some iOS simulators and Android devices I even only get these fields with deviceState for example like this one. There is even no userId field.
{"rootTag":21,"initialProps":{}}
WARN {"hasNotificationPermission": false, "isEmailSubscribed": false, "isPushDisabled": false, "isSMSSubscribed": false, "isSubscribed": false, "notificationPermissionStatus": 0}
Digging into this a bit further, it appears that the most likely cause of this is the native side is trying to get the device state before the context has loaded.
if (appContext == null) { logger.error("OneSignal.initWithContext has not been called. Could not get OSDeviceState"); return null; }
To confirm, please look for
OneSignal.initWithContext has not been called. Could not get OSDeviceState
in your native logcat (e.g: open Android Studio).In the meantime, it seems we can add a check in the Android bridge to prevent a full on crash.
Regardless, please note: We still recommend only getting the device state via the subscription change observer to ensure you're not getting the device state too early
Thanks for your patience y'all.
From #1085: Instead of delaying the device state getter via a timer, try putting the
getDeviceState
function call in the subscription observer. This way, you will know that it is subscribed. e.g:OneSignal.addSubscriptionObserver(async (event) => { this.OSLog("OneSignal: subscription changed:", event); if (event.to.isSubscribed) { const state = await OneSignal.getDeviceState(); // do something with the device state } });
I've tried that but it is not 100% work, like sometimes i got the device id sometimes not, mostly the negative case happens when on the first launch of the app. So i have to close the app first, then the device id will be fetch successfully. any idea?
Is there any body still getting this error in 28 July 2022 or only me?
Is there any body still getting this error in 28 July 2022 or only me?
Getting the same error. However not often or rarely on some of devices like Redmi and Infinix.
Same issue here, any solution yet?
One year later; Same issue here, any solution yet?
Description: We're receiving a number of crash reports originating in
RNOneSignal.getDeviceState
, stack trace attached below.It affects every android SDK version and manufacturer.
Environment
"react-native-onesignal": "^4.0.2",
react: 17.0.1 => 17.0.1 react-native: 0.64.0-rc.2 => 0.64.0-rc.2
Steps to Reproduce Issue: Haven't been able to reproduce the issue, it's reported on Google Play's crash dashboard.
Anything else: