ภาพรวม
ตัวอย่างนี้สาธิตการสร้าง Notification เพิ่มเติมเมื่อรับ Push Notification (FCM) โดยสร้าง Notification ใหม่ใน onMessageReceived() ของ FirebaseMessagingService
ขั้นตอนที่ 1: สร้างโปรเจกต์และเพิ่ม Firebase
// build.gradle (Project)
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
// build.gradle (App)
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation 'com.google.firebase:firebase-messaging:23.0.0'
implementation 'com.google.firebase:firebase-analytics:21.0.0'
}
ขั้นตอนที่ 2: Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:onClick="createNotification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:text="Create notification" />
</RelativeLayout>
ขั้นตอนที่ 3: MainActivity - สร้าง Notification ทดสอบ
package app.tutorialspoint.com.notifyme;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
onNewIntent(getIntent());
}
public void createNotification(View view) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(MainActivity.this, default_notification_channel_id);
mBuilder.setContentTitle("Notify Me");
mBuilder.setContentText("Something important!");
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
}
ขั้นตอนที่ 4: FirebaseMessagingService - สร้าง Notification เพิ่มเมื่อรับ Push
package app.tutorialspoint.com.notifyme;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
@Override
public void onNewToken(String token) {
super.onNewToken(token);
// ส่ง Token ไปยัง Server ของคุณ
sendTokenToServer(token);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// 1. จัดการ Data Message
if (remoteMessage.getData().size() > 0) {
handleDataMessage(remoteMessage.getData());
}
// 2. จัดการ Notification Message (เมื่อแอปอยู่ Foreground)
if (remoteMessage.getNotification() != null) {
String title = remoteMessage.getNotification().getTitle();
String body = remoteMessage.getNotification().getBody();
createAdditionalNotification(title, body, remoteMessage.getData());
}
}
private void handleDataMessage(Map data) {
// ประมวลผลข้อมูลจาก Server
String customKey = data.get("custom_key");
// TODO: บันทึกลง DB, อัปเดต UI, ฯลฯ
}
private void createAdditionalNotification(String title, String body, Map data) {
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
// ส่งข้อมูลจาก Push ไปยัง Activity
if (data != null) {
for (Map.Entry entry : data.entrySet()) {
notificationIntent.putExtra(entry.getKey(), entry.getValue());
}
}
notificationIntent.putExtra("fromPush", true);
notificationIntent.putExtra("pushTitle", title);
notificationIntent.putExtra("pushBody", body);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(
getApplicationContext(), 0, notificationIntent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
getApplicationContext(), default_notification_channel_id)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle(title != null ? title : "New Notification")
.setContentText(body != null ? body : "You have a new message")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE);
// ใช้ BigTextStyle หากข้อความยาว
if (body != null && body.length() > 100) {
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(body));
}
NotificationManager mNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Push Notifications", importance);
// ตั้งค่าเสียง, ไฟ, สั่น ที่ Channel Level
notificationChannel.setSound(null, null); // ใช้เสียงเริ่มต้น
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{0, 500, 200, 500});
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
// ใช้ ID ที่ไม่ซ้ำกัน (timestamp) เพื่อไม่ให้ทับ Notification เดิม
int notificationId = (int) System.currentTimeMillis();
mNotificationManager.notify(notificationId, mBuilder.build());
}
private void sendTokenToServer(String token) {
// TODO: Implement server token registration
}
}
ขั้นตอนที่ 5: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.tutorialspoint.com.notifyme">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Firebase Messaging Service -->
<service
android:name=".MyFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
ประเภท Push Notification และการจัดการ
| ประเภท | Background | Foreground | onMessageReceived |
|---|---|---|---|
| Notification Message | ระบบแสดงอัตโนมัติ | ✅ เรียก | ไม่ได้รับ Notification object |
| Data Message | ✅ เรียก | ✅ เรียก | ได้รับ Data payload ทั้งหมด |
| Both (Notification + Data) | ระบบแสดง Notification | ✅ เรียก | ได้รับ Data payload |
แนวทางปฏิบัติที่ดี
- ใช้ Data Message สำหรับควบคุม Notification เองทั้ง Background และ Foreground
- ID ไม่ซ้ำกัน ใช้
System.currentTimeMillis()หรือ atomic counter - Group Notification ใช้
setGroup()และsetGroupSummary()รวม Notification เดียวกัน - จัดการ Token Refresh ใน
onNewToken()ส่งไป Server ทันที - Background Execution Limits Android 8+ จำกัด Service ใช้ WorkManager สำหรับงานหนัก
การจัดกลุ่ม Notification (Notification Grouping)
// สร้าง Group Summary
NotificationCompat.Builder summaryBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("ข้อความใหม่ 3 รายการ")
.setContentText("กดเพื่อดูทั้งหมด")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setGroup("group_key_messages")
.setGroupSummary(true)
.setStyle(new NotificationCompat.InboxStyle()
.addLine("สมชาย: สวัสดี")
.addLine("มานี: ไปไหนมา")
.addLine("สมหญิง: อร่อยไหม")
.setBigContentTitle("3 ข้อความใหม่")
.setSummaryText("กดเพื่อเปิดแชท"));
notificationManager.notify(GROUP_SUMMARY_ID, summaryBuilder.build());
// Notification ย่อยในกลุ่ม
for (Message msg : messages) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(msg.getSender())
.setContentText(msg.getText())
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setGroup("group_key_messages")
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
notificationManager.notify(msg.getId(), builder.build());
}