ข้อความขาเข้าจะได้รับการจัดการแตกต่างกันไปตามสถานะของอุปกรณ์ เพื่อทำความเข้าใจสถานการณ์เหล่านี้และวิธีผสานรวม FCM เข้ากับแอปพลิเคชันของคุณ สิ่งสำคัญอย่างแรกคือการระบุสถานะต่างๆ ของอุปกรณ์
รัฐ | คำอธิบาย |
---|---|
เบื้องหน้า | เมื่อแอปพลิเคชันเปิดอยู่ อยู่ในมุมมอง และใช้งานอยู่ |
ความเป็นมา | เมื่อแอปพลิเคชันเปิดอยู่ ทำงานอยู่เบื้องหลัง (ย่อเล็กสุด) ปัญหานี้มักเกิดขึ้นเมื่อผู้ใช้กดปุ่ม "หน้าแรก" บนอุปกรณ์ สลับไปยังแอปอื่นโดยใช้ตัวสลับแอป หรือเปิดแอปพลิเคชันในแท็บอื่น (เว็บ) |
สิ้นสุดการใช้งาน | เมื่ออุปกรณ์ล็อกอยู่หรือแอปพลิเคชันไม่ทำงาน |
แอปพลิเคชันจะรับเพย์โหลดข้อความผ่าน FCM ได้ตามเงื่อนไขเบื้องต้นดังต่อไปนี้
- ต้องมีการเปิดแอปพลิเคชันอย่างน้อย 1 ครั้ง (เพื่อให้ลงทะเบียนกับ 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
ซึ่งมีรายละเอียดข้อมูลต่างๆ เกี่ยวกับเพย์โหลด เช่น ข้อมูลมาจากไหน รหัสที่ไม่ซ้ำกัน เวลาที่ส่ง มีการแจ้งเตือนหรือไม่ และอื่นๆ เนื่องจากระบบได้ดึงข้อมูลข้อความในขณะที่แอปพลิเคชันทำงานอยู่เบื้องหน้า คุณจึงเข้าถึงสถานะและบริบทของแอปพลิเคชัน Flutter ได้โดยตรง
ข้อความที่ทำงานอยู่เบื้องหน้าและข้อความแจ้งเตือน
ข้อความแจ้งเตือนที่มาถึงขณะที่แอปพลิเคชันทำงานอยู่เบื้องหน้าจะไม่แสดงการแจ้งเตือนที่มองเห็นได้โดยค่าเริ่มต้นทั้งใน Android และ iOS อย่างไรก็ตาม คุณสามารถเปลี่ยนการทำงานนี้ได้
- สำหรับ Android คุณต้องสร้างช่องทางการแจ้งเตือน "ลำดับความสำคัญสูง"
- ใน iOS คุณสามารถอัปเดตตัวเลือกการนำเสนอสำหรับแอปพลิเคชันได้
ข้อความพื้นหลัง
ขั้นตอนการจัดการข้อความเบื้องหลังจะแตกต่างกันไปตามแพลตฟอร์มที่มาพร้อมเครื่อง (Android และ Apple) และบนเว็บ
แพลตฟอร์ม Apple และ Android
จัดการข้อความเบื้องหลังโดยการลงทะเบียนเครื่องจัดการ onBackgroundMessage
เมื่อได้รับข้อความ ระบบจะสร้าง Isolated ขึ้นมา (เฉพาะ Android ส่วน iOS/macOS ไม่จำเป็นต้องใช้ Isolated แยกต่างหาก) ซึ่งช่วยให้คุณจัดการกับข้อความได้แม้ว่าแอปพลิเคชันจะไม่ได้ทำงานอยู่ก็ตาม
สิ่งที่ควรทราบเกี่ยวกับเครื่องจัดการข้อความในเบื้องหลังมีดังนี้
- และต้องไม่ใช่ฟังก์ชันที่ไม่ระบุชื่อ
- โดยต้องเป็นฟังก์ชันระดับบนสุด (เช่น ไม่ใช่เมธอดคลาสที่ต้องมีการเริ่มต้น)
- เมื่อใช้ Flutter เวอร์ชัน 3.3.0 ขึ้นไป เครื่องจัดการข้อความจะต้องใส่คำอธิบายประกอบด้วย
@pragma('vm:entry-point')
เหนือการประกาศฟังก์ชัน (มิฉะนั้นอาจถูกนำออกระหว่างการสั่นของต้นไม้ในโหมดปล่อย)
@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 วินาที อุปกรณ์อาจหยุดการทำงานของกระบวนการดังกล่าวโดยอัตโนมัติ
เว็บไซต์
เขียน Service Worker บนเว็บซึ่งทำงานในเบื้องหลัง ใช้ 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
มี 2 วิธีในการจัดการการโต้ตอบนี้ ได้แก่
getInitialMessage()
: หากแอปพลิเคชันเปิดจากสถานะสิ้นสุด ระบบจะแสดงผลFuture
ที่มีRemoteMessage
เมื่อใช้แล้ว ระบบจะนำRemoteMessage
ออกonMessageOpenedApp
:Stream
ที่โพสต์RemoteMessage
เมื่อแอปพลิเคชันเปิดขึ้นจากสถานะเบื้องหลัง
เราขอแนะนำให้จัดการทั้ง 2 สถานการณ์เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ราบรื่น โค้ดตัวอย่างด้านล่างจะสรุปวิธีดำเนินการ
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
แปลข้อความ
คุณส่งสตริงที่แปลแล้วได้ 2 วิธีดังนี้
- จัดเก็บภาษาที่ต้องการของผู้ใช้แต่ละคนในเซิร์ฟเวอร์ และส่งการแจ้งเตือนที่กำหนดเองสำหรับแต่ละภาษา
- ฝังสตริงที่แปลแล้วในแอปของคุณและใช้ประโยชน์จากการตั้งค่าภาษาดั้งเดิมของระบบปฏิบัติการ
ต่อไปนี้เป็นวิธีการใช้วิธีที่ 2
Android
ระบุข้อความภาษาเริ่มต้นของคุณใน
resources/values/strings.xml
:<string name="notification_title">Hello world</string> <string name="notification_message">This is a message</string>
ระบุข้อความที่แปลแล้วในไดเรกทอรี
values-language
ตัวอย่างเช่น ระบุข้อความภาษาฝรั่งเศสในresources/values-fr/strings.xml
ดังนี้<string name="notification_title">Bonjour le monde</string> <string name="notification_message">C'est un message</string>
ในเพย์โหลดของเซิร์ฟเวอร์ ให้ใช้
title_loc_key
และbody_loc_key
สำหรับข้อความที่แปลแล้ว แทนการใช้คีย์title
,message
และbody
แล้วตั้งค่าเป็นแอตทริบิวต์name
ของข้อความที่ต้องการแสดงเพย์โหลดข้อความจะมีลักษณะดังนี้
{ "data": { "title_loc_key": "notification_title", "body_loc_key": "notification_message" } }
iOS
ระบุข้อความภาษาเริ่มต้นของคุณใน
Base.lproj/Localizable.strings
:"NOTIFICATION_TITLE" = "Hello World"; "NOTIFICATION_MESSAGE" = "This is a message";
ระบุข้อความที่แปลแล้วในไดเรกทอรี
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 หรือการเขียนการแจ้งเตือน
หากต้องการเปิดใช้การส่งออก ให้ทำตามขั้นตอนที่อธิบายไว้ที่นี่ก่อน จากนั้นทำตามวิธีการต่อไปนี้
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 ลงใน Podfile
ขั้นตอนที่ 1 - เพิ่มส่วนขยายบริการการแจ้งเตือน
- ใน Xcode ให้คลิก File > New > Target...
- โมดัลจะแสดงรายการเป้าหมายที่เป็นไปได้ ให้เลื่อนลงหรือใช้ตัวกรองเพื่อเลือกส่วนขยายบริการการแจ้งเตือน คลิกถัดไป
- เพิ่มชื่อผลิตภัณฑ์ (ใช้ "ImageNotification" ควบคู่ไปกับบทแนะนำนี้) ตั้งค่าภาษาเป็น Objective-C แล้วคลิกเสร็จสิ้น
- เปิดใช้รูปแบบโดยคลิกเปิดใช้งาน
ขั้นตอนที่ 2 - เพิ่มเป้าหมายไปยัง Podfile
ตรวจสอบว่าส่วนขยายใหม่ของคุณมีสิทธิ์เข้าถึงพ็อด Firebase/Messaging
โดยการเพิ่มใน Podfile:
จาก Navigator ให้เปิด Podfile ดังนี้ Pods > Podfile
เลื่อนลงไปที่ด้านล่างของไฟล์แล้วเพิ่มรายการต่อไปนี้
target 'ImageNotification' do use_frameworks! pod 'Firebase/Auth' # Add this line if you are using FirebaseAuth phone authentication pod 'Firebase/Messaging' end
ติดตั้งหรืออัปเดตพ็อดโดยใช้
pod install
จากไดเรกทอรีios
หรือmacos
ขั้นตอนที่ 3 - ใช้โปรแกรมช่วยเหลือส่วนขยาย
ณ จุดนี้ ทุกอย่างควรทำงานได้ตามปกติ ขั้นตอนสุดท้ายคือการเรียกใช้ตัวช่วยส่วนขยาย
จากตัวนำทาง ให้เลือกส่วนขยาย ImageNotification ของคุณ
เปิดไฟล์
NotificationService.m
ที่ด้านบนของไฟล์ ให้นำเข้า
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 เกี่ยวกับวิธีสร้างคำขอส่ง โปรดทราบว่าอุปกรณ์บังคับใช้ขนาดรูปภาพสูงสุด 300 KB