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

Đọc tất cả Notification đến trên Android với NotificationListenerService

Bài viết này triển khai cùng kỹ thuật với bài trước: sử dụng NotificationListenerService để theo dõi, ghi log tất cả notification xuất hiện trên thiết bị. Phù hợp cho app backup tin nhắn, tự động điền OTP, hoặc giám sát thông báo.

Triển khai nhanh (tóm tắt từ bài chi tiết)

1. Interface Callback (MyListener.java)

package app.tutorialspoint.com.notifyme;

public interface MyListener {
    void setValue(String packageName);
}

2. Service lắng nghe (NotificationService.java)

package app.tutorialspoint.com.notifyme;

import android.content.Context;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;

public class NotificationService extends NotificationListenerService {
    private static final String TAG = "NotifListener";
    private static MyListener listener;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        String pkg = sbn.getPackageName();
        String text = sbn.getNotification().tickerText != null ? sbn.getNotification().tickerText.toString() : "";
        Log.d(TAG, "Posted: " + pkg + " - " + text);
        if (listener != null) listener.setValue("POST: " + pkg + " - " + text);
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        String pkg = sbn.getPackageName();
        Log.d(TAG, "Removed: " + pkg);
        if (listener != null) listener.setValue("REMOVE: " + pkg);
    }

    public static void setListener(MyListener l) { listener = l; }
}

3. MainActivity implement Listener

package app.tutorialspoint.com.notifyme;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Bundle;
import androidx.core.app.NotificationCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements MyListener {
    private TextView logView;

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

        NotificationService.setListener(this);
        logView = findViewById(R.id.textView);

        findViewById(R.id.btnCreateNotification).setOnClickListener(v -> createTestNotif());
    }

    private void createTestNotif() {
        NotificationManager m = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder b = new NotificationCompat.Builder(this, "default")
            .setContentTitle("Test")
            .setContentText("Listener demo")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setAutoCancel(true);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            m.createNotificationChannel(new NotificationChannel("10001", "Test", NotificationManager.IMPORTANCE_HIGH));
            b.setChannelId("10001");
        }
        m.notify((int)System.currentTimeMillis(), b.build());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_settings) {
            startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void setValue(String s) {
        runOnUiThread(() -> logView.append("\n" + s));
    }
}

4. Manifest (bắt buộc permission & intent-filter)

<service
    android:name=".NotificationService"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>

Mở rộng: Lấy nội dung chi tiết notification (Android 7+)

@Override
public void onNotificationPosted(StatusBarNotification sbn) {
    Notification notif = sbn.getNotification();
    Bundle extras = notif.extras;
    
    // Lấy tiêu đề, nội dung văn bản
    CharSequence title = extras.getCharSequence(Notification.EXTRA_TITLE);
    CharSequence text = extras.getCharSequence(Notification.EXTRA_TEXT);
    CharSequence bigText = extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
    
    // Lấy ảnh lớn (BigPictureStyle)
    Bitmap picture = (Bitmap) extras.getParcelable(Notification.EXTRA_LARGE_ICON);
    
    // Lấy RemoteInput (nếu có quick reply)
    // Xử lý actions, categories, v.v.
}

Các trường EXTRAS phổ biến

Key (Notification.EXTRA_*)KiểuMô tả
TITLECharSequenceTiêu đề notification
TEXTCharSequenceNội dung ngắn
BIG_TEXTCharSequenceNội dung mở rộng (BigTextStyle)
SUB_TEXTCharSequencePhụ đề
LARGE_ICONBitmapLarge icon bitmap
PICTUREBitmapBigPictureStyle ảnh
MESSAGESParcelable[]MessagingStyle tin nhắn
PEOPLEString[]Danh sách người liên quan

Lưu ý triển khai thực tế

  • Service chạy nền, cần xử lý tốt vòng đời tránh bị kill.
  • Đăng ký listener trong Application.onCreate() hoặc MainActivity nhưng phải đảm bảo service đã bind.
  • Xử lý null safety cho extras và các trường bên trong.
  • Tuân thủ chính sách Google Play về quyền riêng tư khi xin quyền Notification Access.