firebase-ios-sdk icon indicating copy to clipboard operation
firebase-ios-sdk copied to clipboard

FR: Support iOS 16 Simulator on Firebase Messaging

Open ispiropoulos opened this issue 3 years ago • 4 comments

Feature proposal

  • Firebase Component: Messaging

Trying to test remote notifications via Firebase Messaging on an Apple Silicon Mac with macOS Ventura and Xcode 14. Getting this log message:

2022-06-30 15:56:00.487199+0300 my-project[75680:3976914] 9.2.0 - [FirebaseMessaging][I-FCM023014] Running InstanceID on a simulator doesn't have APNS. Use prod profile by default.

And notification sending fails with this error: "errorCode": "UNREGISTERED"

The proposed change is to support iOS 16 simulators.

ispiropoulos avatar Jun 30 '22 13:06 ispiropoulos

Thanks for the feature request. From the Xcode 14 Release notes:

Simulator now supports remote notifications in iOS 16 when running in macOS 13 on Mac computers with Apple silicon or T2 processors. Simulator supports the Apple Push Notification Service Sandbox environment. Your server can send a remote notification to your app running in that simulator by connecting to the APNS Sandbox (api.sandbox.push.apple.com). Each simulator generates registration tokens unique to the combination of that simulator and the Mac hardware it’s running on. See User Notifications for more information.

Remote Notifications support more features (like Notification Service Extensions) than locally simulated notifications using .apns payload files or the simctl push command.

Device Registration Tokens are of variable length. Tokens in Simulator may be larger than current physical device tokens. Don’t hardcode any specific length or format for these tokens. (60974170)

paulb777 avatar Jun 30 '22 14:06 paulb777

If you are interested about a temporary workaround, while we wait for this to be implemented, you can do the following:

  1. Build and run your app on a device trough Xcode
  2. Go to your app's DerivedData folder -> Build/Products/Dev-iphoneos/{YOUR_APP_NAME}.app
  3. Copy the embedded.mobileprovision to your project and add it as a resource to the app - we need this, because the code here is trying to identify the environment form the provisioning profile which defaults to production if no profile is found , but the Simulator supports only the sandbox environment.
  4. Declare the following Objective-C Category in your code:

GULAppEnvironmentUtil+SimulatorPN.h

@import GoogleUtilities_Environment;
@interface GULAppEnvironmentUtil (SimulatorPN)
@end

GULAppEnvironmentUtil+SimulatorPN.m

#import "GULAppEnvironmentUtil+SimulatorPN.h"
#import <objc/runtime.h>

@implementation GULAppEnvironmentUtil (SimulatorPN)

+(void)load {
  Method original = class_getClassMethod([self class], @selector(isSimulator));
  Method swizzled = class_getClassMethod([self class], @selector(isSimulator_PN));
  method_exchangeImplementations(original, swizzled);
}

+ (BOOL)isSimulator_PN {
  return NO;
}

@end

Run your app in the Simulator and you will be able to receive push notifications from Firebase in the Simulator.

Keep in mind that the solution should only be applied when running in simulator.

KoCMoHaBTa avatar Oct 26 '22 09:10 KoCMoHaBTa

If you are interested about a temporary workaround, while we wait for this to be implemented, you can do the following:

  1. Build and run your app on a device trough Xcode
  2. Go to your app's DerivedData folder -> Build/Products/Dev-iphoneos/{YOUR_APP_NAME}.app
  3. Copy the embedded.mobileprovision to your project and add it as a resource to the app - we need this, because the code here is trying to identify the environment form the provisioning profile which defaults to production if no profile is found , but the Simulator supports only the sandbox environment.
  4. Declare the following Objective-C Category in your code:

GULAppEnvironmentUtil+SimulatorPN.h

@import GoogleUtilities_Environment;
@interface GULAppEnvironmentUtil (SimulatorPN)
@end

GULAppEnvironmentUtil+SimulatorPN.m

#import "GULAppEnvironmentUtil+SimulatorPN.h"
#import <objc/runtime.h>

@implementation GULAppEnvironmentUtil (SimulatorPN)

+(void)load {
  Method original = class_getClassMethod([self class], @selector(isSimulator));
  Method swizzled = class_getClassMethod([self class], @selector(isSimulator_PN));
  method_exchangeImplementations(original, swizzled);
}

+ (BOOL)isSimulator_PN {
  return NO;
}

@end

Run your app in the Simulator and you will be able to receive push notifications from Firebase in the Simulator.

Keep in mind that the solution should only be applied when running in simulator.

Hi, do you know the xamarin/c# variant for this workaround?

Thank you

AlleSchonWeg avatar Nov 14 '22 14:11 AlleSchonWeg

No idea, but the solution is using method swizzling. You can check if this can help you.

KoCMoHaBTa avatar Nov 16 '22 16:11 KoCMoHaBTa