aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.12k forks source link

PushNotification.onRegister called on Android, but not called on iOS #7738

Closed my-name-is-nheo closed 3 years ago

my-name-is-nheo commented 3 years ago

Describe the bug Using AWS Pinpoint to send push notifications to my Amplify project in React-Native.I followed the steps on documentation to set up for both platforms and react-native-push-notification-ios to augment my AppDelegate files. Running my application on physical devices, I was able to get the token for android and send a FCM push notification on the pinpoint console. (Filled in Device token, Push Notification set to FCM). For some reason, I cannot get the token for iOS.

To Reproduce Steps to reproduce the behavior:

For Android

  1. followed these
  2. Working fine
  3. For iOS

  4. followed these
  5. Added capabilities: background mode - remote notification as instructed.
  6. Augmented AppDelegate files.

Expected behavior see a console log of device token when app is ran the first time ( been uninstalling continuously for this step )

Screenshots If applicable, add screenshots to help explain your problem.

What is Configured?

const awsconfig = {
  Auth: {
    identityPoolId: 
    region:
    userPoolId: '
    userPoolWebClientId: 
  },
  Storage: {
    bucket: 
    region: 
  },
  Analytics: {
    disabled: false,
    AWSPinpoint: {
      appId: 
      region: 
      requestIOSPermissions: true,
      requestPermissions: true,
    },
  },
  API: {
    endpoints: [],
  },
};

Amplify.configure(awsconfig);
// PushNotification.configure(awsconfig);

PushNotification.onRegister(async (token) => {
  console.log('in app registration', token);
  await AsyncStorage.setItem('appEndpointId', token);
  console.log('token set to asyncstorage');
});

// works on android. but not on ios.
// NativeModules.RNPushNotification.getToken((token) => {
//   console.log(`PushToken: ${token}`);
// });
PushNotification.onNotification((notification) => {
  console.log('in app notification', notification);
  if (Platform.OS === 'ios') {
    notification.finish(PushNotificationIOS.FetchResult.NoData);
  }
});

PushNotification.onNotificationOpened((notification) => {
  console.log('the notification is opened', notification);
});

if (Platform.OS === 'ios') {
  PushNotification.requestIOSPermissions();
}

class RootComponent extends React.Component {

Smartphone (please complete the following information):

Additional context

I have also attached the AppDelegate Files. When creating a new certificate in apple's developer, I selected Apple Push Notification SSL (Sandbox & Production) and selected an existing App ID. I checked IAM Policy permissions on my AWS account, I have full access to every service. I have enabled Push notifications and remote notifications on background modes through XCode. My theory is that I may have used the incorrect certificate when generate the p12. How do i know which certificate to use? I have my app on testflight already, how can i tell from Developer console which certificate I used? Any suggestions...?

AppDelegateH AppDelegateM1 AppDelegateM2 AppDelegateM13

kfernandes29 commented 3 years ago

I can't get it to call onRegister for my iPad app but it's working just fine for my iPhone app. Doesn't make sense to me.

my-name-is-nheo commented 3 years ago

@kfernandes29 how does your app.js look like? Do my app delegate files have the right lines? When creating a new certificate on Developer, which service did you pick?

my-name-is-nheo commented 3 years ago

@amhinson

kfernandes29 commented 3 years ago

@kfernandes29 how does your app.js look like? Do my app delegate files have the right lines? When creating a new certificate on Developer, which service did you pick?

Hey, oddly enough it started working by running this again:

npm install aws-amplify @aws-amplify/pushnotification @react-native-community/push-notification-ios

amhinson commented 3 years ago

Ah good to know! So you aren't having problems anymore?

my-name-is-nheo commented 3 years ago

@kfernandes29 how does your app.js look like? Do my app delegate files have the right lines? When creating a new certificate on Developer, which service did you pick?

Hey, oddly enough it started working by running this again:

npm install aws-amplify @aws-amplify/pushnotification @react-native-community/push-notification-ios

@kfernandes29 I will give this a try right now

@amhinson please don't close this yet.

my-name-is-nheo commented 3 years ago

@kfernandes29 so confused on how that made a difference but thank you. it works perfectly now :)

@amhinson do you have any idea on why reinstall the packages solved the issue...?

amhinson commented 3 years ago

I am unsure, unfortunately. There is a chance that aws-amplify and @aws-amplify/pushnotification were out of sync, which has been known to cause issues. In general, we recommend keeping all Amplify dependencies up to date and in sync.

I'm going to close this issue for now, but feel free to reopen it if you're still having issues! 🙏

