รับข้อความในแอป Flutter

ข้อความขาเข้าจะได้รับการจัดการแตกต่างกันไป ขึ้นอยู่กับสถานะของอุปกรณ์ เพื่อให้เข้าใจสถานการณ์เหล่านี้และวิธีการรวม FCM เข้ากับแอปพลิเคชันของคุณเอง สิ่งสำคัญอันดับแรกคือต้องกำหนดสถานะต่างๆ ที่อุปกรณ์สามารถอยู่ได้:

สถานะ คำอธิบาย
เบื้องหน้า เมื่อเปิดแอปพลิเคชัน อยู่ในมุมมองและใช้งานอยู่
พื้นหลัง เมื่อเปิดแอปพลิเคชั่นแต่อยู่ในพื้นหลัง (ย่อเล็กสุด) ซึ่งมักเกิดขึ้นเมื่อผู้ใช้กดปุ่ม "หน้าแรก" บนอุปกรณ์ เปลี่ยนไปใช้แอปอื่นโดยใช้ตัวสลับแอป หรือเปิดแอปพลิเคชันในแท็บอื่น (เว็บ)
สิ้นสุด เมื่ออุปกรณ์ถูกล็อคหรือแอพพลิเคชั่นไม่ทำงาน

มีเงื่อนไขเบื้องต้นบางประการที่ต้องปฏิบัติตามก่อนที่แอปพลิเคชันจะสามารถรับเพย์โหลดข้อความผ่าน FCM ได้:

  • จะต้องเปิดแอปพลิเคชันอย่างน้อยหนึ่งครั้ง (เพื่อให้สามารถลงทะเบียนกับ FCM)
  • บน iOS หากผู้ใช้ปัดแอปพลิเคชันออกจากตัวสลับแอป จะต้องเปิดใหม่ด้วยตนเองเพื่อให้ข้อความพื้นหลังเริ่มทำงานได้อีกครั้ง
  • บน Android หากผู้ใช้บังคับออกจากการตั้งค่าอุปกรณ์ จะต้องเปิดใหม่ด้วยตนเองเพื่อให้ข้อความเริ่มทำงานได้
  • บนเว็บ คุณต้องขอโทเค็น (โดยใช้ getToken() ) พร้อมกับใบรับรองการพุชเว็บของคุณ

ขออนุญาติรับข้อความ

บน iOS, macOS, เว็บและ Android 13 (หรือใหม่กว่า) ก่อนที่จะสามารถรับเพย์โหลด FCM บนอุปกรณ์ของคุณได้ คุณต้องขออนุญาตจากผู้ใช้ก่อน

แพ็คเกจ firebase_messaging จัดเตรียม API อย่างง่ายสำหรับการขออนุญาตผ่านวิธี requestPermission API นี้ยอมรับอาร์กิวเมนต์ที่มีชื่อจำนวนหนึ่งซึ่งกำหนดประเภทสิทธิ์ที่คุณต้องการขอ เช่น การส่งข้อความที่มีเพย์โหลดการแจ้งเตือนสามารถเรียกเสียงหรืออ่านข้อความผ่าน Siri ได้หรือไม่ ตามค่าเริ่มต้น วิธีการร้องขอสิทธิ์เริ่มต้นที่สมเหตุสมผล API อ้างอิงมีเอกสารฉบับสมบูรณ์ว่าแต่ละสิทธิ์มีไว้เพื่ออะไร

ในการเริ่มต้น ให้เรียกใช้เมธอดจากแอปพลิเคชันของคุณ (บน iOS จะแสดงโมดอลเนทีฟบนเว็บ ส่วนโฟลว์ API ดั้งเดิมของเบราว์เซอร์จะถูกทริกเกอร์):

FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: false,
  badge: true,
  carPlay: false,
  criticalAlert: false,
  provisional: false,
  sound: true,
);

print('User granted permission: ${settings.authorizationStatus}');

