ภาพรวม
ตั้งแต่ Android 8.0 (Oreo, API 26) ทุก Notification ต้องผ่าน Notification Channel ช่องทางนี้ช่วยให้ผู้ใช้ควบคุมการแจ้งเตือนได้ละเอียด (เปิด/ปิดเสียง, การสั่น, แสดงบน Lockscreen, ระดับความสำคัญ) แอปสามารถสร้าง Channel หลายช่องสำหรับประเภท Notification ที่ต่างกัน
ตัวอย่าง: สร้าง Channel พร้อมการตั้งค่าครบถ้วน
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → New Project → Empty Activity (Package: app.tutorialspoint.com.notifyme)
ขั้นตอนที่ 2: Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:id="@+id/btnCreateNotification"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Create notification"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ขั้นตอนที่ 3: เพิ่มไฟล์เสียง (res/raw/quite_impressed.mp3)
ขั้นตอนที่ 4: MainActivity.java - สร้าง Channel และ Notification
package app.tutorialspoint.com.notifyme;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import androidx.core.app.NotificationCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
public static final String CHANNEL_ID_HIGH = "channel_high_priority";
public static final String CHANNEL_ID_LOW = "channel_low_priority";
private static final String DEFAULT_CHANNEL_ID = "default";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// สร้าง Channel ตอนเริ่มแอป (แนะนำ)
createNotificationChannels();
Button btnCreateNotification = findViewById(R.id.btnCreateNotification);
btnCreateNotification.setOnClickListener(v -> showNotificationWithHighPriorityChannel());
}
// สร้าง Channel หลายตัวสำหรับประเภทต่างๆ
private void createNotificationChannels() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Channel 1: สำคัญสูง (Chat, Alert) - มีเสียง สั่น แสดงหัวข้อ
NotificationChannel highChannel = new NotificationChannel(
CHANNEL_ID_HIGH,
"Urgent Notifications",
NotificationManager.IMPORTANCE_HIGH
);
highChannel.setDescription("Important alerts, messages, calls");
highChannel.enableLights(true);
highChannel.setLightColor(Color.RED);
highChannel.enableVibration(true);
highChannel.setVibrationPattern(new long[]{0, 500, 200, 500});
highChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
highChannel.setShowBadge(true);
// Channel 2: สำคัญต่ำ (Promo, Info) - ไม่มีเสียง แสดงใน Shade อย่างเดียว
NotificationChannel lowChannel = new NotificationChannel(
CHANNEL_ID_LOW,
"Promotions & Info",
NotificationManager.IMPORTANCE_LOW
);
lowChannel.setDescription("Non-urgent updates, promotions");
lowChannel.enableLights(false);
lowChannel.enableVibration(false);
lowChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
lowChannel.setShowBadge(false);
manager.createNotificationChannel(highChannel);
manager.createNotificationChannel(lowChannel);
}
private void showNotificationWithHighPriorityChannel() {
Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
getPackageName() + "/raw/quite_impressed.mp3");
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_HIGH)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("High Priority Alert")
.setContentText("This uses the High Priority channel with custom sound")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// สำหรับ Android 8.0+ Channel จะถูกสร้างแล้วใน createNotificationChannels()
// แต่ถ้ายังไม่สร้าง ให้สร้างที่นี่ก็ได้ (Idempotent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// อัปเดตเสียงของ Channel (ถ้าต้องการเปลี่ยน) - ต้องสร้าง Channel ใหม่ ID ใหม่
// channel.setSound(soundUri, audioAttributes); // ไม่ทำงานหลังสร้างแล้ว
}
int id = (int) System.currentTimeMillis();
manager.notify(id, builder.build());
}
}
ขั้นตอนที่ 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">
<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>
</application>
</manifest>
Notification Channel - รายละเอียดสำคัญ
Importance Levels (ระดับความสำคัญ)
| ค่าคงที่ | ระดับ | พฤติกรรม |
|---|---|---|
| IMPORTANCE_MAX | ด่วนที่สุด | แสดงหัวข้อ (Heads-up), เสียง, สั่น, เหนือ Lockscreen |
| IMPORTANCE_HIGH | สูง | แสดงหัวข้อ, เสียง, สั่น |
| IMPORTANCE_DEFAULT | ปกติ | เสียง, สั่น, ไม่แสดงหัวข้อ |
| IMPORTANCE_LOW | ต่ำ | ไม่มีเสียง, ไม่สั่น, แสดงใน Shade เท่านั้น |
| IMPORTANCE_MIN | น้อยที่สุด | ไม่มีเสียง, ไม่สั่น, ไม่แสดงใน Shade (เฉพาะ Badge) |
| IMPORTANCE_NONE | ไม่แจ้งเตือน | ไม่มีการแจ้งเตือนเลย เฉพาะ Badge |
การตั้งค่าที่ Channel รองรับ
- Sound:
setSound(uri, audioAttributes)- ตั้งได้ครั้งเดียวตอนสร้าง - Vibration:
enableVibration(true),setVibrationPattern(long[]) - Light:
enableLights(true),setLightColor(Color) - Lockscreen:
setLockscreenVisibility(VISIBILITY_PUBLIC/PRIVATE/SECRET) - Badge:
setShowBadge(true/false)- แสดงตัวเลขบน Icon Launcher - Bypass DND:
setBypassDnd(true)- แจ้งเตือนแม้โหมดอย่ารบกวน (ต้องได้อนุญาตจาก User)
การจัดการ Channel แบบไดนามิก
1. อัปเดต Channel (จำกัด)
// สามารถอัปเดตได้: Name, Description, Importance (บางกรณี) // ไม่สามารถอัปเดตได้: Sound, Vibration Pattern, Light, Lockscreen Visibility // วิธีแก้: สร้าง Channel ใหม่ ID ใหม่ แล้วย้าย Notification ไปใช้ Channel ใหม่
2. ลบ Channel
manager.deleteNotificationChannel(CHANNEL_ID_HIGH);
3. ดึงข้อมูล Channel
NotificationChannel channel = manager.getNotificationChannel(CHANNEL_ID_HIGH);
if (channel != null) {
int importance = channel.getImportance();
boolean vibrationEnabled = channel.shouldVibrate();
// ...
}
4. กลุ่ม Channel (Channel Groups) - API 26+
// สร้าง Group
NotificationChannelGroup group = new NotificationChannelGroup("group_id", "Chat Notifications");
manager.createNotificationChannelGroup(group);
// กำหนด Channel ให้อยู่ใน Group
channel.setGroup("group_id");
แนวทางปฏิบัติที่ดี
- สร้าง Channel ตอนเริ่มแอป (Application.onCreate() หรือ Activity แรก) ไม่ใช่ตอนส่ง Notification
- จัดกลุ่ม Channel ตามประเภท: Chat, Promo, System, Update, dll.
- ตั้งชื่อ Channel ให้ผู้ใช้เข้าใจ: "Direct Messages", "Promotions", "Security Alerts"
- ใช้ Importance ให้เหมาะสม: อย่าใช้ HIGH สำหรับ Promo
- ทดสอบบนอุปกรณ์จริง เพราะ UI Settings ต่างกันตาม廠商 (Samsung, Xiaomi, Pixel)
การทดสอบ
- รันแอป กดปุ่มสร้าง Notification
- ไป Settings → Apps → [Your App] → Notifications
- จะเห็น 2 Channel: "Urgent Notifications" และ "Promotions & Info"
- ลองปิดเสียง Channel "Promotions" → สร้าง Notification ใหม่ด้วย Channel นั้น → จะไม่มีเสียง
สำคัญ: การจัดการ Channel ถูกต้องส่งผลต่อ UX และ App Store Rating โดยตรง ผู้ใช้รบกวนได้ง่ายหากแจ้งเตือนมากเกินไปหรือไม่เกี่ยวข้อง