react-native-onesignal icon indicating copy to clipboard operation
react-native-onesignal copied to clipboard

[Bug]: Could not invoke OneSignal.addPermissionObserver

Open killerchip opened this issue 2 years ago • 12 comments

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?

  • [ ] iOS
  • [X] Android

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

  • [X] I agree to follow this project's Code of Conduct

killerchip avatar Sep 07 '23 10:09 killerchip

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.

Codesane avatar Sep 07 '23 16:09 Codesane

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 avatar Sep 07 '23 20:09 jennantilla

@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 avatar Sep 11 '23 11:09 killerchip

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.

killerchip avatar Sep 12 '23 13:09 killerchip

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

evo-sampath avatar Sep 21 '23 06:09 evo-sampath

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

emawby avatar Sep 21 '23 19:09 emawby

@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.

killerchip avatar Sep 29 '23 08:09 killerchip

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);
    });
  }, []);
};

KestasVenslauskas avatar Nov 12 '23 15:11 KestasVenslauskas

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

karthick-dmg avatar Nov 15 '23 09:11 karthick-dmg

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 avatar Dec 20 '23 03:12 mljlynch

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
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
  /**
   * 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');
    }
  };

mljlynch avatar Dec 20 '23 04:12 mljlynch

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 )

tonyjimena avatar Mar 12 '24 17:03 tonyjimena

@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 avatar Jul 17 '24 19:07 emawby

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

emawby avatar Jul 23 '24 18:07 emawby