React-native-onesignal: [АВАРИЯ] [ANDROID] NullPointerException в getDeviceState

Созданный на 6 февр. 2021  ·  28Комментарии  ·  Источник: OneSignal/react-native-onesignal

Описание:
Мы получаем несколько отчетов о сбоях из 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)
Android Possible Bug

Самый полезный комментарий

@ diego-paired нашим временным обходным решением было отложить вызов getDeviceState() после инициализации OneSingal (мы добавили 2-секундную задержку)

Спасибо за чаевые

Все 28 Комментарий

+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)

Привет, Диего,
Спасибо, что сообщили об этой проблеме.

Не могли бы вы включить код, который вы используете? Также не могли бы вы предоставить информацию о среде (например: производитель и модель устройства, ОС и т. Д.)?

Ваше здоровье

Привет, Диего,
Спасибо, что сообщили об этой проблеме.

Не могли бы вы включить код, который вы используете? Также не могли бы вы предоставить информацию о среде (например: производитель и модель устройства, ОС и т. Д.)?

Ваше здоровье

Спасибо за ответ.

Об этом сообщается на нашей консоли Google Play со скоростью около 50 сбоев в неделю, у меня нет никакого способа воспроизвести это.

image

То же самое.

info Получение информации о системе и библиотеках ...
Система:
ОС: macOS 10.15.7
Процессор: (4) x64 Intel (R) Core (TM) i5-5257U CPU @ 2,70 ГГц
Память: 36,86 МБ / 8,00 ГБ
Оболочка: 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 / версии / узел / v10.22.0 / bin / npm
Сторож: 4.9.0 - / usr / local / bin / watchman
Менеджеры:
CocoaPods: 1.10.0 - / usr / local / bin / pod
SDK:
SDK для iOS:
Платформы: iOS 13.6, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2.
Android SDK:
Уровни API: 23, 25, 26, 28, 29
Инструменты сборки: 28.0.3, 29.0.2, 29.0.3
Android NDK: не найдено
Иды:
Android-студия: 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
npmPackages:
@ response-native-community / cli: не найдено
реагировать: 16.13.1 => 16.13.1
реагировать-родной: 0.63.3 => 0.63.3
react-native-macos: не найдено
npmGlobalPackages:
реагировать-родной : не найдено

"react-native": "0.63.3",
"реагировать-родной-одинсигнал": "^ 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

Возникает такая же проблема.

"react-native": "^ 0.63.4",
"реагировать-родной-одинсигнал": "^ 4.0.3"

Я обновил "react-native-onesignal": "^ 3.9.3" до "react-native-onesignal": "^ 4.0.3". У меня сейчас вылеты. Я обновил код инициализации, как указано выше. Я добавил свежее.

...
пусть устройство = ожидание OneSignal.getDeviceState ();
...

Из журнала сбоев Play Store

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 = ждать 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 />
);

}

Screen Shot 2021-02-18 at 10 59 35

Привет @renatobentorocha!
Спасибо, что поделились с нами кодом!
Хук useEffect здесь может быть вызван для инициализации SDK в основном компоненте приложения. По сути, это асинхронный вызов, который вызывается, как только компонент монтируется, но нет состояния, которое проверяет, была ли завершена инициализация.
Взаимодействие с другими людьми
Вы можете использовать ловушку useState, чтобы добавить состояние для проверки статуса инициализации перед рендерингом экрана приветствия.
Взаимодействие с другими людьми
Другая рекомендация, предложенная @rgomezp , - запустить его в обратном вызове addSubscriptionObserver (извините за то, что я слишком быстро говорил об устаревшем getPermissionSubscriptionState ранее), что гарантирует, что SDK был успешно инициализирован до доступа к состоянию устройства.
Взаимодействие с другими людьми
Сообщите нам, поможет ли это решить проблему,
Взаимодействие с другими людьми
Спасибо
Взаимодействие с другими людьми

Привет @ tyang1 Спасибо за внимание, но в документации с одним сигналом для этого обратного вызова (getPermissionSubscriptionState) говорится:

Screen Shot 2021-02-22 at 09 07 47

Я протестирую с addSubscriptionObserver и дам вам знать, что происходит

Получение этого тоже. Не умею воспроизводить. @rgomezp, возможно, это проблема с

image

Привет,
Я не думаю, что это проблема с потоками, поскольку трассировки стека указывают на то, что это, скорее, происходит на уровне оболочки. Это определенно могло быть ошибкой. Нам просто нужны надежные шаги воспроизведения, чтобы двигаться вперед с разрешением.

Интересно, @renatobentorocha, что вы сообщили, что 98% это происходит в фоновом режиме.

@oferRounds @dijinshopwise вы тоже это видите?

+1

image

@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) {
                //
            });
        }

        // ...
}

Я перехожу на старую версию, и Google Play предупреждает об этой же ошибке.

com.geektime.rnonesignalandroid.RNOneSignal.getDeviceState

Любое предложение? Какое-нибудь временное решение?

Мы до сих пор получаем сотни таких сбоев, есть новости?
image

@ diego-paired нашим временным обходным решением было отложить вызов getDeviceState() после инициализации OneSingal (мы добавили 2-секундную задержку)

@ diego-paired нашим временным обходным решением было отложить вызов getDeviceState() после инициализации OneSingal (мы добавили 2-секундную задержку)

Спасибо за чаевые

Привет @renatobentorocha!
Спасибо, что поделились с нами кодом!
Хук useEffect здесь может быть вызван для инициализации SDK в основном компоненте приложения. По сути, это асинхронный вызов, который вызывается, как только компонент монтируется, но нет состояния, которое проверяет, была ли завершена инициализация.
Взаимодействие с другими людьми
Вы можете использовать ловушку useState, чтобы добавить состояние для проверки статуса инициализации перед рендерингом экрана приветствия.
Взаимодействие с другими людьми
Другая рекомендация, предложенная @rgomezp , - запустить его в обратном вызове addSubscriptionObserver (извините за то, что я слишком быстро говорил об устаревшем getPermissionSubscriptionState ранее), что гарантирует, что SDK был успешно инициализирован до доступа к состоянию устройства.
Взаимодействие с другими людьми
Сообщите нам, поможет ли это решить проблему,
Взаимодействие с другими людьми
Спасибо

@ diego-paired @ дан-разработчик

Я последовал предложению @rgomezp, и сбои на данный момент прекратились.

OneSignal.addSubscriptionObserver(() => {
    OneSignal.getDeviceState().then((deviceState) => {
      console.log({deviceState})
    });
  });

Используя тестовое приложение , добавили этот код к кнопке:

Ситуация 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)
});
});

Журнал показывает:

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 :

Ситуация 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);
}

Журнал показывает:

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;
      }

источник

Для подтверждения найдите OneSignal.initWithContext has not been called. Could not get OSDeviceState в своем собственном logcat (например, откройте 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. Я не уверен, что спрашиваю в нужном месте, но на некоторых симуляторах iOS и устройствах Android я даже получаю эти поля только с deviceState, например, как это. Нет даже поля userId.

{"rootTag":21,"initialProps":{}}
 WARN  {"hasNotificationPermission": false, "isEmailSubscribed": false, "isPushDisabled": false, "isSMSSubscribed": false, "isSubscribed": false, "notificationPermissionStatus": 0}
Была ли эта страница полезной?
0 / 5 - 0 рейтинги