0Pricing
React Native Academy · บทเรียน

ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย

สร้างช่องการแจ้งเตือนบน Android สำหรับการแจ้งเตือนแต่ละประเภท เพิ่มรูปภาพและปุ่มการทำงานในการแจ้งเตือน และกำหนดค่าจำนวนป้ายบน iOS

ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ

What Are Notification Channels?

Notification channels are categories of notifications that Android users can control independently. Introduced in Android 8 (API 26), channels let users decide which types of notifications from your app they want to receive — for example, they might allow 'Messages' but block 'Promotions'. Each channel has its own sound, vibration, and importance settings.

Channels are an Android-only concept. iOS has its own notification management through notification categories and user settings, but no direct equivalent to channels. Always guard channel setup code with a Platform.OS check.

import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';

async function setupChannels() {
  if (Platform.OS !== 'android') return;

  // Create your app's notification channels:
  await Notifications.setNotificationChannelAsync('messages', { ... });
  await Notifications.setNotificationChannelAsync('reminders', { ... });
  await Notifications.setNotificationChannelAsync('promotions', { ... });
}

Creating a Notification Channel

Create a channel with Notifications.setNotificationChannelAsync(channelId, config). The config includes the name (shown to users in Settings), importance (how prominently notifications appear), vibrationPattern, lightColor, and whether to enableVibrate.

Channels are permanent — once created, users can modify them in Settings and your app cannot override their preferences. Create channels before calling them, and call this setup on every app launch because channels persist across app reinstalls through the channel ID.

await Notifications.setNotificationChannelAsync('messages', {
  name: 'Messages',
  description: 'New messages from other users',
  importance: Notifications.AndroidImportance.HIGH,
  vibrationPattern: [0, 250, 250, 250],
  lightColor: '#0066CC',
  enableVibrate: true,
  enableLights: true,
  showBadge: true,
  lockscreenVisibility: Notifications.AndroidNotificationVisibility.PUBLIC,
});

Importance Levels for Channels

The importance level controls how aggressively the notification interrupts the user:

  • NONE (0) — never appears
  • MIN (1) — no sound, no banner, appears in drawer
  • LOW (2) — no sound, no banner, in drawer
  • DEFAULT (3) — makes sound, appears as banner
  • HIGH (4) — makes sound, appears prominently
  • MAX (5) — always shown, wakes screen

Use HIGH for time-sensitive communications (messages, calls) and DEFAULT or LOW for informational updates and promotional content.

// Different channels with appropriate importance:
await Notifications.setNotificationChannelAsync('calls', {
  name: 'Incoming Calls',
  importance: Notifications.AndroidImportance.MAX, // wakes screen
});

await Notifications.setNotificationChannelAsync('news', {
  name: 'News Updates',
  importance: Notifications.AndroidImportance.LOW, // unobtrusive
});

await Notifications.setNotificationChannelAsync('marketing', {
  name: 'Promotions',
  importance: Notifications.AndroidImportance.MIN, // nearly invisible
});

Assigning Notifications to Channels

When sending a push notification to an Android device, specify which channel it belongs to by including channelId in the notification message. If no channel is specified, the notification falls into the default channel. On older Android versions (below API 26), the channel ID is ignored.

Correctly assigning notifications to channels is important — users who mute the 'Promotions' channel expect their 'Messages' channel to remain active. Mixing notification types in one channel leads to users muting important notifications.

// In push notification payload:
const message = {
  to: pushToken,
  title: 'Alice: Hey, are you free tonight?',
  body: 'New message from Alice',
  channelId: 'messages',     // routes to messages channel
  data: { screen: 'Chat', conversationId: 'alice_123' },
};

// For a promotional notification:
const promo = {
  to: pushToken,
  title: 'Weekend Sale — 30% off!',
  channelId: 'promotions',   // low importance, unobtrusive
};

Notification Groups on Android

When a user has multiple unread notifications from your app, Android can group them into a single expandable notification to avoid overwhelming the notification shade. Configure grouping by setting the groupId in the notification payload and creating a summary notification.

Grouped notifications show a stacked appearance with a count when collapsed and expand to show individual notifications. This is important for chat apps where a user might receive many messages before opening the app.

// Send individual notifications with group ID:
const messageNotif = {
  to: token,
  title: 'Alice: Hello!',
  channelId: 'messages',
  android: {
    groupId: 'chat_messages',
    tag: 'msg_alice_1',
  },
};

// Send group summary:
const summary = {
  to: token,
  title: '3 new messages',
  channelId: 'messages',
  android: {
    groupId: 'chat_messages',
    groupSummary: true,
  },
};

Rich Notifications: Images and Big Text

Android supports rich notification styles that go beyond title and body text. The BigPicture style shows a large image in the expanded notification. The BigText style shows multiple lines of text when expanded. These styles make notifications more informative and engaging.

In expo-notifications, use the android.bigPicture or android.bigText fields in the notification content. Rich notifications require Android channel support and increase engagement compared to plain text notifications.

const richNotification = {
  to: token,
  title: 'New photo from Alice',
  body: 'Alice shared a photo with you',
  channelId: 'messages',
  android: {
    imageUrl: 'https://myapp.com/photos/photo123.jpg', // big picture
    color: '#FF6B6B',
    actions: [
      { title: 'View', action: 'view_photo' },
      { title: 'Dismiss', action: 'dismiss' },
    ],
  },
};

