Flutter : แสดง Notification ด้วย Firebase Messaging ใน Flutter
สวัสดีผู้อ่านครับ จากตอนที่แล้วผมได้ลองเล่นเกี่ยวกับการแสดง Notification ใน Flutter ไปแล้ว ซึ่งป็นการใช้งานคำสั่งให้แสดง notification จากตัวแอปเอง แต่ในงานจริงๆการแสดง notification จะมาจากการส่งที่ server หรือหลังบ้าน ดังนั้นการทำให้แสดง notification แบบ offline จะยังไม่เพียงพอ ควรต้องเพิ่มส่วนต่อขยายให้แอปสามารถรับผลจาก server แล้วแสดง notification ได้นั่นเอง ซึ่งในที่นี้พระเอกคือ Firebase Cloud Messaging (FCM) จะช่วยให้เราสามารถส่ง notification มายังแอปได้ เอาละมาลองเล่นกัน
ใครยังไม่ได้อ่านในตอนที่แล้ว เพราะบล็อกนี้เป็นภาคต่อ แนะนำอ่านก่อนนะครับ
ติดตั้ง Firebase ใน project
ในบล็อกนี้จะไม่อธิบายขั้นตอนการติดตั้ง firebase นะครับ เพราะมีอธิบายไว้ในเว็บของ firebase แล้วทั้ง iOS และ Android
เพิ่ม dependencies
เพิ่ม firebase_messaging และ firebase_core ใน pubspec.yaml
dependencies:
..
flutter_local_notifications: 0.7.0
http: 0.12.0+2
path_provider: 0.5.0+1
firebase_messaging: 4.0.0+4
firebase_core: ^0.3.0
หากมี error ลองเปลี่ยนเวอชั่นใน android/build.gradle เป็น 3.3.2
buildscript {
..
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
การใช้งาน
import ไฟล์ firebase_messaging เข้ามา
import 'package:firebase_messaging/firebase_messaging.dart';
ประกาศตัวแปร FirebaseMessaging
class _MyHomePageState extends State<MyHomePage> {
FirebaseMessaging firebaseMessaging = FirebaseMessaging();
จุดสำคัญอยู่ตรงนี้คือ firebaseMessaging.configure()
ซึ่ง callback ของมัน คือ onMessage ที่ถูกเรียกเมื่อมี noti ส่งเข้ามา
@override
initState(){
initFirebaseMessaging();
super.initState();
}
void initFirebaseMessaging() {
firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
);
firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
firebaseMessaging.getToken().then((String token) {
assert(token != null);
print("Token : $token");
});
}
}
ลองใช้งานกัน ก่อนอื่นเราจะทดสอบส่ง noti แบบใช้ token ที่ได้มาจากจากคำสั่ง getToken()
ไปที่เว็บ firebase สร้าง notification ใหม่ ใส่ title , body
จากนั้นกดที่ send test message แล้วเอา token วางลงไป กดส่ง test ได้เลย
สิ่งที่ได้คือ มันจะวิ่งมาที่ onMessage แล้วมี data มาให้ ประมาณนี้
{notification: {title: Hello, body: benznest} data:{}}
เราก็แค่เอา data ที่ได้รับแปลงออกมา แล้วเรียกใช้คำสั่ง notification จาก library ในตอนที่แล้ว
firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
Map mapNotification = message["notification"];
String title = mapNotification["title"];
String body = mapNotification["body"];
sendNotification(title: title, body: body);
}
..
}
เท่านี้ก็กดส่ง noti จาก firebase ไปแสดงในแอปได้แล้ว
ส่ง Noti แบบแนบ data
ที่ firebase เราสามารถแนบ data ที่มี key ไปด้วยได้ ซึ่งจะอยู่ในหัวข้อ Additional แล้วก็ถ้ามี channel ก็ให้ใส่ Channel ให้ตรงกับที่เรากำหนดไว้ด้วย
ค่าที่ได้ใน onMessage จะเป็นประมาณนี้ ก็คือ data จะอยู่ใน key ที่ชื่อว่า data นั่นเอง
{notification: {title: Hello, body: benznest}, data: {job: developer}}
Subscribe
การส่ง noti อีกแบบคือ การส่งแบบไปให้คนที่อยู่ในกลุ่มที่เรากำหนด ใน firebase เรียก topic ก็คือให้เรากำหนด topic แล้วให้ผู้ใช้มา subscribe ว่าอยู่ใน topic นี้ จากนั้นเราสามารถส่ง noti ไปหาทุกคนใน topic ในคราวเดียวได้เลย
การใช้งานง่ายมากคือ subscribeToTopic แล้วกำหนดชื่อ topic
หากอยากออกจาก topic ก็ใช้ unsubscribeFromTopic
firebaseMessaging.subscribeToTopic("NEWS"); // subscribe topic News
firebaseMessaging.unsubscribeFromTopic("NEWS");
การส่ง noti ไปแบบ topic นี้สามารถกำหนดได้ที่หัวข้อ Target
ลองใช้งานกัน ผมจะเพิ่มสวิทตัวนึง เอาไว้เลือกว่าต้องการ subscribe ไหม
class _MyHomePageState extends State<MyHomePage> {
bool isSubscribeHotNews= false;
..
เพิ่ม Switch โดยถ้า switch เปิดก็ subscribe หากปิดจะเป็น unsubscribe
Container(
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(6),
border: Border.all(width: 1, color: Colors.black54)),
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(16),
child: Column(children: <Widget>[
Text("Subscribe news "),
Switch(
value: isSubscribeHotNews,
onChanged: (checked) {
if(checked) {
firebaseMessaging.subscribeToTopic("NEWS");
}else{
firebaseMessaging.unsubscribeFromTopic("NEWS");
}
setState(() => isSubscribeHotNews = checked);
})
]),
)
ผลคือ หากเปิด switch ก็สามารถส่งแจ้งเตือนมาได้ แต่หากปิดแจ้งเตือนก็จะไม่มานั่นเอง
Firebase Messaging + Local Notification
ตอนนี้ Firebase Messaging สามารถใช้งานร่วมกับ local_notification ใน iOS ได้แล้ว หลัวจากที่ก่อนหน้านี้มีปัญหา conflict กัน
firebase_messaging: ^5.1.2
flutter_local_notifications: ^0.8.0