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

[📚] Activate crashlytics in the notification service extension

Open mfbx9da4 opened this issue 2 years ago • 5 comments

Hey is there a way to activate crashlytics in the notification service extension?

mfbx9da4 avatar May 25 '22 12:05 mfbx9da4

To get firebase things in your notification service extension, you need to add your extension name as a new target in your Podfile, sort of like

https://stackoverflow.com/a/57844206/9910298

I don't have anything product-specific in one of my apps that uses multiple targets, so I can show my whole Podfile (currently with react-native 0.68.2), I define an abstract target for my whole product's brand name, then concrete targets for the 4 different targets that I use to address separate firebase back-ends (each with a different GoogleServices-Info.plist file bound to the targets via file membership in the Xcode project)

If I understand correctly and the notification service extension is a separate target, then naming it in the list of targets should get it working with firebase hooked up in it, including crashlytics?

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

# Versions used below, for quick reference / outdated+upgrade checks
$iOSMinimumDeployVersion = '11.0'
$FirebaseSDKVersion = '8.15.0' # https://firebase.google.com/support/release-notes/ios

platform :ios, $iOSMinimumDeployVersion
install! 'cocoapods', :deterministic_uuids => false

# We have problems with the CDN sometimes, this uses github directly if needed. Disabled for now.
#source 'https://github.com/CocoaPods/Specs.git'

abstract_target 'Komp.ai' do

  config = use_native_modules!

  # Flags change depending on the env values.
  flags = get_default_flags()
  flags[:hermes_enabled] = true
  
  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => flags[:hermes_enabled],
    :fabric_enabled => flags[:fabric_enabled],
    # An abosolute path to your application root.
    :app_path => "#{Dir.pwd}/.."
  )

  # Required by react-native-permissions
  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
  pod 'Permission-Calendars', :path => "#{permissions_path}/Calendars"
  pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts"
  pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
  pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
  pod 'Permission-Motion', :path => "#{permissions_path}/Motion"
  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
  pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders"

  # Use pre-compiled FirebaseFirestore
  pod 'FirebaseFirestore/WithLeveldb', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => $FirebaseSDKVersion
  $RNFirebaseAnalyticsWithoutAdIdSupport = true

  target 'Komp.aiTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'Komp.aiDev' do
  end

  target 'Komp.aiTest' do
  end

  target 'Komp.aiStaging' do
  end

  target 'Komp.aiProd' do
  end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable the next line.
  use_flipper!()

  post_install do |installer|
    react_native_post_install(installer)

    installer.aggregate_targets.each do |aggregate_target| 
      aggregate_target.user_project.native_targets.each do |target|
        target.build_configurations.each do |config|
          # Fix some library / linker errors on M1
          config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
          config.build_settings['VALID_ARCHS'] = 'arm64 x86_64'
          config.build_settings['EXCLUDED_ARCHS'] = 'i386'
        end
      end
      aggregate_target.user_project.save
    end

    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        # Using the un-qualified names means you can swap in different implementations, for example ccache
        config.build_settings["CC"] = "clang"
        config.build_settings["LD"] = "clang"
        config.build_settings["CXX"] = "clang++"
        config.build_settings["LDPLUSPLUS"] = "clang++"

        # Turn off warnings on dependencies - some of them are really really noisy
        # config.build_settings["OTHER_SWIFT_FLAGS"] = "-suppress-warnings"
        config.build_settings["GCC_WARN_INHIBIT_ALL_WARNINGS"] = "YES"
      end
    end

    __apply_Xcode_12_5_M1_post_install_workaround(installer)
  end
end

mikehardy avatar May 25 '22 13:05 mikehardy

Thanks very much will give it a go 🙂

mfbx9da4 avatar May 25 '22 15:05 mfbx9da4

Finally getting round to implementing this. @mikehardy

I don't think the above suggestion will work as many of the dependencies for the main target cannot be used in extensions ie limited by NS_EXTENSION_UNAVAILABLE_IOS and co.

I will keep digging to look for a solution.

mfbx9da4 avatar Jun 28 '22 11:06 mfbx9da4

Okay managed to make it work

  1. Podfile should look something like this
target 'MyProject' do
  pod 'GoogleUtilities'
  # ... all other react native deps
end

target 'NotificationService' do
  use_frameworks! :linkage => :static

  # Google Utilities is required to avoid archiving error "Multiple commands produce ... GoogleUtilities.framework"
  # https://github.com/CocoaPods/CocoaPods/issues/8206#issuecomment-696754566
  pod 'GoogleUtilities'
  pod 'Firebase/Crashlytics'
end

Note "GoogleUtilities" pod is needed to fix the linked issue when archiving.

  1. You will likely need to re-add your GoogleService-Info.plist file to your project. The reason I needed to re-add it is because it wasn't added to the Notification Service Extension target. Remove the file from the project and then add it again using the following instructions image

  2. Initialize firebase in the NSE swift file

import Foundation
import FirebaseCore
import FirebaseCrashlytics

class NotificationService: UNNotificationServiceExtension {
  
  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?
  
  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    // Setup crashlytics
    FirebaseApp.configure()
    let crashlytics = Crashlytics.crashlytics()
    // Manually sending unsent crash reports proved more reliable than automatic collection
    crashlytics.setCrashlyticsCollectionEnabled(false)
    crashlytics.sendUnsentReports()

    // ...
    
    
  }
  
}
  1. You will need to upload dSYM files to firebase. You should follow these instructions with one minor tweak. Step 4c should have this as the script "${PODS_ROOT}/FirebaseCrashlytics/run" since we have installed using cocoapods. Taken from this answer. Also note you have to add these steps to both the main app target and the notification service extension target. image

mfbx9da4 avatar Jun 28 '22 15:06 mfbx9da4

Re-opening as documentation is still needed

mfbx9da4 avatar Jun 29 '22 14:06 mfbx9da4

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Dec 05 '22 19:12 github-actions[bot]