คุณสมบัติ authorizationStatus ของออบเจ็กต์ NotificationSettings ที่ส่งคืนจากคำขอสามารถใช้เพื่อกำหนดการตัดสินใจโดยรวมของผู้ใช้:

  • authorized : ผู้ใช้ได้รับสิทธิ์
  • denied : ผู้ใช้ปฏิเสธการอนุญาต
  • notDetermined : ผู้ใช้ยังไม่ได้เลือกว่าจะให้สิทธิ์หรือไม่
  • provisional : ผู้ใช้ได้รับสิทธิ์ชั่วคราว

คุณสมบัติอื่นๆ ใน NotificationSettings จะส่งคืนว่ามีการเปิดใช้ ปิดใช้งาน หรือไม่รองรับการอนุญาตเฉพาะบนอุปกรณ์ปัจจุบันหรือไม่

เมื่อได้รับอนุญาตและเข้าใจสถานะอุปกรณ์ประเภทต่างๆ แล้ว แอปพลิเคชันของคุณสามารถเริ่มจัดการเพย์โหลด FCM ที่เข้ามาได้แล้ว

การจัดการข้อความ

ขึ้นอยู่กับสถานะปัจจุบันของแอปพลิเคชันของคุณ เพย์โหลดขาเข้าของ ข้อความประเภท ต่างๆ จำเป็นต้องมีการใช้งานที่แตกต่างกันเพื่อจัดการ:

ข้อความเบื้องหน้า

หากต้องการจัดการข้อความในขณะที่แอปพลิเคชันของคุณอยู่เบื้องหน้า ให้ฟังสตรีม onMessage

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print('Got a message whilst in the foreground!');
  print('Message data: ${message.data}');

  if (message.notification != null) {
    print('Message also contained a notification: ${message.notification}');
  }
});

สตรีมประกอบด้วย RemoteMessage ซึ่งแสดงรายละเอียดข้อมูลต่างๆ เกี่ยวกับเพย์โหลด เช่น แหล่งที่มา ID เฉพาะ เวลาที่ส่ง มีการแจ้งเตือนหรือไม่ และอื่นๆ เนื่องจากข้อความถูกดึงออกมาในขณะที่แอปพลิเคชันของคุณอยู่เบื้องหน้า คุณจึงสามารถเข้าถึงสถานะและบริบทของแอปพลิเคชัน Flutter ได้โดยตรง

ข้อความเบื้องหน้าและการแจ้งเตือน

ข้อความแจ้งเตือนที่มาถึงในขณะที่แอปพลิเคชันอยู่เบื้องหน้าจะไม่แสดงการแจ้งเตือนที่มองเห็นได้ตามค่าเริ่มต้น ทั้งบน Android และ iOS อย่างไรก็ตาม เป็นไปได้ที่จะแทนที่ลักษณะการทำงานนี้:

  • บน Android คุณต้องสร้างช่องทางการแจ้งเตือน "ลำดับความสำคัญสูง"
  • บน iOS คุณสามารถอัปเดตตัวเลือกการนำเสนอสำหรับแอปพลิเคชันได้

ข้อความพื้นหลัง

กระบวนการจัดการข้อความพื้นหลังจะแตกต่างกันไปตามแพลตฟอร์มดั้งเดิม (Android และ Apple) และบนเว็บ

แพลตฟอร์มของ Apple และ Android

จัดการข้อความพื้นหลังโดยการลงทะเบียนตัวจัดการ onBackgroundMessage เมื่อได้รับข้อความ การแยกจะเกิดขึ้น (เฉพาะ Android, iOS/macOS ไม่จำเป็นต้องใช้การแยกแยก) ช่วยให้คุณสามารถจัดการข้อความได้แม้ว่าแอปพลิเคชันของคุณไม่ได้ทำงานอยู่ก็ตาม