iOS Rich Notifications

iOS supports rich notifications through notification service extensions — a separate target in the app that intercepts push notifications before display and can add images, modify content, or download media. This requires native code outside expo-notifications' managed API.

For simpler use cases, iOS push notifications can include a mutable-content: 1 flag and a media attachment URL in the APNs payload, processed by a Notification Service Extension. For Expo managed apps, this requires a config plugin or bare workflow.

// iOS push payload (APNs level):
// expo-notifications sends this automatically
// when you set content fields:
const iOSPushPayload = {
  aps: {
    alert: {
      title: 'New photo from Alice',
      body: 'Alice shared a photo with you',
    },
    sound: 'default',
    badge: 3,
    'mutable-content': 1, // allows service extension to modify
    'content-available': 1, // allows background fetch
  },
};

iOS Badge Count Management

On iOS the badge count appears as a red number on the app icon in the home screen. Set the badge count in the push notification payload's badge field. The server should always send the total unread count (absolute number), not an increment, because multiple devices must show the same badge count.

When the user opens and reads all notifications, reset the badge to 0 with Notifications.setBadgeCountAsync(0). Add this call to the screen that shows the notifications list so the badge clears naturally when the user checks their inbox.

// Push payload — absolute unread count:
const notification = {
  to: token,
  title: 'Alice sent you a message',
  body: 'Click to read',
  badge: 5, // total unread, not +1
};

// In app, when inbox is opened:
import * as Notifications from 'expo-notifications';

useEffect(() => {
  return navigation.addListener('focus', () => {
    Notifications.setBadgeCountAsync(0); // clear on inbox open
  });
}, [navigation]);

Notification Sound Customization

Both iOS and Android support custom notification sounds. Add audio files to your app bundle and reference them by filename. On iOS, short .aiff, .wav, or .caf files under 30 seconds work as notification sounds. On Android, sounds are configured at the channel level.

For Expo managed workflow, add audio files to the assets folder and reference them via a config plugin or bare workflow. Many apps skip custom sounds and use the default system sound, which users are already conditioned to notice.

// iOS: add sound file to iOS app bundle
// Android: create channel with sound
if (Platform.OS === 'android') {
  await Notifications.setNotificationChannelAsync('messages', {
    name: 'Messages',
    importance: Notifications.AndroidImportance.HIGH,
    sound: 'message_sound', // filename without extension
  });
}

// In push payload:
{
  to: token,
  sound: 'default', // use system default
  // Or: sound: 'message_sound.aiff' on iOS
}

Deleting Notification Channels

If you restructure your notification types, you can delete old channels with Notifications.deleteNotificationChannelAsync(channelId). Deleting and recreating a channel with the same ID resets user customizations — this is controversial because it overrides user preferences.

Best practice: avoid deleting channels that users might have customized. Instead, deprecate old channels by creating new ones with better names and routing new notifications to the new channel. Old channels become empty but remain visible in Settings (they disappear after the app is reinstalled).

// Get all current channels:
const channels = await Notifications.getNotificationChannelsAsync();
console.log('Active channels:', channels.map(c => c.id));

// Delete a deprecated channel:
await Notifications.deleteNotificationChannelAsync('old_alerts');

// CAUTION: this resets any user customizations
// for that channel ID if recreated

Notification Permission Status and In-App Settings

Provide in-app notification preference controls even if the OS-level permission is granted. Users should be able to opt out of marketing notifications while keeping message notifications enabled. Implement server-side preference flags per user and per notification type.

Also provide a clear UI when the OS permission is denied, with a button that opens the Settings app using Linking.openSettings(). This prevents users from assuming your app is broken when they've unknowingly denied permissions.

import { Linking } from 'react-native';
import * as Notifications from 'expo-notifications';

async function checkAndPromptPermission() {
  const { status } = await Notifications.getPermissionsAsync();

  if (status === 'denied') {
    Alert.alert(
      'Notifications Disabled',
      'Enable notifications in Settings to receive important updates.',
      [
        { text: 'Cancel', style: 'cancel' },
        { text: 'Open Settings', onPress: () => Linking.openSettings() },
      ]
    );
  }
}

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: Android notification channels group notifications by type and give users independent control over each category's sound, vibration, and display settings, importance levels from MIN to MAX control how aggressively notifications interrupt the user, and the channelId field in push payloads routes each notification to the correct channel. Next up we implement offline-first data fetching using TanStack React Query with cache persistence.

คำถามที่พบบ่อย

บทเรียน “ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย”

สร้างช่องการแจ้งเตือนบน Android สำหรับการแจ้งเตือนแต่ละประเภท เพิ่มรูปภาพและปุ่มการทำงานในการแจ้งเตือน และกำหนดค่าจำนวนป้ายบน iOS คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม

ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การขอสิทธิ์และรับโทเค็นพุช
  2. การส่งการแจ้งเตือนผ่าน Expo Push API
  3. การจัดการการแจ้งเตือนขณะอยู่เบื้องหน้าและเบื้องหลัง
  4. ช่องการแจ้งเตือนและเนื้อหาแบบหลากหลาย
← กลับไปที่ React Native Academy