my-name-is-nheo commented 3 years ago

I am unsure, unfortunately. There is a chance that aws-amplify and @aws-amplify/pushnotification were out of sync, which has been known to cause issues. In general, we recommend keeping all Amplify dependencies up to date and in sync.

I'm going to close this issue for now, but feel free to reopen it if you're still having issues! 🙏

@amhinson thank you for your fast response!

vivekvt commented 3 years ago

PushNotification.onRegister(async (token) => { await AsyncStorage.setItem('deviceToken', token); console.log(PushNotification.onRegister: ${token}); PushNotification.updateEndpoint(token); });

PushNotification.onRegister not called on iOS

It is working fine on android

I followed everything as told in - https://docs.amplify.aws/lib/push-notifications/getting-started/q/platform/js

amhinson commented 3 years ago

@vivekvt There is a note in the docs about how onRegister is only called when the token is originally generated or updated: https://docs.amplify.aws/lib/push-notifications/working-with-api/q/platform/js

Do you think that might be what you are seeing?

Also, are you running it on a physical device or simulator?

vivekvt commented 3 years ago

@vivekvt There is a note in the docs about how onRegister is only called when the token is originally generated or updated: https://docs.amplify.aws/lib/push-notifications/working-with-api/q/platform/js

Do you think that might be what you are seeing?

Also, are you running it on a physical device or simulator?

@amhinson I am running on iOS simulator

amhinson commented 3 years ago

Ah ok. The iOS simulator is unable to receive remote push notifications, so you'll have to use a physical device to test.

vivekvt commented 3 years ago

Ah ok. The iOS simulator is unable to receive remote push notifications, so you'll have to use a physical device to test. @amhinson I tried on physical iOS device. still I didn't got any token. (PushNotification.onRegister not called on iOS)

amhinson commented 3 years ago

Hmm interesting. Can you verify that you've done step 5 from the docs regarding adding the capability and updating the AppDelegate files? It'd also be helpful to see your AppDeletegate.m & AppDeletegate.h.

vivekvt commented 3 years ago

@amhinson

Step 5 from - AMPLIFY PUSH NOTIFICATIONS DOC

I made all changes told in - @react-native-community/push-notification-ios doc

Add Capabilities

Screenshot 2021-02-26 at 1 31 25 AM

Augment AppDelegate

AppDelegate.h

#import <UserNotifications/UNUserNotificationCenter.h>
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UIViewController *rootViewController;

@end

AppDelegate.m

#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLinkingManager.h>
#import <Stripe/Stripe.h>

#import "RNBootSplash.h"

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"mobile"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;

  self.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  [Stripe setDefaultPublishableKey:@"<placeholder>"];
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];

  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

  return YES;
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"packages/mobile/index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end
amhinson commented 3 years ago

Hmm interesting! Can you share your package.json?

my-name-is-nheo commented 3 years ago

@vivekvt yea seems like everything was set up properly . I would try reinstalling node modules and pod file. If that didn't work, my guess is something may be wrong with your certificate. Have you done this part? Link

vivekvt commented 3 years ago

Hmm interesting! Can you share your package.json?

@amhinson package.json

