Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách khởi động Activity Android khi người dùng bấm vào thông báo

Giới thiệu

Hướng dẫn cơ bản: dùng PendingIntent.getActivity() gán vào setContentIntent() của NotificationCompat.Builder.

Code mẫu chuẩn AndroidX

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"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnCreateNotification"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Tạo thông báo mở Activity" />

</RelativeLayout>

MainActivity.java

package com.example.notificationopenactivity;

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.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private static final String CHANNEL_ID = "open_activity_channel";

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

        Button btn = findViewById(R.id.btnCreateNotification);
        btn.setOnClickListener(v -> {
            // 1. Intent đích
            Intent notificationIntent = new Intent(this, MainActivity.class);
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            notificationIntent.putExtra("from_notification", true);

            // 2. PendingIntent - FLAG_IMMUTABLE bắt buộc API 31+
            PendingIntent pendingIntent = PendingIntent.getActivity(
                    this, 0, notificationIntent, 
                    PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

            // 3. Notification Builder
            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
                    .setSmallIcon(R.drawable.ic_launcher_foreground)
                    .setContentTitle("Mở Activity từ thông báo")
                    .setContentText("Bấm vào để mở MainActivity")
                    .setContentIntent(pendingIntent) // ==== GÁN VÀO ĐÂY ====
                    .setAutoCancel(true);

            // 4. Channel (API 26+)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel channel = new NotificationChannel(
                        CHANNEL_ID, "Open Activity", NotificationManager.IMPORTANCE_DEFAULT);
                manager.createNotificationChannel(channel);
                builder.setChannelId(CHANNEL_ID);
            }

            // 5. Hiển thị
            manager.notify((int) System.currentTimeMillis(), builder.build());
        });
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.notificationopenactivity">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <application ...>
        <activity android:name=".MainActivity" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Mở Activity khác (không phải MainActivity)

// Trong MainActivity hoặc nơi tạo notification
Intent detailIntent = new Intent(this, DetailActivity.class);
detailIntent.putExtra("item_id", 123);
detailIntent.putExtra("title", "Tin nhắn từ notification");

PendingIntent pendingIntent = PendingIntent.getActivity(
        this, REQUEST_CODE_DETAIL, detailIntent, 
        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

Xử lý data trong Activity đích

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent); // Quan trọng: cập nhật getIntent()
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    if (intent != null && intent.getBooleanExtra("from_notification", false)) {
        int itemId = intent.getIntExtra("item_id", -1);
        // Mở fragment, load data, scroll...
    }
}

Các lỗi thường gặp

  • Quên setContentIntent() → bấm thông báo không làm gì cả.
  • Dùng PendingIntent.getActivity() nhưng flag sai → tạo nhiều instance Activity.
  • Không xin quyền POST_NOTIFICATIONS (Android 13+) → thông báo không hiện.
  • Icon nhỏ (setSmallIcon) không có trong drawable → crash hoặc không hiện.