OneSignal / react-native-onesignal

React Native Library for OneSignal Push Notifications Service
Other
1.56k stars 371 forks source link

[Bug]: Could not invoke OneSignal.addPermissionObserver #1552

Closed killerchip closed 1 day ago

killerchip commented 10 months ago

What happened?

I have installed in an Expo app with SDK49.0.9 and custom expo 'dev-client'. Installed react-native-onesignal with onesignal-expo-plugin. I only call in 'App.tsx' OneSignal.initialize('XXXX')

And I get an error could not invoke OneSignal.addPermissionObserver on start up.

Steps to reproduce?

1. Create an expo app with SDK 49.0.9 and build a custom dev-client for android
2. expo install onesignal-expo-plugin
3. yarn add react-native-onesignal

4. edit app.json
"plugins": [["onesignal-expo-plugin", {mode: "development"}]]

5. In App.ts 
import {LogLevel, OneSignal} from 'react-native-onesignal';
OneSignal.Debug.setLogLevel(LogLevel.Verbose);
OneSignal.initialize('XXXXX');

Run the dev client

What did you expect to happen?

I expected the app to run and not crash on start up.

React Native OneSignal SDK version

5.0.0

Which platform(s) are affected?

Relevant log output

I get a screen in expo dev client stating:

There was a problem loading the project.
This development build encountered the following error:

Could not invoke OneSignal.addPermissionObserver
null
Must call with 'initWithContext' before use

invoke
JavaMethodWrapper.java

invoke
JavaModuleWrapper.java

run
NativeRunnable.java

handleCallback
Handler.java

dispatchMessage
Handler.java

dispatchMessage
Handler.java

loopOnce
Looper.java

loop
Looper.java

run
MessageQueueThredImpl.java

run
Thread.java

Code of Conduct

Codesane commented 10 months ago

The API has changed in the 5.x version.

Try using

OneSignal.Notifications.addEventListener("permissionChange", enabled => {
    console.log("Notifications Enabled: ", enabled)
})

You might have to re-build the native apk file as well.

jennantilla commented 10 months ago

Thanks, @Codesane for linking to the new method!

@killerchip please feel free to refer to our migration guide for an overview of all the changes in 5.0.0.

Let us know if you have any additional questions or concerns!

killerchip commented 10 months ago

@jennantilla @Codesane My problem still remains... I don't even use the 'addEventListener', I just add the following lines in my App.tsx

OneSignal.Debug.setLogLevel(LogLevel.Verbose);
OneSignal.initialize('XXXXX');

And I get the error.

I'm no Android expert, but I think the issue is somewhere there: indext.ts:

  export function initialize(appId: string) {
    if (!isNativeModuleLoaded(RNOneSignal)) return;

    RNOneSignal.initialize(appId);

    _addPermissionObserver();
    _addPushSubscriptionObserver();
  }

The RNOneSignal.initialize native function is supposed to initialize and run 'initWithContext'. But either this does not happen, or there's a race condition, and 'initWithContext' is not called when the _addPremissionObserver() is called.

Has my suspicion any logical base? or am I looking into the wrong direction?

killerchip commented 10 months ago

In fact I added a couple of logging in the function above, and created a log files from 'adb logcat'. I can see that the _appPermissionObserver() is called before the initWithContext is called on the native level, for some reason.

evo-sampath commented 10 months ago

Thanks, @Codesane for linking to the new method!

@killerchip please feel free to refer to our migration guide for an overview of all the changes in 5.0.0.

Let us know if you have any additional questions or concerns!

@jennantilla Thanks for the info and can you add this info in the official docs

emawby commented 10 months ago

@killerchip I am not able to reproduce this issue. Which verison of the onesignal-expo-plugin and react-native-onesignal are you using?

killerchip commented 9 months ago

@killerchip I am not able to reproduce this issue. Which verison of the onesignal-expo-plugin and react-native-onesignal are you using?

Hi @emawby , apologies for the late reply. I'm using react-native-onesignal: ^5.0.0 and onesignal-expo-plugin: ^2.0.0

and from my yan.lock I see that those versions exactly resolved.

KestasVenslauskas commented 8 months ago

