Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

ตัวอย่าง Notification ใน Android พร้อม Vibration, Sound, Action และ Big View Styles

ภาพรวม

บทช่วยสอนนี้รวมคุณสมบัติ Notification ขั้นสูงไว้ด้วยกัน: การสั่น (Vibration), เสียง (Sound), Action Buttons, และ Big View Styles (BigText, BigPicture, Inbox, Messaging) เพื่อสร้าง Notification ที่โต้ตอบและสวยงาม

ตัวอย่างโค้ดครบถ้วน (Java)

ขั้นตอนที่ 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: MainActivity.java

package app.tutorialspoint.com.notifyme;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
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 {
    private static final String DEFAULT_CHANNEL_ID = "default_channel";
    private static final String CHANNEL_ID = "advanced_notifications";
    private int notificationCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        createNotificationChannel();

        Button btnCreateNotification = findViewById(R.id.btnCreateNotification);
        btnCreateNotification.setOnClickListener(v -> createAdvancedNotification());
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "Advanced Notifications",
                    NotificationManager.IMPORTANCE_HIGH
            );
            channel.setDescription("Notifications with actions, big views, vibration & sound");
            channel.enableVibration(true);
            channel.setVibrationPattern(new long[]{0, 200, 100, 200, 100, 200});
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(channel);
        }
    }

    private void createAdvancedNotification() {
        notificationCounter++;

        // 1. Intent และ PendingIntent สำหรับ Content Tap
        Intent mainIntent = new Intent(this, MainActivity.class);
        mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent contentPendingIntent = PendingIntent.getActivity(
                this, 0, mainIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        // 2. Action Buttons (สูงสุด 3 ปุ่ม)
        // Action 1: Reply (ต้องใช้ RemoteInput สำหรับ Direct Reply)
        Intent replyIntent = new Intent(this, NotificationActionReceiver.class)
                .setAction("ACTION_REPLY")
                .putExtra("notification_id", notificationCounter);
        PendingIntent replyPendingIntent = PendingIntent.getBroadcast(
                this, 1, replyIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        // Action 2: Mark as Read
        Intent readIntent = new Intent(this, NotificationActionReceiver.class)
                .setAction("ACTION_MARK_READ")
                .putExtra("notification_id", notificationCounter);
        PendingIntent readPendingIntent = PendingIntent.getBroadcast(
                this, 2, readIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        // Action 3: Open App
        Intent openIntent = new Intent(this, MainActivity.class);
        openIntent.setAction("ACTION_OPEN");
        PendingIntent openPendingIntent = PendingIntent.getActivity(
                this, 3, openIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );

        // 3. สร้าง Notification พร้อม BigTextStyle
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentTitle("Advanced Notification #" + notificationCounter)
                .setContentText("This notification has Actions, BigText, Vibration & Sound")
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText("Big View Styles: ข้อความยาวที่จะแสดงเต็มเมื่อผู้ใช้ขยาย Notification นี้ " +
                                "สามารถใส่ข้อความหลายบรรทัดได้ และรองรับการ format แบบง่ายๆ"))
                .setContentIntent(contentPendingIntent)
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setVibrate(new long[]{0, 200, 100, 200, 100, 200}) // Fallback สำหรับ API < 26
                .setDefaults(NotificationCompat.DEFAULT_SOUND) // ใช้เสียง Default
                // เพิ่ม Action Buttons
                .addAction(R.drawable.ic_launcher_foreground, "Reply", replyPendingIntent)
                .addAction(R.drawable.ic_launcher_foreground, "Mark Read", readPendingIntent)
                .addAction(R.drawable.ic_launcher_foreground, "Open App", openPendingIntent)
                // Big Picture Style (ถ้ามีรูป)
                // .setStyle(new NotificationCompat.BigPictureStyle()
                //         .bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.your_image))
                //         .setSummaryText("Image caption"))
                // Inbox Style (สำหรับรายการ)
                // .setStyle(new NotificationCompat.InboxStyle()
                //         .addLine("Item 1")
                //         .addLine("Item 2")
                //         .setBigContentTitle("3 new messages")
                //         .setSummaryText("Tap to view all"));

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(notificationCounter, builder.build());
    }
}

ขั้นตอนที่ 4: BroadcastReceiver สำหรับ Action Buttons

สร้าง Class ใหม่: NotificationActionReceiver.java

package app.tutorialspoint.com.notifyme;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public class NotificationActionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        int notificationId = intent.getIntExtra("notification_id", -1);
        
        if ("ACTION_REPLY".equals(action)) {
            // สำหรับ Direct Reply ต้องใช้ RemoteInput (ดูด้านล่าง)
            Toast.makeText(context, "Reply clicked for #" + notificationId, Toast.LENGTH_SHORT).show();
            Log.d("NotificationAction", "Reply action");
        } else if ("ACTION_MARK_READ".equals(action)) {
            Toast.makeText(context, "Marked as read #" + notificationId, Toast.LENGTH_SHORT).show();
            Log.d("NotificationAction", "Mark read action");
            // TODO: อัปเดต Database, ลบ Notification, etc.
        } else if ("ACTION_OPEN".equals(action)) {
            Log.d("NotificationAction", "Open action");
        }
    }
}

