Giới thiệu
Ví dụ này minh họa cách tạo thêm một thông báo cục bộ (local notification) khi ứng dụng nhận được Push Notification từ server (FCM). Thường dùng để: hiển thị khác giao diện, thêm action buttons, hoặc xử lý logic local trước khi hiện.
Các bước thực hiện
Bước 1: Tạo dự án mới
Tạo project Android Studio mới.
Bước 2: Layout (res/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="Mô phỏng nhận Push → Tạo thông báo local" />
</RelativeLayout>
Bước 3: MainActivity - Xử lý Push và tạo Notification (src/MainActivity.java)
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);
}
// GIẢ LẬP NHẬN PUSH NOTIFICATION TỪ FCM
public void simulatePushReceived(String title, String body, String data) {
// Xử lý data từ push
Log.d("PUSH_RECEIVED", "Title: " + title + ", Body: " + body + ", Data: " + data);
// TẠO THÔNG BÁO LOCAL TÙY CHỈNH
createLocalNotification(title, body, data);
}
public void createNotification(View view) {
// Mô phỏng nhận push
simulatePushReceived("Push từ Server", "Nội dung push notification", "{\"orderId\":12345}");
}
private void createLocalNotification(String title, String body, String data) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
MainActivity.this, default_notification_channel_id);
mBuilder.setContentTitle(title);
mBuilder.setContentText(body);
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
mBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
// THÊM ACTION BUTTONS TÙY CHỈNH
Intent viewIntent = new Intent(this, MainActivity.class);
viewIntent.putExtra("push_data", data);
viewIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent viewPendingIntent = PendingIntent.getActivity(
this, 0, viewIntent, PendingIntent.FLAG_IMMUTABLE);
mBuilder.setContentIntent(viewPendingIntent);
mBuilder.addAction(R.drawable.ic_action, "Xem chi tiết", viewPendingIntent);
mBuilder.addAction(R.drawable.ic_action, "Đóng", viewPendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "Kênh Push Local", importance);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
int notificationId = (int) System.currentTimeMillis();
mNotificationManager.notify(notificationId, mBuilder.build());
Toast.makeText(this, "Đã tạo thông báo local từ Push", Toast.LENGTH_SHORT).show();
}
}
Bước 4: 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" />
<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>
Triển khai thực tế với FirebaseMessagingService
// src/MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// 1. Lấy data từ push
String title = remoteMessage.getNotification() != null
? remoteMessage.getNotification().getTitle() : "Thông báo mới";
String body = remoteMessage.getNotification() != null
? remoteMessage.getNotification().getBody() : "";
Map data = remoteMessage.getData();
// 2. Tạo local notification tùy chỉnh
createCustomNotification(title, body, data);
}
private void createCustomNotification(String title, String body, Map data) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "push_channel");
builder.setContentTitle(title)
.setContentText(body)
.setSmallIcon(R.drawable.ic_notification)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH);
// Intent mở app với data
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("push_data", new Gson().toJson(data));
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
builder.setContentIntent(pendingIntent);
// Action buttons
builder.addAction(R.drawable.ic_view, "Xem", pendingIntent);
builder.addAction(R.drawable.ic_dismiss, "Bỏ qua",
PendingIntent.getBroadcast(this, 0, new Intent("DISMISS"), PendingIntent.FLAG_IMMUTABLE));
// Channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"push_channel", "Push Notifications", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder.setChannelId("push_channel");
}
manager.notify((int) System.currentTimeMillis(), builder.build());
}
}
Manifest cho FCM Service
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Luồng xử lý Push → Local Notification
- Server gửi FCM message (data payload khuyến nghị)
FirebaseMessagingService.onMessageReceived()được gọi (app foreground/background)- Parse data, quyết định hiển thị như thế nào
- Tạo
NotificationCompat.Buildertùy chỉnh - Add actions, styles, intents phù hợp
NotificationManager.notify()hiển thị
Lợi ích tạo Local Notification từ Push
- Thêm Action Buttons (Trả lời, Xem, Mua, Hủy...)
- Xử lý logic local: lưu DB, cập nhật badge, sync data
- Nhóm thông báo (Notification Grouping)
- Kiểm soát visibility, priority, category
- Offline support: queue notification khi offline
Chạy thử nghiệm
Chạy app → Nhấn nút mô phỏng → Kéo shade → Thấy thông báo với 2 action buttons "Xem chi tiết" và "Đóng".