มีบางสิ่งที่ควรคำนึงถึงเกี่ยวกับตัวจัดการข้อความพื้นหลังของคุณ:

  1. จะต้องไม่ใช่ฟังก์ชันที่ไม่ระบุชื่อ
  2. จะต้องเป็นฟังก์ชันระดับบนสุด (เช่น ไม่ใช่เมธอดคลาสที่ต้องกำหนดค่าเริ่มต้น)
  3. เมื่อใช้ Flutter เวอร์ชัน 3.3.0 หรือสูงกว่า ตัวจัดการข้อความจะต้องมีคำอธิบายประกอบด้วย @pragma('vm:entry-point') เหนือการประกาศฟังก์ชัน (ไม่เช่นนั้นอาจถูกลบออกในระหว่างการเขย่าต้นไม้สำหรับโหมด release)
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();

  print("Handling a background message: ${message.messageId}");
}

void main() {
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(MyApp());
}

เนื่องจากตัวจัดการทำงานในการแยกของตัวเองนอกบริบทแอปพลิเคชันของคุณ จึงไม่สามารถอัปเดตสถานะแอปพลิเคชันหรือดำเนินการ UI ใด ๆ ที่ส่งผลกระทบต่อตรรกะได้ อย่างไรก็ตาม คุณสามารถดำเนินการตามตรรกะ เช่น คำขอ HTTP, ดำเนินการ IO (เช่น อัปเดตที่เก็บข้อมูลในเครื่อง), สื่อสารกับปลั๊กอินอื่น ๆ เป็นต้น

ขอแนะนำให้ทำตรรกะของคุณให้เสร็จโดยเร็วที่สุด การทำงานที่ใช้เวลานานและเข้มข้นจะส่งผลต่อประสิทธิภาพของอุปกรณ์ และอาจทำให้ระบบปฏิบัติการยุติกระบวนการได้ หากงานทำงานนานกว่า 30 วินาที อุปกรณ์อาจหยุดกระบวนการโดยอัตโนมัติ

เว็บ

บนเว็บ ให้เขียน JavaScript Service Worker ซึ่งทำงานในเบื้องหลัง ใช้โปรแกรมทำงานของบริการเพื่อจัดการข้อความพื้นหลัง

ในการเริ่มต้น ให้สร้างไฟล์ใหม่ในไดเร็กทอรี web ของคุณ และเรียกมันว่า firebase-messaging-sw.js :

importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js");

firebase.initializeApp({
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
});

const messaging = firebase.messaging();

// Optional:
messaging.onBackgroundMessage((message) => {
  console.log("onBackgroundMessage", message);
});

ไฟล์จะต้องนำเข้าทั้งแอปและ SDK การส่งข้อความ เริ่มต้น Firebase และเปิดเผยตัวแปรการ messaging

ถัดไปจะต้องลงทะเบียนคนงาน ภายในไฟล์รายการ หลังจาก โหลดไฟล์ main.dart.js แล้ว ให้ลงทะเบียนพนักงานของคุณ:

<html>
<body>
  ...
  <script src="main.dart.js" type="application/javascript"></script>
  <script>
       if ('serviceWorker' in navigator) {
          // Service workers are supported. Use them.
          window.addEventListener('load', function () {
            // ADD THIS LINE
            navigator.serviceWorker.register('/firebase-messaging-sw.js');

            // Wait for registration to finish before dropping the <script> tag.
            // Otherwise, the browser will load the script multiple times,
            // potentially different versions.
            var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;

            //  ...
          });
      }
  </script>

จากนั้นรีสตาร์ทแอปพลิเคชัน Flutter ของคุณ ผู้ปฏิบัติงานจะได้รับการลงทะเบียนและข้อความพื้นหลังจะได้รับการจัดการผ่านไฟล์นี้

การจัดการปฏิสัมพันธ์

เนื่องจากการแจ้งเตือนเป็นสัญญาณที่มองเห็นได้ จึงเป็นเรื่องปกติที่ผู้ใช้จะโต้ตอบกับการแจ้งเตือน (โดยการกด) ลักษณะการทำงานเริ่มต้นบนทั้ง Android และ iOS คือการเปิดแอปพลิเคชัน หากแอปพลิเคชันถูกยกเลิก แอปพลิเคชันจะเริ่มต้นขึ้น ถ้าอยู่ด้านหลังก็จะถูกนำมาอยู่เบื้องหน้า

