Push notification setup

Table of contents

Notes

Google Firebase Services setup

These are non-secret keys to link our app to the Firebase Cloud Messaging app instance.

  1. Create a Firebase account
  2. Create a project with apps (iOS + Android) in Firebase Console
    • iOS
      There is a 5 step process,
      1. “Register App”: use your app bundle id, for example “interkit.app.starter”
      2. “Download config file”: download the file and put it in ios/App/App/GoogleService-Info.plist (might have to add/drag-drop it via XCode), but do not change any code yet.
        (You can download the plist file later under Project Settings › General › Your apps › Apple apps › Fooproject.)
        The next might have changed since we wrote this and might not be necessary any more.
      3. “Add Firebase SDK”: Choose version 7.11.0. You only need to add “FirebaseMessaging”
      4. “Add initialisation code”: Skip this step! Do iOS setup below instead
    • Android
      1. Upon creation, you are prompted to download the credential file google-services.json – place it in projects/yourproject/android/app/
        (A default file for the starter project is already there, overwrite it. It has to sit there, otherwise the empty app won’t run, even when push notifications aren’t used.)

Obtain APNs for iOS setup

  1. Go to your Apple Developer Account
  2. Generate an APNs key (Apple Push Notification service) there (https://developer.apple.com/account/resources/authkeys/list) Note: A maximum of 2 keys are allowed per Apple Developer Account, a key is supposed to serve “all your apps”.
  3. Plug it into Firebase Console: Project Settings › Cloud Messageing › Apple app configuration › Apple apps › Fooproject › Upload…

Install the plugin

cd projects/yourproject
npm install --save @capacitor/push-notifications
npx cap sync

Android setup

Not much else to do, but please also read “iOS setup” below and read the linked guide, it is helpful.

iOS setup

  • Do not follow the API docs mini-guide
  • Do not follow the SDK guide on Firebase Console
  • Do follow the Capacitor/ionic guide
  • but make sure you’re on v5
  • Ignore the ionic and Angular bits, especially “Using the Capacitor Push Notification API” - this has been taken care of.
  • You can start at “Creating a Project for your App on Firebase” - there is a bit of overlap with our guide above.
  • Crucially, follow the CocoPods and AppDelegate bits:
#(XCode)/Pods/Podfile

#...
target 'App' do
  capacitor_pods
  # Add your Pods here
  pod 'Firebase/Messaging' # 👈 add this line
end
#...

Then npx cap update ios to update new Pods. This might take a minute.

// projects/yourproject/ios/App/App/AppDelegate.swift

import UIKit
import Capacitor
import Firebase // 👈 add this line

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    FirebaseApp.configure() // 👈 add this line
    return true
  }

  // 👇add these two funcs

  func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
    Messaging.messaging().token(completion: { (token, error) in
      if let error = error {
          NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
      } else if let token = token {
          NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: token)
      }
    })
  }
  
  func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
  }

  // ...

In XCode, add “Push Notifications” capability. If you are missing this specific capability, check if your Apple Developer Account is “paid”, it doesn’t work for free/expired accounts.

Provide credentials

These are private keys to be kept secret, get them from Firebase Console (Project settings › Service accounts › Firebase Admin SDK › Generate new private key -> it’s ~2k of cert looking JSON). Provide them to the app:

  1. via Database Sheet: in a sheet named config, with columns “key” and “value” (you just need to name the columns, the key can stay a uuid), create a row with a special key firebaseAdminCredentials, paste the JSON in value.
  2. if this sheet does not exist, we check if a JSON file is present
    1. in a path provided by .env var FCM_CREDENTIALS_PATH, file name PROJECTID_firebase-admin.json, if not there, then we try
    2. in the project folder (found via .env REPOSITORIES_PATH), file name firebase-admin.json.

Push notification icon on Android

(Not supported on iOS, it just uses the launcher icon)

  • Create a white-on-transparent (with alpha) icon.
  • The mipmap/intermediates will be 24/36/48/72/96 pixels, named mdpi/hdpi/xhdpi/xxhdpi/xxxhdpi.
    Beware with pixel art!
  • To create the intermediates and place the files in the correct folders, you can use Android Asset Studio:
    • open Android Studio, go to (the default) “Android view”. You should see the project file tree on the left
    • find app/res, right click, Create New › Image Asset
    • Follow the wizard.
      Don’t use dash/minus in the filename, underscores are ok.
      This tool will apparently scale every image, even if it is redundant/unnecessary. Do it manually to avoid aliasing artifacts.
  • android/app/src/main/res/drawable-[mhx]+dpi/our_icon_name.png will be created. Overwrite them (or create them manually at the correct dimensions in the first place).
  • There is also an online tool: romannurik.github.io/AndroidAssetStudio/.
  • Link the resource: edit android/app/src/main/AndroidManifest.xml, to the <application> node add this child node:
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/our_icon_name" />
    See also relevant Capacitor docs
  • npx cap sync android
  • Compile, run, debug… done.
  • With more effort, full-color (over white-on-transparent) might be possible, or just re-coloring/hue-ing the white icon. Consider
    Firebase Docs
    this Stack Overflow Q