ขั้นตอนที่ 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.VIBRATE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ -->
    
    <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>
        
        <receiver android:name=".NotificationActionReceiver" android:exported="false">
            <intent-filter>
                <action android:name="ACTION_REPLY" />
                <action android:name="ACTION_MARK_READ" />
                <action android:name="ACTION_OPEN" />
            </intent-filter>
        </receiver>
        
        <service
            android:name=".MyFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    </application>
</manifest>

Big View Styles เลือกใช้ตามเนื้อหา

| Style | ใช้เมื่อไหร่ | เมธอดสำคัญ | |---|---|---| | **BigTextStyle** | ข้อความยาว, บทความ, รายละเอียด | bigText(String), setBigContentTitle(), setSummaryText() | | **BigPictureStyle** | รูปภาพ, สติ๊กเกอร์, Media | bigPicture(Bitmap), bigLargeIcon(Bitmap), setSummaryText() | | **InboxStyle** | รายการข้อความ, Email, List | addLine(String), setBigContentTitle(), setSummaryText() | | **MessagingStyle** | แชท, SMS, Conversation | addMessage(Message), setConversationTitle(), setGroupConversation() |

ตัวอย่าง MessagingStyle (แชท)

NotificationCompat.MessagingStyle messagingStyle = 
    new NotificationCompat.MessagingStyle("Me")
        .setConversationTitle("Group Chat")
        .addMessage("Hello!", System.currentTimeMillis(), "John")
        .addMessage("Hi there!", System.currentTimeMillis(), "Jane")
        .addMessage("How are you?", System.currentTimeMillis(), "John");

builder.setStyle(messagingStyle);

Direct Reply (ตอบกลับจาก Notification โดยตรง) - API 24+

// ใน Builder
RemoteInput remoteInput = new RemoteInput.Builder("key_text_reply")
        .setLabel("Reply...")
        .build();

NotificationCompat.Action replyAction = new NotificationCompat.Action.Builder(
        R.drawable.ic_reply, "Reply", replyPendingIntent)
        .addRemoteInput(remoteInput)
        .setAllowGeneratedReplies(true)
        .build();

builder.addAction(replyAction);

ใน BroadcastReceiver/Service รับค่าด้วย:

Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
    CharSequence replyText = remoteInput.getCharSequence("key_text_reply");
    // ประมวลผล replyText
}

การทดสอบ

  1. รันแอป กดปุ่ม Create Notification
  2. ดู Notification: มี Action Buttons 3 ปุ่ม, ขยายดู BigText
  3. กด Action Buttons → Toast แสดง Action ที่กด
  4. กดเนื้อหา Notification → เปิด MainActivity
  5. ลองตั้งค่าโหมดเงียบ (Do Not Disturb) → Notification HIGH จะยังแจ้งเตือนได้ (ถ้าอนุญาต)
หมายเหตุ: Android 13+ (API 33) ต้องขอ Permission POST_NOTIFICATIONS จากผู้ใช้ก่อนแสดง Notification