ขึ้นอยู่กับเนื้อหาของการแจ้งเตือน คุณอาจต้องการจัดการกับการโต้ตอบของผู้ใช้เมื่อแอปพลิเคชันเปิดขึ้น ตัวอย่างเช่น หากข้อความแชทใหม่ถูกส่งผ่านการแจ้งเตือนและผู้ใช้กดข้อความนั้น คุณอาจต้องการเปิดการสนทนาที่ต้องการเมื่อแอปพลิเคชันเปิดขึ้น

แพ็คเกจ firebase-messaging มีสองวิธีในการจัดการการโต้ตอบนี้:

  • getInitialMessage() : หากแอปพลิเคชันถูกเปิดจากสถานะที่สิ้นสุด Future ที่มี RemoteMessage จะถูกส่งคืน เมื่อใช้งานแล้ว RemoteMessage จะถูกลบออก
  • onMessageOpenedApp : Stream ที่โพสต์ RemoteMessage เมื่อแอปพลิเคชันถูกเปิดจากสถานะเบื้องหลัง

ขอแนะนำให้จัดการทั้งสองสถานการณ์เพื่อให้แน่ใจว่า UX ราบรื่นสำหรับผู้ใช้ของคุณ ตัวอย่างโค้ดด้านล่างนี้สรุปวิธีการบรรลุเป้าหมายนี้:

class Application extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _Application();
}

class _Application extends State<Application> {
  // It is assumed that all messages contain a data field with the key 'type'
  Future<void> setupInteractedMessage() async {
    // Get any messages which caused the application to open from
    // a terminated state.
    RemoteMessage? initialMessage =
        await FirebaseMessaging.instance.getInitialMessage();

    // If the message also contains a data property with a "type" of "chat",
    // navigate to a chat screen
    if (initialMessage != null) {
      _handleMessage(initialMessage);
    }

    // Also handle any interaction when the app is in the background via a
    // Stream listener
    FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
  }

  void _handleMessage(RemoteMessage message) {
    if (message.data['type'] == 'chat') {
      Navigator.pushNamed(context, '/chat',
        arguments: ChatArguments(message),
      );
    }
  }

  @override
  void initState() {
    super.initState();

    // Run code required to handle interacted messages in an async function
    // as initState() must not be async
    setupInteractedMessage();
  }

  @override
  Widget build(BuildContext context) {
    return Text("...");
  }
}

วิธีที่คุณจัดการกับการโต้ตอบขึ้นอยู่กับการตั้งค่าแอปพลิเคชันของคุณ ตัวอย่างข้างต้นแสดงภาพประกอบพื้นฐานโดยใช้ StatefulWidget

แปลข้อความ

คุณสามารถส่งสตริงที่แปลแล้วได้สองวิธี:

  • จัดเก็บภาษาที่ต้องการของผู้ใช้แต่ละคนในเซิร์ฟเวอร์ของคุณ และส่งการแจ้งเตือนที่กำหนดเองสำหรับแต่ละภาษา
  • ฝังสตริงที่แปลแล้วในแอปของคุณ และใช้การตั้งค่าภาษาดั้งเดิมของระบบปฏิบัติการ

ต่อไปนี้เป็นวิธีใช้วิธีที่สอง:

หุ่นยนต์

  1. ระบุข้อความภาษาเริ่มต้นของคุณใน resources/values/strings.xml :

    <string name="notification_title">Hello world</string>
    <string name="notification_message">This is a message</string>
    
  2. ระบุข้อความที่แปลแล้วในไดเร็กทอรี values- language ตัวอย่างเช่น ระบุข้อความภาษาฝรั่งเศสใน resources/values-fr/strings.xml :

    <string name="notification_title">Bonjour le monde</string>
    <string name="notification_message">C'est un message</string>
    
  3. ในเพย์โหลดของเซิร์ฟเวอร์ แทนที่จะใช้ title , message และ body key ให้ใช้ title_loc_key และ body_loc_key สำหรับข้อความที่แปลของคุณ และตั้งค่าเป็นแอตทริบิวต์ name ของข้อความที่คุณต้องการแสดง

    เพย์โหลดข้อความจะมีลักษณะดังนี้:

    {
      "data": {
        "title_loc_key": "notification_title",
        "body_loc_key": "notification_message"
      }
    }
    

