react-native-push-notification / ios

React Native Push Notification API for iOS.
MIT License
753 stars 288 forks source link

React Native push notifications not working in iOS. #443

Open sukantasamanta96 opened 5 months ago

sukantasamanta96 commented 5 months ago

I am trying to set up the push notification for iOS for React Native version 0.71.7. I have done all the setup for this push notification which is mentioned in your git repository. Push notification was working fine for my old version of project 0.67.2. But in this new version, it is not working. Please help me out to solve this problem.

Mechine Configaration :- Mac Os Version:- 14.4.1 Xcode Version:- 15.3 Node Version:- v20.12.0 RN Version:- 0.71.7

Sample code base which i am using in the index.js import { SafeAreaView, Text, View } from 'react-native'; import React, { Component } from 'react'; import PushNotificationIOS from "@react-native-community/push-notification-ios"; import PushNotification from "react-native-push-notification"; export default class App extends Component { constructor(props) { super(props); this.state = { deviceToken: "" }; }

componentDidMount() { this._getToken(); const type = 'notification'; PushNotificationIOS.addEventListener(type, this.onRemoteNotification); return () => { PushNotificationIOS.removeEventListener(type); }; }

onRemoteNotification = (notification) => { const isClicked = notification.getData().userInteraction === 1; if (isClicked) { // Navigate user to another screen } else { // Do something else with push notification } // Use the appropriate result based on what you needed to do for this notification const result = PushNotificationIOS.FetchResult.NoData; notification.finish(result); };

// get RCM token for push notification _getToken = () => { let that = this;

// Must be outside of any component LifeCycle (such as `componentDidMount`).
PushNotification.configure({
  // (optional) Called when Token is generated (iOS and Android)
  onRegister: function (token) {
    // return (token);
    console.log(">>>>>>>>>>>", token.token);
    that.setState({ deviceToken: token.token });
  },

  // (required) Called when a remote is received or opened, or local notification is opened
  onNotification: function (notification) {
    console.log("NOTIFICATION:>>>>>>>>", notification);

    // process the notification
    const { foreground, userInteraction, title, message } = notification;
    if (foreground && (title || message) && !userInteraction)
      PushNotification.localNotification(notification);
    // (required) Called when a remote is received or opened, or local notification is opened
    notification.finish(PushNotificationIOS.FetchResult.NoData);
  },

  // getMessage: function()

  // (optional) Called when Registered Action is pressed and invokeApp is false, if true onNotification will be called (Android)
  onAction: function (notification) {
    // console.log("ACTION:", notification.action);
    // console.log("NOTIFICATION:", notification);
    // process the action
  },

  // (optional) Called when the user fails to register for remote notifications. Typically occurs when APNS is having issues, or the device is a simulator. (iOS)
  onRegistrationError: function (err) {
    console.error(err.message, err);
  },

  // IOS ONLY (optional): default: all - Permissions to register.
  permissions: {
    alert: true,
    badge: true,
    sound: true,
  },

  // Should the initial notification be popped automatically
  // default: true
  popInitialNotification: true,

  /**
   * (optional) default: true
   * - Specified if permissions (ios) and token (android and ios) will requested or not,
   * - if not, you must call PushNotificationsHandler.requestPermissions() later
   * - if you are not using remote notification or do not have Firebase installed, use this:
   *     requestPermissions: Platform.OS === 'ios'
   */
  requestPermissions: true,
});

PushNotification.localNotification({
  ignoreInForeground: true,
});

};

render() { return ( <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text style={{ fontSize: 20 }}>App ) } }

I am sharing the reference screenshots.

Screenshot 2024-06-10 at 6 51 48 PM Screenshot 2024-06-10 at 6 54 56 PM Screenshot 2024-06-10 at 6 55 31 PM Screenshot 2024-06-10 at 6 56 00 PM Screenshot 2024-06-10 at 6 56 36 PM

Please help me to solve this problem i have been suffering from this problem for a long time after upgrading the React native project version.

Saad-Bashar commented 3 months ago

Did you figure it out?

sukantasamanta96 commented 3 months ago

Hi @Saad-Bashar, I tried all the natatory steps which ate mentioned in the documents but failed to resolve this. I fix the issue with "@react-native-firebase/messaging" module.

go-cristian commented 2 months ago

I was able to hack this by giving some time to report the notification arrived, I added something like this in my AppDelegate:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [RNCPushNotificationIOS didReceiveNotificationResponse:response];
});
iChristosK commented 2 months ago

Any updates on this?

kevindice commented 3 weeks ago

I would 2nd that you probably want to have some delay here. Here's mine.

(We happen to use Adobe's marketing cloud, so the notification response (pressed/dismissed) is tracked for marketing analytics purposes too.)

tl;dr, wrap in dispatch_async(dispatch_get_main_queue(), ^{ ... } and you're probably good.

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
             withCompletionHandler:(void (^)(void))completionHandler {

  dispatch_async(dispatch_get_main_queue(), ^{
    [RNCPushNotificationIOS didReceiveNotificationResponse:response];
    [AEPMobileMessaging handleNotificationResponse:response
        urlHandler:^(NSURL *url) {
          // Returns "false" for adobe assurance URLs and "true" for all other
          // URLs.
          //
          // Here "false" means that the SDK will handle the URLs and "true"
          // means that the host app will handle the URL.
          return !([url.path containsString:@"adobeassurance"] ||
                   [url.scheme containsString:@"http"]);
        }
        closure:^(AEPPushTrackingStatus status) {
          // we don't actually care about doing anything here
        }];

    completionHandler();
  });
}

Please excuse the ugly formatting. I use clang-format -i --sort-includes=0 --style=LLVM and apparently this is what it does.