Gettings Must call 'initWithContext' before use crashes. Using "react-native-onesignal": "^5.0.2",


  useEffect(() => {
    OneSignal.initialize(ONE_SIGNAL_APP_ID);

    OneSignal.Notifications.addEventListener('click', async (e) => {
      console.log('OneSignal: notification click event:', e);
    });
  }, []);
};
karthick-dmg commented 8 months ago

Gettings Must call 'initWithContext' before use crashes. Using "react-native-onesignal": "^5.0.2",

  useEffect(() => {
    OneSignal.initialize(ONE_SIGNAL_APP_ID);

    OneSignal.Notifications.addEventListener('click', async (e) => {
      console.log('OneSignal: notification click event:', e);
    });
  }, []);
};

Facing this issue on Android suddenly. It used to work earlier

mljlynch commented 7 months ago

We are also getting this error. It seems like there is a race condition when you call initialize and then try to call a OneSignal method.

mljlynch commented 7 months ago

For further context: This is happening on Android in particular - maybe related to: https://github.com/OneSignal/react-native-onesignal/issues/1554.

Example Code for initialization ```ts const handleIngredientChangeNotification = useCallback(() => { presentScreen(RootScreen.Inbox); oneSignalService.setTagToTrue('hasOpenedIngredientChangeAlert'); }, []); const handleNotification = useCallback( (notification: OSNotification) => { if (notification.additionalData) { const { type } = notification.additionalData as NotificationData; switch (type) { case NotificationEventType.IngredientChangeEvent: handleIngredientChangeNotification(); } } }, [handleIngredientChangeNotification], ); const didReceiveOpenNotificationHandler = useCallback( (event: NotificationClickEvent) => { // Handle the notification after delivery from the background handleNotification(event.notification); analyticsService.logPushNotificationEvent( AnalyticsEvent.PushNotificationOpened, { notificationId: event.notification.notificationId, templateId: event.notification.templateId ?? '', type: PushNotificationEventType.IngredientChangeNotification, }, ); }, [handleNotification], ); const didReceiveForegroundNotification = ( event: NotificationWillDisplayEvent, ) => { event.preventDefault(); const notification = event.getNotification(); notification.display(); analyticsService.logPushNotificationEvent( AnalyticsEvent.PushNotificationShownInForeground, { notificationId: notification.notificationId, templateId: notification.templateId ?? '', }, ); }; useEffect(() => { // OneSignal Init Code oneSignalService.initialize(ONESIGNAL_APP_ID); OneSignal.Debug.setLogLevel(LogLevel.Verbose); const promptForPush = async () => { if (await OneSignal.Notifications.canRequestPermission()) { OneSignal.Notifications.requestPermission(false); } }; promptForPush(); // Method for handling notifications opened OneSignal.Notifications.addEventListener( 'click', didReceiveOpenNotificationHandler, ); OneSignal.Notifications.addEventListener( 'foregroundWillDisplay', didReceiveForegroundNotification, ); return () => { OneSignal.Notifications.removeEventListener( 'click', didReceiveOpenNotificationHandler, ); OneSignal.Notifications.removeEventListener( 'foregroundWillDisplay', didReceiveForegroundNotification, ); }; }, [didReceiveOpenNotificationHandler]); ```

We are getting an error on the addTag method. This can be resolved by adding a setInterval ar

Example call to addTag ```ts /** * Calls provided function when this service has been initialized * * @param onSafe function to call */ private safeCall = (onSafe: () => void, maxTries: number = 1) => { if (this.initialized) { onSafe(); } else if (maxTries > 0) { console.log(`waiting on onesignal`); let tries = 0; const callTimer = setInterval(() => { tries++; if (this.initialized) { clearInterval(callTimer); onSafe(); } else if (tries >= maxTries) { clearInterval(callTimer); logError('exceeded maxTries for OneSignalService safeCall'); } }, 500); } else { logError('OneSignalService not initialized'); } }; ```
tonyjimena commented 4 months ago

On my case the error comes because the constant of onesignalAppId is undefined when i use with Constants.expoConfig.extra.oneSignal App Id,

Im solved using process.env OneSignal.initialize( Constants.expoConfig.extra.oneSignalAppId || process.env.EXPO_PUBLIC_ONESIGNAL_APP_ID )

emawby commented 1 week ago

@tonyjimena I am not able to reproduce that issue. Were you able to get around it? Are you sure the app id was defined in the config properly?

emawby commented 1 day ago

closing for inactivity. If this is still an issue please tag and I can reopen