ไอโอเอส

  1. ระบุข้อความภาษาเริ่มต้นของคุณใน Base.lproj/Localizable.strings :

    "NOTIFICATION_TITLE" = "Hello World";
    "NOTIFICATION_MESSAGE" = "This is a message";
    
  2. ระบุข้อความที่แปลแล้วในไดเร็กทอรี language .lproj ตัวอย่างเช่น ระบุข้อความภาษาฝรั่งเศสใน fr.lproj/Localizable.strings :

    "NOTIFICATION_TITLE" = "Bonjour le monde";
    "NOTIFICATION_MESSAGE" = "C'est un message";
    

    เพย์โหลดข้อความจะมีลักษณะดังนี้:

    {
      "data": {
        "title_loc_key": "NOTIFICATION_TITLE",
        "body_loc_key": "NOTIFICATION_MESSAGE"
      }
    }
    

เปิดใช้งานการส่งออกข้อมูลการส่งข้อความ

คุณส่งออกข้อมูลข้อความไปยัง BigQuery เพื่อการวิเคราะห์เพิ่มเติมได้ BigQuery ช่วยให้คุณวิเคราะห์ข้อมูลโดยใช้ BigQuery SQL, ส่งออกไปยังผู้ให้บริการระบบคลาวด์รายอื่น หรือใช้ข้อมูลสำหรับโมเดล ML ที่คุณกำหนดเอง การส่งออกไปยัง BigQuery จะรวมข้อมูลที่มีอยู่ทั้งหมดสำหรับข้อความ ไม่ว่าข้อความจะเป็นประเภทใดก็ตาม หรือไม่ว่าจะส่งข้อความผ่าน API หรือตัวเขียนการแจ้งเตือนก็ตาม

หากต้องการเปิดใช้งานการส่งออก ขั้นแรกให้ทำตามขั้นตอน ที่อธิบายไว้ที่นี่ จากนั้นทำตามคำแนะนำเหล่านี้:

หุ่นยนต์

คุณสามารถใช้รหัสต่อไปนี้:

await FirebaseMessaging.instance.setDeliveryMetricsExportToBigQuery(true);

ไอโอเอส

สำหรับ iOS คุณต้องเปลี่ยน AppDelegate.m ด้วยเนื้อหาต่อไปนี้

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import <Firebase/Firebase.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:userInfo];
}

@end

เว็บ

สำหรับเว็บ คุณต้องเปลี่ยนโปรแกรมทำงานของบริการเพื่อใช้ SDK เวอร์ชัน v9 เวอร์ชัน v9 จำเป็นต้องรวมเข้าด้วยกัน ดังนั้นคุณต้องใช้บันเดิลเช่น esbuild เป็นต้น เพื่อให้โปรแกรมทำงานของบริการทำงานได้ ดู แอปตัวอย่าง เพื่อดูวิธีบรรลุเป้าหมายนี้

เมื่อคุณได้ย้ายไปยัง v9 SDK แล้ว คุณสามารถใช้โค้ดต่อไปนี้:

import {
  experimentalSetDeliveryMetricsExportedToBigQueryEnabled,
  getMessaging,
} from 'firebase/messaging/sw';
...

const messaging = getMessaging(app);
experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, true);

อย่าลืมรัน yarn build เพื่อส่งออกเวอร์ชันใหม่ของ Service Worker ของคุณไปยังโฟลเดอร์ web

แสดงภาพในการแจ้งเตือนบน iOS

บนอุปกรณ์ Apple เพื่อให้การแจ้งเตือน FCM ขาเข้าแสดงรูปภาพจากเพย์โหลด FCM คุณต้องเพิ่มส่วนขยายบริการการแจ้งเตือนเพิ่มเติมและกำหนดค่าแอปของคุณเพื่อใช้งาน

