描述:
我们收到了许多源自RNOneSignal.getDeviceState
的崩溃报告,堆栈跟踪如下。
它会影响每个 android SDK 版本和制造商。
环境"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
重现问题的步骤:
无法重现该问题,已在 Google Play 的崩溃仪表板上报告。
还要别的吗:
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)
你好,迭戈
感谢您报告此问题。
你能包括你正在使用的代码吗? 能否请您提供环境信息(例如:设备品牌和型号、操作系统等...)?
干杯
你好,迭戈
感谢您报告此问题。你能包括你正在使用的代码吗? 能否请您提供环境信息(例如:设备品牌和型号、操作系统等...)?
干杯
感谢您的回复。
它以每周大约 50 次崩溃的速度在我们的 Google Play 控制台上报告,我无法重现它。
同样在这里。
info 正在获取系统和图书馆信息...
系统:
操作系统:macOS 10.15.7
CPU:(4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
内存:36.86 MB / 8.00 GB
外壳:5.7.1 - /bin/zsh
二进制文件:
节点:10.22.0 - ~/.nvm/versions/node/v10.22.0/bin/node
纱线:1.22.4 - /usr/local/bin/yarn
npm: 6.14.6 - ~/.nvm/versions/node/v10.22.0/bin/npm
守望者:4.9.0 - /usr/local/bin/watchman
经理:
CocoaPods:1.10.0 - /usr/local/bin/pod
SDK:
IOS SDK:
平台:iOS 13.6、DriverKit 19.0、macOS 10.15、tvOS 13.4、watchOS 6.2
安卓SDK:
API 级别:23、25、26、28、29
构建工具:28.0.3、29.0.2、29.0.3
Android NDK:未找到
IDE:
安卓工作室:3.6 AI-192.7142.36.36.6308749
Xcode: 11.6/11E708 - /usr/bin/xcodebuild
语言:
Java:1.8.0_242 - /usr/bin/javac
Python:2.7.16 - /usr/bin/python
npm 软件包:
@react-native-community/cli:未找到
反应:16.13.1 => 16.13.1
反应原生:0.63.3 => 0.63.3
react-native-macos:未找到
npmGlobalPackages:
反应原生:未找到
“反应原生”:“0.63.3”,
"react-native-onesignal": "^4.0.1",
致命异常:java.lang.NullPointerException
尝试在空对象引用上调用虚拟方法“org.json.JSONObject com.onesignal.OSDeviceState.toJSONObject()”
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)
请提供代码片段以方便复制。
干杯
@rgomezp
错误发生在 OneSignal.getDeviceState() 调用中:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
例外是:
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)
OneSignal 和 React Native 包是:
"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
得到同样的问题。
“反应原生”:“^0.63.4”,
"react-native-onesignal": "^4.0.3"
我从“react-native-onesignal”:“^3.9.3”升级到“react-native-onesignal”:“^4.0.3”。 我现在崩溃了。 我已经更新了与上面相同的初始化代码。 我是新鲜添加的。
...
让设备 = 等待 OneSignal.getDeviceState();
...
从 Play 商店崩溃日志
java.lang.NullPointerException:
在 com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState (RNOneSignal.java)
在 java.lang.reflect.Method.invoke (Method.java)
在 com.facebook.react.bridge.JavaMethodWrapper.invoke (JavaMethodWrapper.java)
在 com.facebook.react.bridge.JavaModuleWrapper.invoke (JavaModuleWrapper.java)
在 com.facebook.react.bridge.queue.NativeRunnable.run (NativeRunnable.java)
在 android.os.Handler.handleCallback (Handler.java:739)
在 android.os.Handler.dispatchMessage (Handler.java:95)
在 com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage (MessageQueueThreadHandler.java)
在 android.os.Looper.loop (Looper.java:148)
在 com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run (MessageQueueThreadImpl.java)
在 java.lang.Thread.run (Thread.java:818)
Firebase 崩溃日志
致命异常:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“org.json.JSONObject com.onesignal.g0.a()”
在 com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState(RNOneSignal.java:4)
在 java.lang.reflect.Method.invoke(Method.java)
你好,
感谢您提供信息,但如果有人可以提供最有帮助的代码示例。 这
const getDeviceState = async() => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
并没有提供足够的信息来重现。 我们需要的是更多关于如何以及在哪里使用它的上下文。
例如:对getDeviceState
的调用与 OneSignal 初始化有何关系? 或者这是在调用什么 RN 生命周期函数?
请确保提供解决此问题所需的所有上下文,因为提供的堆栈跟踪并不能完全满足我们的需要。
我怀疑如果getDeviceState
被调用得太快,这可能会发生。 您可以尝试将getDeviceState
到代码中保证在 OneSignal 初始化完成后运行的点吗? 例如:将其放入订阅更改观察者的回调中。
请记住, getDeviceState
在调用时捕获快照。 出于这个原因,不要缓存状态,而是根据需要重新获取它。
@rgomezp
您好,在我们的入口点 App.tsx 中,我们有:
const oneSignalIntialize = async () => {
OneSignal.setAppId('xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx');
}
const App = () => {
useEffect(() => {
oneSignalIntialize();
}, []);
return (
<LoginFlow />
);
}
在登录流程之后,如果成功,我们会有一个欢迎屏幕:
const getDeviceState = async () => {
const deviceState = await OneSignal.getDeviceState();
console.log({ deviceState });
}
const WelcomeScreen = () => {
useEffect(() => {
getDeviceState();
}, []);
return (
<Components />
);
}
嗨@renatobentorocha ,
感谢您与我们分享代码!
可以调用这里的 useEffect 钩子来初始化 App 主组件中的 SDK。 这本质上是一个异步调用,在组件安装后立即调用,但没有状态检查初始化是否已完成。
有的
您可以使用 useState 钩子添加状态以在呈现欢迎屏幕之前检查初始化状态。
有的
正如@rgomezp所建议的addSubscriptionObserver的回调中运行它(对不起,我之前对已弃用的 getPermissionSubscriptionState 说得太快了),这将保证 SDK 在访问设备状态之前已成功初始化。
有的
让我们知道这是否有助于解决问题,
有的
谢谢
有的
嗨@tyang1感谢关注,但该回调的单信号文档 (getPermissionSubscriptionState) 说:
我将用addSubscriptionObserver
测试,并让您知道会发生什么
得到这个也。 不知道怎么复现。 @rgomezp可能是线程问题? 这种情况随机发生,但相当多。 我们在崩溃报告中看到了许多痕迹
你好,
我不认为这是一个线程问题,因为堆栈跟踪指向它更有可能发生在包装器级别。 这当然可能是一个错误。 我们只需要可靠的复制步骤来推进解决方案。
有趣的是@renatobentorocha ,你报告它在后台发生 98%。
@oferRounds @dijinshopwise这也是你看到的吗?
+1
@rgomezp跟随代码:
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) {
//
});
}
// ...
}
我降级到旧版本,谷歌播放警告同样的错误。
com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState
有什么建议吗? 有什么临时解决办法吗?
我们仍然收到数百起这样的崩溃,有什么消息吗?
@diego-paired 我们的临时解决方法是在 OneSingal init 之后延迟对getDeviceState()
调用(我们添加了 2 秒延迟)
@diego-paired 我们的临时解决方法是在 OneSingal init 之后延迟对
getDeviceState()
调用(我们添加了 2 秒延迟)
谢谢你的提示
嗨@renatobentorocha ,
感谢您与我们分享代码!
可以调用这里的 useEffect 钩子来初始化 App 主组件中的 SDK。 这本质上是一个异步调用,在组件安装后立即调用,但没有状态检查初始化是否已完成。
有的
您可以使用 useState 钩子添加状态以在呈现欢迎屏幕之前检查初始化状态。
有的
正如@rgomezp所建议的addSubscriptionObserver的回调中运行它(对不起,我之前对已弃用的 getPermissionSubscriptionState 说得太快了),这将保证 SDK 在访问设备状态之前已成功初始化。
有的
让我们知道这是否有助于解决问题,
有的
谢谢
@diego-paired @dan-developer
我遵循了@rgomezp 的建议,现在崩溃停止了。
OneSignal.addSubscriptionObserver(() => {
OneSignal.getDeviceState().then((deviceState) => {
console.log({deviceState})
});
});
使用test app ,将此代码添加到按钮:
情况一
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)
});
});
日志显示:
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
但是,当使用componentDidMount 中提供的
情况二
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);
}
日志显示:
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是场景 1 的预期行为吗?
@diego-paired @renatobentorocha @dan-developer 能否分享您的示例或确认上述两种情况是否都是您所看到的?
请详细说明您如何使用此方法,并包括我们重现的步骤。
@jfishman1查看文档。 你会看到getDeviceState
是一个异步函数,所以一定要等待它,或者使用then
。
无论如何,似乎有一个很好的机会在 SDK 中处理此问题以避免这些崩溃。 感谢您的浮出水面。 我们将探索可以进行哪些更改以更无缝地处理这些问题。
深入研究一下,似乎最可能的原因是本机端试图在上下文加载之前获取设备状态。
if (appContext == null) {
logger.error("OneSignal.initWithContext has not been called. Could not get OSDeviceState");
return null;
}
要确认,请在您的本地 logcat 中查找OneSignal.initWithContext has not been called. Could not get OSDeviceState
(例如:打开 Android Studio)。
与此同时,我们似乎可以在 Android 网桥中添加一个检查,以防止完全崩溃。
不管怎样,请注意:
我们仍然建议仅通过订阅更改观察器获取设备状态,以确保您不会过早获取设备状态
感谢大家的耐心等待。
来自#1085:
与其通过计时器延迟设备状态获取器,不如尝试将getDeviceState
函数调用放入订阅观察者中。 这样,您就会知道它已被订阅。 例如:
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
}
});
更新:此问题现已在最新版本 4.0.7 中修复
我更新到最新的 4.0.7 repo。 我不确定我是否问对了地方,但在一些 iOS 模拟器和 Android 设备上,我什至只使用 deviceState 获取这些字段,例如像这样的。 甚至没有 userId 字段。
{"rootTag":21,"initialProps":{}}
WARN {"hasNotificationPermission": false, "isEmailSubscribed": false, "isPushDisabled": false, "isSMSSubscribed": false, "isSubscribed": false, "notificationPermissionStatus": 0}
最有用的评论
谢谢你的提示