[PYTHON] Implemented iOS push notifications in Firebase

At the beginning

When I tried to implement the push notification function in the iOS app, I struggled more than I expected, so I will look back.

Create a Firebase project

In the Firebase Console (https://console.firebase.google.com/?hl=en "Firebase Console"), click Add Project, select Project Name, and enter a new project name. To do.

Register your app with Firebase

  1. Once you've created your Firebase project, you can add iOS apps to your project. From the Firebase Console (https://console.firebase.google.com/?hl=ja "Firebase Console"), go to the Project Page and click the iOS icon in the center to launch the configuration workflow. To do.
  2. Enter your app's bundle ID in the iOS Bundle ID field. To find this bundle ID, open your app in XCode and go to the General tab in the top-level directory. The value in the bundle identifier field is the iOS bundle ID (for example, com.atsushi-uchida.NewsTwit).

Add a Firebase configuration file

  1. Click Download GoogleService-Info.plist to get the Firebase iOS configuration file (GoogleService-Info.plist).
  2. Move the configuration file to the root of your Xcode project. When prompted, select the option to add the configuration file to all targets.

Add the Firebase SDK to your app

We recommend using CocoaPods to install the Firebase library. -If the podfile does not exist, create it.

$ cd your-project-directory
$ pod init

-Add the pod you want to use in the app to the Podfile. For example, in the case of analytics:

$ pod 'Firebase/Analytics'

This will add the libraries needed to get Firebase running in your iOS app, along with Google Analytics for Firebase.

· Install the pod, open the .xcworkspace file and check the project in Xcode.

$ pod install
$ open your-project.xcworkspace

· Note! !! !! If you have installed the pod with CocoaPods even once, update it in the installation.

$ pod update

From the second time onward, if you use the installation, you will often get an error due to dependencies.

Move on to issue the certificate

There are seven things to create and keep in order to send push notifications.

  1. Creating a CSR file ** * If you create it for the first time, the same file will be used after that, so you do not need to create it again **
  2. Create a development certificate (.cer) ** * If you create it for the first time, the same one will be used after that, so you do not need to create it again **
  3. Create AppID
  4. Terminal registration
  5. Creating a provisioning profile
  6. Create Certificate (.cer) for APNs
  7. Creating a certificate (.p12) for APNs

1. Creating a CSR file

  1. Open Keychain Access
  2. Click Keychain Access> Certificate Assistant> Request Certificate from Certificate Authority
  3. Enter the "User's Email Address"
  4. (Leave the "common name" as it is and leave the "CA email address" blank)
  5. For "Request processing", select "Save to disk" and check "Set key pair information".
  6. Click Continue
  7. The save destination will be selected. Select any location and click "Save".
  8. Check the "Key Pair Information" screen and click "Continue".
  9. The "Setting result" screen will appear. Click "Finish".

2. Create a development certificate (.cer)

  1. Log in to the Apple Developer Program (https://developer.apple.com/account/ "Apple Developer Program")
  2. Click Certificates, Identifiers & Profiles
  3. Click Certificates, then click the "+" next to Certificates
  4. The "Create a New Certificate" screen will be displayed, so set it.
  5. Check "iOS App Development" and click "Continue" in the upper right corner.
  6. Click "Choose File", select "Create CSR File" created in 1., and click "Continue".
  7. A developer certificate will be created, so click "Download" to export it.
  8. Creation of development certificate (.cer) is complete

3. Create an App ID

    1. If the work of "Creating a development certificate (.cer)" was skipped, log in to the Apple Developer Program and click "Certificates, Identifiers & Profiles" (* 2. Image reference)
  1. Click the "+" to the right of "Identifiers"
  2. "Register a New Identifier" will be displayed. Check "App IDs" and click "Continue" in the upper right corner.
  3. Enter the outline of the app in "Description" Example) TestPushApp
  4. For Bundle ID, select Explicit and enter the Bundle ID. 6 Note that push notifications will not be available if you select "Wildcard"!
  5. Make a note of the "Bundle ID" as it will be set on the app side!
  6. Scroll down and check "Push Notifications" under "Capabilities"
  7. If you forget this, push notifications will not be available, so be careful!
  8. Click Continue
  9. A confirmation screen will be displayed. Make sure that "Push Notifications" is checked and click "Register".
  10. This completes App ID creation

4. Terminal registration

  1. Click "Devices" and then click the "+" next to "Devices"
  2. Select "Platform" for "iOS, tvOS, WatchOS"
  3. Enter the Device Name and Device ID (UDID) of the device
  4. "Device Name" can be set freely
  5. "Device ID (UDID)" is easy to check using Xcode
  6. Connect your device to your Mac and launch Xcode
  7. Click Window> Devices and Simulators
  8. You can see the UDID as an "identifier"
  9. Click Continue when you are done
  10. Check the device information on the next screen and click "Register"
  11. This completes device registration.

5. Creating a provisioning profile

  1. Click Profiles, then click the "+" next to Profiles
  2. Select "iOS App Development" under "Development" and click "Continue".
  3. Link the App ID, development certificate, and device to be used.
    1. Select the App ID created in "Create App ID" and click "Continue".
    1. Select the (or existing) development certificate created in "Creating a development certificate (.cer)" and click "Continue".
    1. Select the registered (or existing) device in "Register device" and click "Continue".
  4. Finally, enter the file name in "Provisioning Profile Name" Example) TestPushApp Provisioning Profiles
  5. Confirm the link and click "Generate"
  6. A provisioning profile will be created, so click "Download" to export it.
  7. The provisioning profile has been created.