{
  "name": "@mobile",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "android:clean": "cd android &&./gradlew clean",
    "android:build": "cd android &&./gradlew assembleRelease",
    "ios": "react-native run-ios --simulator \"iPhone 12 Pro Max\"",
    "ios:clean": "cd ios && xcodebuild clean",
    "pod:install": "cd ios && pod install",
    "start": "react-native start",
    "splash": "npx react-native generate-bootsplash ./assets/splash.png",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "@apollo/client": "^3.2.7",
    "@aws-amplify/analytics": "^4.0.11",
    "@aws-amplify/pushnotification": "^3.2.23",
    "@parkyourself-frontend/shared": "*",
    "@react-native-community/async-storage": "^1.12.0",
    "@react-native-community/datetimepicker": "2.4.0",
    "@react-native-community/geolocation": "^2.0.2",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-community/netinfo": "^5.9.7",
    "@react-native-community/picker": "^1.7.1",
    "@react-native-community/push-notification-ios": "^1.8.0",
    "@react-navigation/bottom-tabs": "^5.8.0",
    "@react-navigation/drawer": "^5.9.0",
    "@react-navigation/material-top-tabs": "^5.3.10",
    "@react-navigation/native": "^5.7.3",
    "@react-navigation/stack": "^5.9.0",
    "amazon-cognito-identity-js": "^4.5.5",
    "aws-amplify": "^3.3.20",
    "aws-appsync": "^4.0.1",
    "formik": "^2.2.5",
    "moment": "^2.28.0",
    "moment-range": "^4.0.2",
    "prop-types": "15.7.2",
    "react": "*",
    "react-hook-form": "^6.15.1",
    "react-native": "0.63.4",
    "react-native-bootsplash": "^3.1.3",
    "react-native-calendars": "^1.403.0",
    "react-native-camera": "^3.42.1",
    "react-native-date-picker": "^3.2.9",
    "react-native-daterange-picker": "^1.5.1",
    "react-native-dates": "^2.0.4",
    "react-native-gesture-handler": "^1.7.0",
    "react-native-google-places-autocomplete": "^1.8.2",
    "react-native-image-picker": "^3.1.4",
    "react-native-inappbrowser-reborn": "^3.5.1",
    "react-native-maps": "0.27.1",
    "react-native-paper": "^4.7.2",
    "react-native-permissions": "^3.0.0",
    "react-native-qrcode-scanner": "^1.5.3",
    "react-native-qrcode-svg": "^6.1.1",
    "react-native-range-datepicker": "^1.9.1",
    "react-native-ratings": "^7.4.0",
    "react-native-reanimated": "1.13.0",
    "react-native-safe-area-context": "^3.1.7",
    "react-native-screens": "^2.10.1",
    "react-native-share": "^5.1.1",
    "react-native-svg": "^12.1.0",
    "react-native-tab-view": "^2.15.2",
    "react-native-vector-icons": "^7.0.0",
    "react-native-view-shot": "^3.1.2",
    "react-native-webview": "^11.0.0",
    "react-redux": "^7.2.1",
    "react-timekeeper": "^2.1.3",
    "reanimated-bottom-sheet": "^1.0.0-alpha.22",
    "redux": "^4.0.5",
    "redux-devtools-extension": "^2.13.8",
    "redux-persist": "^4.10.2",
    "redux-persist5": "npm:redux-persist@^6.0.0",
    "redux-thunk": "^2.3.0",
    "yup": "^0.30.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/runtime": "^7.12.5",
    "babel-jest": "^26.6.3",
    "jest": "^26.6.3",
    "metro-react-native-babel-preset": "^0.64.0",
    "react-test-renderer": "16.13.1"
  },
  "jest": {
    "preset": "react-native"
  },
  "rnpm": {
    "assets": ["./app/fonts"]
  }
}
vivekvt commented 3 years ago

@vivekvt yea seems like everything was set up properly . I would try reinstalling node modules and pod file. If that didn't work, my guess is something may be wrong with your certificate. Have you done this part? Link

@my-name-is-nheo @amhinson In xcode shall I keep Automatically allow signining ON

or Manually import provision profile which I downloaded after following this steps - https://docs.amplify.aws/sdk/push-notifications/setup-push-service/q/platform/ios#step-2-create-an-apns-ssl-certificate

my-name-is-nheo commented 3 years ago

@vivekvt i didn't have to add a provisioning profile. Weird. Did you turn on push notifications for both release and debug version from xcode?

vivekvt commented 3 years ago

@vivekvt i didn't have to add a provisioning profile. Weird. Did you turn in push notifications for both release and debug version from xcode?

@my-name-is-nheo Yes you can see in this screenshot I posted https://github.com/aws-amplify/amplify-js/issues/7738#issuecomment-786169619

I turned it on for All

my-name-is-nheo commented 3 years ago

I would try to recreate your certificate and make sure you upload the correct p12 file to AWS pinpoint .

vivekvt commented 3 years ago

@amhinson Now I am getting push notification on physical iOS device.

But I am getting this error - Pinpoint: Exceeded maximum endpoint per user count

dylan-westbury commented 3 years ago

Any version of amplify after 3.3.8 will stop receiving push notifications once pinpoint reaches maximum endpoint for user count.

Also amplify version 3.3.8 or lower has a couple of security flaws with some dependencies.

If you have an application with a later version expect push notifications to stop working for your users, although they have may appeared to be working prior to release.

This has been an issue for 6 months, refer to https://github.com/aws-amplify/amplify-js/issues/7251 . There are also other various issues opened related to this.

I have spent many weeks debugging aws-amplify push notifications on various projects, have managed to get them working eventually but generally almost every following release we do for the project they stop working, which creates a vicious cycle of debugging and resolving issues to get them working.

My advice would be to look for an alternate push notification provider as pinpoint is extremely unstable.

FYI @vivekvt

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.