Beschreibung:
Wir erhalten eine Reihe von Absturzberichten mit Ursprung in RNOneSignal.getDeviceState
, Stacktrace unten angehÀngt.
Es betrifft jede Android SDK-Version und jeden Hersteller.
Umgebung
"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
Schritte zum Reproduzieren des Problems:
Das Problem konnte nicht reproduziert werden, es wird im Absturz-Dashboard von Google Play gemeldet.
Noch etwas:
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:883)
at android.os.Handler.dispatchMessage (Handler.java:100)
at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java)
at android.os.Looper.loop (Looper.java:237)
at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java:37)
at java.lang.Thread.run (Thread.java:919)
+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)
Hallo Diego,
Vielen Dank, dass Sie dieses Problem gemeldet haben.
Könnten Sie bitte den von Ihnen verwendeten Code angeben? Können Sie bitte auch Umgebungsinformationen bereitstellen (zB: GerÀtemarke und -modell, Betriebssystem usw.)?
Prost
Hallo Diego,
Vielen Dank, dass Sie dieses Problem gemeldet haben.Könnten Sie bitte den von Ihnen verwendeten Code angeben? Können Sie bitte auch Umgebungsinformationen bereitstellen (zB: GerÀtemarke und -modell, Betriebssystem usw.)?
Prost
Danke fĂŒr deine Antwort.
Es wird auf unserer Google Play-Konsole mit einer Rate von etwa 50 AbstĂŒrzen pro Woche gemeldet, ich habe keine Möglichkeit, es zu reproduzieren.
Hier gilt das gleiche.
info Abrufen von System- und Bibliotheksinformationen...
System:
Betriebssystem: macOS 10.15.7
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2,70GHz
Speicher: 36,86 MB / 8,00 GB
Shell: 5.7.1 - /bin/zsh
BinÀrdateien:
Knoten: 10.22.0 - ~/.nvm/versions/node/v10.22.0/bin/node
Garn: 1.22.4 - /usr/local/bin/garn
npm: 6.14.6 - ~/.nvm/versions/node/v10.22.0/bin/npm
WĂ€chter: 4.9.0 - /usr/local/bin/watchman
Manager:
CocoaPods: 1.10.0 - /usr/local/bin/pod
SDKs:
iOS-SDK:
Plattformen: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
Android SDK:
API-Stufen: 23, 25, 26, 28, 29
Build-Tools: 28.0.3, 29.0.2, 29.0.3
Android-NDK: Nicht gefunden
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6308749
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
Sprachen:
Java: 1.8.0_242 - /usr/bin/javac
Python: 2.7.16 - /usr/bin/python
npmPakete:
@react-native-community/cli: Nicht gefunden
reagieren: 16.13.1 => 16.13.1
reaktiv: 0.63.3 => 0.63.3
React-Native-Macos: Nicht gefunden
npmGlobalPackages:
React-native : Nicht gefunden
"reaktiv-nativ": "0.63.3",
"react-native-onesignal": "^4.0.1",
Schwerwiegende Ausnahme: java.lang.NullPointerException
Versuch, die virtuelle Methode 'org.json.JSONObject com.onesignal.OSDeviceState.toJSONObject()' fĂŒr eine Null-Objektreferenz aufzurufen
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)
Bitte geben Sie ein Code-Snippet an, um die Reproduktion zu erleichtern.
Prost
@rgomezp
Der Fehler tritt beim OneSignal.getDeviceState()-Aufruf auf:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
Die Ausnahme ist:
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)
Die OneSignal- und React Native-Pakete sind:
"react-native": "0.63.3",
"react-native-onesignal": "^4.0.1",
````
The react native info:
```typescript
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
Bekomme das gleiche Problem.
"react-native": "^0.63.4",
"react-native-onesignal": "^4.0.3"
Ich habe ein Upgrade von "react-native-onesignal": "^3.9.3" auf "react-native-onesignal": "^4.0.3" durchgefĂŒhrt. Ich bekomme jetzt AbstĂŒrze. Ich habe den Init-Code wie oben aktualisiert. Ich habe frisch hinzugefĂŒgt.
...
let device = wait OneSignal.getDeviceState();
...
Aus dem Play Store-Absturzprotokoll
java.lang.NullPointerException:
unter com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java)
at java.lang.reflect.Method.invoke (Method.java)
unter com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java)
unter com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java)
unter com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java)
bei android.os.Handler.handleCallback (Handler.java:739)
bei android.os.Handler.dispatchMessage (Handler.java:95)
unter com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java)
bei android.os.Looper.loop (Looper.java:148)
unter com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java)
bei java.lang.Thread.run (Thread.java:818)
Firebase-Absturzprotokoll
Schwerwiegende Ausnahme: java.lang.NullPointerException: Versuch, die virtuelle Methode 'org.json.JSONObject com.onesignal.g0.a()' fĂŒr eine Null-Objektreferenz aufzurufen
unter com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState(RNOneSignal.java:4)
at java.lang.reflect.Method.invoke(Method.java)
Hallo,
Vielen Dank fĂŒr die Informationen, aber wenn jemand ein Codebeispiel bereitstellen könnte, wĂ€re das sehr hilfreich. Diese
const getDeviceState = async () => {
const deviceState = wait OneSignal.getDeviceState();
console.log ({ GerÀtestatus });
}
liefert nicht genĂŒgend Informationen, um sie zu reproduzieren. Was wir brauchen, ist etwas mehr Kontext, wie und wo dies verwendet wird.
ZB: In welcher Beziehung steht der Aufruf von getDeviceState
zur OneSignal-Initialisierung? oder in welcher RN-Lifecycle-Funktion wird das aufgerufen?
Bitte stellen Sie sicher, dass Sie den gesamten Kontext bereitstellen, der zur Behebung dieses Problems erforderlich ist, da die bereitgestellten Stack-Traces nicht ganz das bieten, was wir benötigen.
Ich vermute, dass dies passieren könnte, wenn getDeviceState
zu schnell aufgerufen wird. Können Sie versuchen, getDeviceState
an einen Punkt in Ihrem Code zu verschieben, der garantiert ausgefĂŒhrt wird, nachdem die OneSignal-Initialisierung abgeschlossen ist? zB: fĂŒgen Sie es in den RĂŒckruf zum AbonnementĂ€nderungsbeobachter ein.
Denken Sie daran, dass getDeviceState
einen Snapshot zum Zeitpunkt des Aufrufs erfasst. Aus diesem Grund den Zustand nicht zwischenspeichern, sondern bei Bedarf neu abrufen.
@rgomezp
Hallo, in der App.tsx, unserem Einstiegspunkt, haben wir:
const oneSignalIntialize = async () => {
OneSignal.setAppId('xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx');
}
const App = () => {
useEffect(() => {
oneSignalIntialize();
}, []);
return (
<LoginFlow />
);
}
Nach dem Login-Flow, wenn dies erfolgreich war, haben wir einen Willkommensbildschirm:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
const WelcomeScreen = () => {
useEffect(() => {
getDeviceState();
}, []);
return (
<Components />
);
}
Hallo @renatobentorocha ,
Danke, dass du den Code mit uns teilst!
Der useEffect-Hook hier kann aufgerufen werden, um das SDK innerhalb der Hauptkomponente der App zu initialisieren. Dies ist im Wesentlichen ein asynchroner Aufruf, der aufgerufen wird, sobald die Komponente bereitgestellt wird, aber es gibt keinen Status, der ĂŒberprĂŒft, ob die Initialisierung abgeschlossen wurde.
Sie können den useState-Hook verwenden, um einen Status hinzuzufĂŒgen, um den Init-Status zu ĂŒberprĂŒfen, bevor der BegrĂŒĂungsbildschirm wiedergegeben wird.
Eine weitere Empfehlung, wie von @rgomezp vorgeschlagen , wĂ€re, es im RĂŒckruf an den addSubscriptionObserver auszufĂŒhren (sorry, dass ich zuvor zu schnell ĂŒber den veralteten getPermissionSubscriptionState gesprochen habe), was garantiert, dass das SDK erfolgreich initialisiert wurde, bevor auf den GerĂ€tezustand zugegriffen wird.
Lassen Sie uns wissen, ob dies zur Lösung des Problems beitrÀgt,
Danke
Hallo @tyang1 Danke durch Aufmerksamkeit, aber die One-Signal-Dokumente fĂŒr diesen RĂŒckruf (getPermissionSubscriptionState) sagen:
Ich teste mit addSubscriptionObserver
und werde dich wissen lassen, was passiert ist
Bekomme das auch. WeiĂ nicht, wie man reproduziert. @rgomezp vielleicht ist es ein Threading-Problem? Dies geschieht zufĂ€llig, aber ziemlich oft. In unserem Absturzbericht sehen wir viele Spuren dafĂŒr
Hallo,
Ich glaube nicht, dass dies ein Threading-Problem ist, da die Stack-Traces darauf hinweisen, dass es wahrscheinlicher auf Wrapper-Ebene auftritt. Dies könnte sicherlich ein Bug sein. Wir brauchen nur zuverlÀssige Reproduktionsschritte, um mit einer Auflösung voranzukommen.
Es ist interessant @renatobentorocha, dass Sie berichten, dass dies zu 98% im Hintergrund geschieht.
@oferRounds @dijinshopwise sehen Sie das auch?
+1
@rgomezp folge dem 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) {
//
});
}
// ...
}
Ich habe ein Downgrade auf die alte Version durchgefĂŒhrt und Google Play warnt vor demselben Fehler.
com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState
Irgendein Vorschlag? Irgendeine Ăbergangslösung?
Wir erhalten immer noch Hunderte dieser AbstĂŒrze, irgendwelche Neuigkeiten?
@diego-paired unsere vorĂŒbergehende Problemumgehung bestand darin, den Anruf nach OneSingal-Init auf getDeviceState()
verschieben (wir haben 2 Sekunden Verzögerung hinzugefĂŒgt).
@diego-paired unsere vorĂŒbergehende Problemumgehung bestand darin, den Anruf nach OneSingal-Init auf
getDeviceState()
verschieben (wir haben 2 Sekunden Verzögerung hinzugefĂŒgt).
Danke fĂŒr den Tipp
Hallo @renatobentorocha ,
Danke, dass du den Code mit uns teilst!
Der useEffect-Hook hier kann aufgerufen werden, um das SDK innerhalb der Hauptkomponente der App zu initialisieren. Dies ist im Wesentlichen ein asynchroner Aufruf, der aufgerufen wird, sobald die Komponente bereitgestellt wird, aber es gibt keinen Status, der ĂŒberprĂŒft, ob die Initialisierung abgeschlossen wurde.
Sie können den useState-Hook verwenden, um einen Status hinzuzufĂŒgen, um den Init-Status zu ĂŒberprĂŒfen, bevor der BegrĂŒĂungsbildschirm wiedergegeben wird.
Eine weitere Empfehlung, wie von @rgomezp vorgeschlagen , wĂ€re, es im RĂŒckruf an den addSubscriptionObserver auszufĂŒhren (sorry, dass ich zuvor zu schnell ĂŒber den veralteten getPermissionSubscriptionState gesprochen habe), was garantiert, dass das SDK erfolgreich initialisiert wurde, bevor auf den GerĂ€tezustand zugegriffen wird.
Lassen Sie uns wissen, ob dies zur Lösung des Problems beitrÀgt,
Danke
@diego-gepaart @dan-entwickler
Ich habe den Vorschlag von @rgomezp befolgt und die AbstĂŒrze treten
OneSignal.addSubscriptionObserver(() => {
OneSignal.getDeviceState().then((deviceState) => {
console.log({deviceState})
});
});
FĂŒgen Sie mithilfe der Test-App diesen Code zu einer SchaltflĂ€che hinzu:
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)
});
});
Protokoll zeigt:
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
Wenn Sie jedoch den in der KomponenteDidMount bereitgestellten Beispielcode verwenden :
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);
}
Das Protokoll zeigt:
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 ist Szenario 1 erwartetes Verhalten?
@diego-paired @renatobentorocha @dan-developer
Bitte geben Sie detailliert an, wie Sie diese Methode verwenden, und geben Sie Schritte an, die wir reproduzieren können.
@jfishman1 Sehen Sie sich die Dokumentation an . Sie werden sehen, dass getDeviceState
eine asynchrone Funktion ist, also stellen Sie sicher, dass Sie darauf warten oder ein then
.
UnabhĂ€ngig davon scheint es eine gute Möglichkeit zu geben, dies im SDK zu behandeln, um diese AbstĂŒrze zu vermeiden. Danke fĂŒrs Auftauchen. Wir werden untersuchen, welche Ănderungen vorgenommen werden können, um diese nahtloser zu handhaben.
Wenn wir uns dies etwas genauer ansehen, scheint die wahrscheinlichste Ursache dafĂŒr zu sein, dass die native Seite versucht, den GerĂ€testatus abzurufen, bevor der Kontext geladen wurde.
if (appContext == null) {
logger.error("OneSignal.initWithContext has not been called. Could not get OSDeviceState");
return null;
}
Um dies zu bestÀtigen, suchen Sie bitte nach OneSignal.initWithContext has not been called. Could not get OSDeviceState
in Ihrem nativen Logcat (zB: Ăffnen Sie Android Studio).
In der Zwischenzeit können wir anscheinend eine ĂberprĂŒfung in der Android-Bridge hinzufĂŒgen, um einen vollstĂ€ndigen Absturz zu verhindern.
Bitte beachten Sie trotzdem:
Wir empfehlen dennoch, den GerĂ€testatus nur ĂŒber den Beobachter fĂŒr AbonnementĂ€nderungen abzurufen, um sicherzustellen, dass Sie den GerĂ€testatus nicht zu frĂŒh erhalten
Vielen Dank fĂŒr Ihre Geduld.
Von #1085:
Anstatt den GerĂ€testatus-Getter ĂŒber einen Timer zu verzögern, versuchen Sie, den getDeviceState
Funktionsaufruf in den Subscription-Observer einzufĂŒgen. Auf diese Weise wissen Sie, dass es abonniert ist. z.B:
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: Dies ist jetzt in der neuesten Version 4.0.7 behoben fixed
Ich habe auf das neueste 4.0.7-Repository aktualisiert. Ich bin mir nicht sicher, ob ich an der richtigen Stelle frage, aber auf einigen iOS-Simulatoren und Android-GerÀten bekomme ich diese Felder sogar nur mit deviceState zum Beispiel wie diesem. Es gibt sogar kein userId-Feld.
{"rootTag":21,"initialProps":{}}
WARN {"hasNotificationPermission": false, "isEmailSubscribed": false, "isPushDisabled": false, "isSMSSubscribed": false, "isSubscribed": false, "notificationPermissionStatus": 0}
Hilfreichster Kommentar
Danke fĂŒr den Tipp