6. Create Certificate (.cer) for APNs

  1. Click "Certificates" and then click the "+" next to "Certificates"
    1. Scroll down and check "Apple Push Notification service SSL (Sandbox)" in "Service", unlike when you created a development certificate in "Creating a development certificate (.cer)". Put in
  2. Click Continue
    1. Select the App ID created in "Create App ID" and click "Continue".
    1. Select the (or existing) CSR file created in "Create CSR File" and click "Continue".
  3. A certificate (.cer) for APNs will be created, so click "Download" to export it.
  4. Creation of certificate (.cer) for APNs is complete.

7. Creating a certificate (.p12) for APNs

    1. Double-click the "APNs Certificate (.cer)" created in "Creating APNs Certificate (.cer)" to open Keychain Access.
  1. Click the triangle mark to the left of the certificate for APNs (.cer) to open it.
  2. The key is set in the certificate (.cer) file for APNs.
  3. To export the certificate for APNs (.p12), in the open state, right-click on the certificate instead of the key and click "Export ..."
  4. Specify the file name "Name" and the save destination "Location" and click "Save".
  5. You will be prompted for a password, do not enter anything and click OK
  6. After this, the system may ask for a password. Please be corresponding.
  7. Certificate for APNs (.p12) will be exported
  8. Certificate for APNs (.p12) creation is complete
  9. You have now created all the files you need

Register APNs certificate with Cloud Messaging in Firebase

  1. Next, go to the Firebase settings screen.
  2. Select the gear icon at the top left of the screen for the target project in the Firebase Console and select the project settings.
  3. Select Cloud Messaging from the Setting menu.
  4. Scroll the screen and select Upload APNs Certificate for Development APNs Certificate in IOS App Settings.
  5. Click Upload File, select the APNs certificate you created in 7. Creating a Certificate for APNs (.p12), and select Upload.
  6. If the upload is completed here, the Firebase settings are complete.

Set Xcode Signing

  1. Next, set up Xcode. Open this screen in Xcode and select Signing & Capability.
  2. First, uncheck Automatically manage signing and set the Provisioning Profile to the Provisioning Profile created in 5. "Creating a provisioning profile".
  3. Then click + Capability to sign Push Nortifications and then drag and drop.
  4. Drag and drop Background Mode as well.
  5. Check Remote nortifications in Background Mode. This completes the Xcode settings.

Implemented processing to allow notifications and register devices in AppDelegate.swift

Finally, write the process in AppDelegate and finish. There are 4 mounting locations.

  1. import
  2. didFinishLaunchingWithOptions
  3. In the AppDelegate class
  4. UNUserNotificationCenterDelegate Extension
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       // Override point for customization after application launch.
       FirebaseApp.configure()
       if #available(iOS 10.0, *) {
           // For iOS 10 display notification (sent via APNS)
           UNUserNotificationCenter.current().delegate = self

           let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
           UNUserNotificationCenter.current().requestAuthorization(
               options: authOptions,
               completionHandler: {_, _ in })
       } else {
           let settings: UIUserNotificationSettings =
               UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
           application.registerUserNotificationSettings(settings)
       }

       application.registerForRemoteNotifications()
       
       return true
   }

   // MARK: UISceneSession Lifecycle

   func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
       // Called when a new scene session is being created.
       // Use this method to select a configuration to create the new scene with.
       return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
   }

   func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
       // Called when the user discards a scene session.
       // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
       // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
   }
   
   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
       // Print message ID.
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       // Print full message.
       print(userInfo)
   }

   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
       // Print message ID.
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       // Print full message.
       print(userInfo)

       completionHandler(UIBackgroundFetchResult.newData)
   }


}

@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
   func userNotificationCenter(_ center: UNUserNotificationCenter,
                               willPresent notification: UNNotification,
                               withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
       let userInfo = notification.request.content.userInfo

       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       print(userInfo)

       completionHandler([])
   }

   func userNotificationCenter(_ center: UNUserNotificationCenter,
                               didReceive response: UNNotificationResponse,
                               withCompletionHandler completionHandler: @escaping () -> Void) {
       let userInfo = response.notification.request.content.userInfo
       if let messageID = userInfo["gcm.message_id"] {
           print("Message ID: \(messageID)")
       }

       print(userInfo)

       completionHandler()
   }
}