หากคุณใช้การตรวจสอบสิทธิ์โทรศัพท์ Firebase คุณต้องเพิ่มพ็อด Firebase Auth ลงใน Podfile ของคุณ

ขั้นตอนที่ 1 - เพิ่มส่วนขยายบริการแจ้งเตือน

  1. ใน Xcode คลิก File > New > Target...
  2. กิริยาจะแสดงรายการเป้าหมายที่เป็นไปได้ เลื่อนลงหรือใช้ตัวกรองเพื่อเลือก ส่วนขยายบริการการแจ้งเตือน คลิก ถัดไป
  3. เพิ่มชื่อผลิตภัณฑ์ (ใช้ "ImageNotification" เพื่อปฏิบัติตามบทช่วยสอนนี้) ตั้งค่าภาษาเป็น Objective-C แล้วคลิก Finish
  4. เปิดใช้งานรูปแบบโดยคลิก เปิดใช้งาน

ขั้นตอนที่ 2 - เพิ่มเป้าหมายให้กับ Podfile

ตรวจสอบให้แน่ใจว่าส่วนขยายใหม่ของคุณมีสิทธิ์เข้าถึงพ็อด Firebase/Messaging โดยการเพิ่มลงใน Podfile:

  1. จากนาวิเกเตอร์ ให้เปิด Podfile: Pods > Podfile

  2. เลื่อนลงไปที่ด้านล่างของไฟล์และเพิ่ม:

    target 'ImageNotification' do
      use_frameworks!
      pod 'Firebase/Auth' # Add this line if you are using FirebaseAuth phone authentication
      pod 'Firebase/Messaging'
    end
    
  3. ติดตั้งหรืออัปเดตพ็อดของคุณโดยใช้ pod install จากไดเร็กทอรี ios หรือ macos

ขั้นตอนที่ 3 - ใช้ตัวช่วยส่วนขยาย

ณ จุดนี้ ทุกอย่างควรจะยังทำงานได้ตามปกติ ขั้นตอนสุดท้ายคือการเรียกใช้ตัวช่วยส่วนขยาย

  1. จากเนวิเกเตอร์ ให้เลือกส่วนขยาย ImageNotification ของคุณ

  2. เปิดไฟล์ NotificationService.m

  3. ที่ด้านบนของไฟล์ ให้นำเข้า FirebaseMessaging.h ต่อจาก NotificationService.h ดังที่แสดงด้านล่าง

    แทนที่เนื้อหาของ NotificationService.m ด้วย:

    #import "NotificationService.h"
    #import "FirebaseMessaging.h"
    #import "FirebaseAuth.h" // Add this line if you are using FirebaseAuth phone authentication
    #import <UIKit/UIKit.h> // Add this line if you are using FirebaseAuth phone authentication
    
    @interface NotificationService ()
    
    @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
    @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
    
    @end
    
    @implementation NotificationService
    
    /* Uncomment this if you are using Firebase Auth
    - (BOOL)application:(UIApplication *)app
                openURL:(NSURL *)url
                options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
      if ([[FIRAuth auth] canHandleURL:url]) {
        return YES;
      }
      return NO;
    }
    
    - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
      for (UIOpenURLContext *urlContext in URLContexts) {
        [FIRAuth.auth canHandleURL:urlContext.URL];
      }
    }
    */
    
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
    
        // Modify the notification content here...
        [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent withContentHandler:contentHandler];
    }
    
    - (void)serviceExtensionTimeWillExpire {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        self.contentHandler(self.bestAttemptContent);
    }
    
    @end
    

ขั้นตอนที่ 4 - เพิ่มรูปภาพลงในเพย์โหลด

ในเพย์โหลดการแจ้งเตือนของคุณ คุณสามารถเพิ่มรูปภาพได้แล้ว ดูเอกสาร iOS เกี่ยวกับ วิธีการสร้างคำขอส่ง โปรดทราบว่าอุปกรณ์บังคับใช้ขนาดรูปภาพสูงสุด 300KB