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

เลือกแพลตฟอร์ม iOS+ Android Web Flutter Unity C++


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

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

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

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

ขอสิทธิ์รับข้อความ

ใน 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 ซึ่งให้รายละเอียดข้อมูลต่างๆ เกี่ยวกับเพย์โหลด เช่น แหล่งที่มา รหัสที่ไม่ซ้ำกัน เวลาที่ส่ง มีการแจ้งเตือนหรือไม่ และอื่นๆ เนื่องจากระบบดึงข้อความมาขณะที่แอปพลิเคชันของคุณอยู่เบื้องหน้า คุณจึงเข้าถึงสถานะและบริบทของแอปพลิเคชัน Flutter ได้โดยตรง

ข้อความที่ทำงานอยู่เบื้องหน้าและข้อความแจ้งเตือน

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

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

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

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

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

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

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

  1. และต้องไม่ใช่ฟังก์ชันที่ไม่ระบุชื่อ
  2. โดยต้องเป็นฟังก์ชันระดับบนสุด (เช่น ไม่ใช่เมธอดคลาสที่ต้องมีการเริ่มต้น)
  3. เมื่อใช้ Flutter เวอร์ชัน 3.3.0 ขึ้นไป คุณต้องใส่คำอธิบายประกอบเครื่องจัดการข้อความด้วย @pragma('vm:entry-point') ไว้เหนือการประกาศฟังก์ชัน (ไม่เช่นนั้น ระบบอาจนำออกระหว่างการทำ Tree Shaking สำหรับโหมดเผยแพร่)
@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());
}

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

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

เว็บ

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

ในการเริ่มต้นใช้งาน ให้สร้างไฟล์ใหม่ในไดเรกทอรี web และตั้งชื่อว่า firebase-messaging-sw.js ดังนี้

// See this file for the latest firebase-js-sdk version:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js");

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

const messaging = firebase.messaging();

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

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

จากนั้นต้องลงทะเบียนผู้ปฏิบัติงาน ภายในไฟล์ index.html ให้ลงทะเบียน Worker โดยแก้ไขแท็ก <script> ซึ่งจะบูตสแตรป Flutter ดังนี้

<script src="flutter_bootstrap.js" async>
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
      navigator.serviceWorker.register('firebase-messaging-sw.js', {
        scope: '/firebase-cloud-messaging-push-scope',
      });
    });
  }
</script>

หากยังคงใช้ระบบการสร้างเทมเพลตแบบเก่า คุณสามารถลงทะเบียน Worker ได้โดยแก้ไขแท็ก <script> ซึ่งจะบูตสแตรป Flutter ดังนี้

<html>
<body>
  <script>
      var serviceWorkerVersion = null;
      var scriptLoaded = false;
      function loadMainDartJs() {
        if (scriptLoaded) {
          return;
        }
        scriptLoaded = true;
        var scriptTag = document.createElement('script');
        scriptTag.src = 'main.dart.js';
        scriptTag.type = 'application/javascript';
        document.body.append(scriptTag);
      }

      if ('serviceWorker' in navigator) {
        // Service workers are supported. Use them.
        window.addEventListener('load', function () {
          // Register Firebase Messaging service worker.
          navigator.serviceWorker.register('firebase-messaging-sw.js', {
            scope: '/firebase-cloud-messaging-push-scope',
          });

          // 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;

          navigator.serviceWorker.register(serviceWorkerUrl).then((reg) => {
            function waitForActivation(serviceWorker) {
              serviceWorker.addEventListener('statechange', () => {
                if (serviceWorker.state == 'activated') {
                  console.log('Installed new service worker.');
                  loadMainDartJs();
                }
              });
            }
            if (!reg.active && (reg.installing || reg.waiting)) {
              // No active web worker and we have installed or are installing
              // one for the first time. Simply wait for it to activate.
              waitForActivation(reg.installing ?? reg.waiting);
            } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
              // When the app updates the serviceWorkerVersion changes, so we
              // need to ask the service worker to update.
              console.log('New service worker available.');
              reg.update();
              waitForActivation(reg.installing);
            } else {
              // Existing service worker is still good.
              console.log('Loading app from service worker.');
              loadMainDartJs();
            }
          });

          // If service worker doesn't succeed in a reasonable amount of time,
          // fallback to plaint <script> tag.
          setTimeout(() => {
            if (!scriptLoaded) {
              console.warn(
                'Failed to load app from service worker. Falling back to plain <script> tag.'
              );
              loadMainDartJs();
            }
          }, 4000);
        });
      } else {
        // Service workers not supported. Just drop the <script> tag.
        loadMainDartJs();
      }
  </script>