I think you can do it with copy and paste, so please implement it that way. The code setting is completed here. Connect the app to the actual device, start the app, and you will see a dialog to allow notifications, so leave it in the allowed state. (Notification will not be delivered without permission of notification. + Remote notification will not be delivered unless it is an actual machine.)

Send notifications from Cloud Messaging

  1. All you have to do is send a notification! Select Cloud Messaging from the Firebase Console left menu.
  2. Click Send your firdt message and enter what you want to be notified. (Appropriate and okay.) Click Next.
  3. Select your app from Select App and click Next.
  4. The schedule can be set in detail, but it's okay now. Click Next.
  5. Click Next without setting anything for the conversion event.
  6. At the end, you can finely set the notification sound ON / OFF and the quantity of IOS batch (the red circle on the upper right of the app). I'll leave the settings to you. If there are no problems, click Confirm.
  7. Finally, click Publish and the notification will be sent and the notification will be sent to the actual machine.
  8. This completes the settings and notifications.

If push notifications are not delivered correctly

  1. The document creation order is incorrect
  2. Edited the document created on the way
  3. Multiple development certificates have been created
  4. Multiple CSR files have been created
  5. I forgot to check "Push Notifications" when creating the App ID
  6. Check if the app is open on the actual device (it will not arrive if the app is open)
  7. You may not be able to allow notifications properly, so delete the app and reinstall it.
  8. Check Info.plist for any strange settings. (Some articles say that it needs to be set in Info.plist, but it is not necessary.)

Push notifications using the Firebase Admin SDK

I tried push notification from the server to the smartphone using Firebase Cloud Messaging (FCM). I will write how to send push notifications from the server via Firebase.

Install Firebase Admin SDK

$ pip install firebase-admin

To authenticate your service account and authorize access to your Firebase service, you need to generate a private key file in JSON format.

Get the key file for firebase connection from Firebase console

  1. Press the gear mark at the top left of the Firebase Console (https://console.firebase.google.com/?hl=ja "Firebase Console") to open the project settings screen.
  2. From this screen, click the "Service Accounts" tab.
  3. Click the "Generate New Private Key" button to download the private key file.
  4. Securely store the JSON file containing the key.

Push notification to a specific smartphone

Send push notifications to a specific smartphone (YOUR_REGISTRATION_TOKEN). The code is below. path / to / serviceAccountKey.json specifies the downloaded private key file.

import firebase_admin
from firebase_admin import credentials
from firebase_admin import messaging

cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)

# This registration token comes from the client FCM SDKs.
registration_token = 'YOUR_REGISTRATION_TOKEN'

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(
        title='test server',
        body='test server message',
    ),
    token=registration_token,
)

# Send a message to the device corresponding to the provided
# registration token.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Push notification to smartphones participating in the topic

This is a method to push notifications to multiple smartphones participating in a specific topic. For example, when pushing notifications to smartphones participating in the "weather" topic, change the message composition part as follows. Specifically, just change the token part to topic.

message = messaging.Message(
    notification=messaging.Notification(
        title='test server',
        body='test server message',
    ),
    topic='weather',
)

Joining a topic on ios can be achieved with the following code in AppDelegate.swift.

Messaging.messaging().subscribe(toTopic: "weather") { error in
    print("Subscribed to weather topic")
}

Advanced version Add the number (badge display) on the upper right of the icon

Until now, only the title and message were used, but I'd like to add badge processing (the number on the upper right of the icon). This can be achieved with code like the following.

import firebase_admin
from firebase_admin import credentials
from firebase_admin import messaging

cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)

notification = messaging.Notification(
    title='test server',
    body='test server message',
)
topic='weather'

apns = messaging.APNSConfig(
   payload = messaging.APNSPayload(
       aps = messaging.Aps(badge = 1) #This is the part required for background notification
   )
)

message = messaging.Message(
    notification=notification,
    apns=apns,
    topic=topic,
)

response = messaging.send(message)
print('Successfully sent message:', response)

At the end

Looking back, the number of characters has become quite large. Is that so hard? Thank you for reading the long text. The following is the link that I referred to.

  1. Add Firebase to your iOS project (https://firebase.google.com/docs/ios/setup?hl=ja "Add Firebase to your iOS project")
  2. [Swift5] How to implement remote push notification
  3. How to make a certificate required for push notification 2020
  4. Push Notifications Using Firebase Admin SDK

Recommended Posts

Implemented iOS push notifications in Firebase
Send push notifications to iOS apps in Python
Send push notifications from your iOS app via Firebase Cloud Messaging
Implemented Shiritori in Python
Send push notifications to iOS apps with Python2 (with sample code)
Play with push notifications with imap4lib
Sudoku solver implemented in Python 3
6 Ball puzzle implemented in python