</body>

จากนั้นรีสตาร์ทแอปพลิเคชัน Flutter ระบบจะลงทะเบียนโปรแกรมทำงานและจัดการข้อความในเบื้องหลังโดยใช้ไฟล์นี้

การจัดการการโต้ตอบ

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

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

แพ็กเกจ firebase-messaging มี 2 วิธีในการจัดการการโต้ตอบนี้ ได้แก่

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

ขอแนะนำให้จัดการทั้ง 2 สถานการณ์เพื่อให้ผู้ใช้ได้รับ 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 using 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

แปลข้อความ

คุณส่งสตริงที่แปลแล้วได้ 2 วิธีดังนี้

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

วิธีใช้วิธีที่ 2 มีดังนี้

Android

  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_loc_key และ body_loc_key สำหรับข้อความที่แปลแล้วแทนการใช้คีย์ title, message และ body และตั้งค่าคีย์เหล่านั้นเป็นแอตทริบิวต์ name ของข้อความที่ต้องการแสดง

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

    {
      "android": {
         "notification": {
           "title_loc_key": "notification_title",
           "body_loc_key": "notification_message"
         }
      }
    }
    

iOS

  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";
    

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

    {
      "apns": {
         "payload": {
           "alert": {
             "title-loc-key": "NOTIFICATION_TITLE",
             "loc-key": "NOTIFICATION_MESSAGE"
           }
         }
      }
    }
    

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

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

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

Android

คุณใช้โค้ดต่อไปนี้ได้

await FirebaseMessaging.instance.setDeliveryMetricsExportToBigQuery(true);

iOS

สำหรับ 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

เว็บ

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

เมื่อย้ายข้อมูลไปยัง SDK เวอร์ชัน 9 แล้ว คุณจะใช้โค้ดต่อไปนี้ได้

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 ให้คลิกไฟล์ > ใหม่ > เป้าหมาย...
  2. โมดัลจะแสดงรายการเป้าหมายที่เป็นไปได้ ให้เลื่อนหรือใช้ตัวกรองเพื่อเลือก Notification Service Extension คลิกถัดไป
  3. เพิ่มชื่อสินค้า (ใช้ "ImageNotification" เพื่อทำตามบทแนะนำนี้) เลือก Swift หรือ Objective-C แล้วคลิกเสร็จสิ้น
  4. เปิดใช้รูปแบบโดยคลิกเปิดใช้งาน

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

Swift

ตรวจสอบว่าส่วนขยายใหม่มีสิทธิ์เข้าถึงแพ็กเกจ FirebaseMessaging swift โดยเพิ่มลงในเป้าหมาย Runner ดังนี้

  1. จากแถบนำทาง ให้เพิ่ม Firebase Apple platforms SDK: File > Add Package Dependencies...

  2. ค้นหาหรือป้อน URL ของแพ็กเกจ: none https://github.com/firebase/firebase-ios-sdk

  3. เพิ่มลงในโปรเจ็กต์ Runner: เพิ่มแพ็กเกจ

  4. เลือก FirebaseMessaging และเพิ่มลงในเป้าหมาย ImageNotification: Add Package

Objective-C

ตรวจสอบว่าส่วนขยายใหม่มีสิทธิ์เข้าถึงพ็อด 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 - ใช้ตัวช่วยส่วนขยาย

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

Swift

  1. จากแถบนำทาง ให้เลือกส่วนขยาย ImageNotification

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

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

    import UserNotifications
    import FirebaseMessaging
    
    class NotificationService: UNNotificationServiceExtension {
    
        var contentHandler: ((UNNotificationContent) -> Void)?
        var bestAttemptContent: UNMutableNotificationContent?
    
        override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
            self.contentHandler = contentHandler
            bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    
            Messaging.serviceExtension().populateNotificationContent(bestAttemptContent!, withContentHandler: contentHandler)
        }
    
        override func serviceExtensionTimeWillExpire() {
            if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
                contentHandler(bestAttemptContent)
            }
        }
    }
    

Objective-C

  1. จากแถบนำทาง ให้เลือกส่วนขยาย ImageNotification

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

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

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

    #import "NotificationService.h"
    #import "FirebaseMessaging.h"
    #import <FirebaseAuth/FirebaseAuth-Swift.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 () <NSURLSessionDelegate>
    
    @property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver);
    @property(nonatomic) 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 - เพิ่มรูปภาพลงในเพย์โหลด

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