Android应用监听WhatsApp通知存本地数据库及后台运行问题求助
Hey there! Let's break down your problem step by step—you've got the notification listening part working, now we just need to fix the data persistence and keep the service running reliably. Here's what you need to do:
Since you're new, Room Database is the best choice here—it's part of Android Jetpack, easy to set up, and handles all the SQLite boilerplate for you.
Step 1: Add Room Dependencies
First, add these to your app-level build.gradle (Module level):
dependencies { def room_version = "2.5.0" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" }
Step 2: Create a Notification Entity
This class represents a single row in your database—define all the data you want to store from WhatsApp notifications:
import androidx.room.Entity; import androidx.room.PrimaryKey; @Entity(tableName = "whatsapp_notifications") public class WhatsAppNotification { @PrimaryKey(autoGenerate = true) public long id; public String sender; // e.g., contact name public String messageContent; public long postTime; // timestamp of when the notification was posted public String packageName; // confirm it's WhatsApp // Constructor public WhatsAppNotification(String sender, String messageContent, long postTime, String packageName) { this.sender = sender; this.messageContent = messageContent; this.postTime = postTime; this.packageName = packageName; } // Generate getters and setters via Android Studio }
Step 3: Create a DAO (Data Access Object)
This interface defines how you interact with the database:
import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; import java.util.List; @Dao public interface NotificationDao { @Insert void insertNotification(WhatsAppNotification notification); @Query("SELECT * FROM whatsapp_notifications ORDER BY postTime DESC") List<WhatsAppNotification> getAllNotifications(); }
Step 4: Create the Room Database Class
This is the main database holder (singleton to avoid duplicate connections):
import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; import android.content.Context; @Database(entities = {WhatsAppNotification.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract NotificationDao notificationDao(); private static volatile AppDatabase INSTANCE; public static AppDatabase getDatabase(Context context) { if (INSTANCE == null) { synchronized (AppDatabase.class) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "whatsapp_notes_db") .build(); } } } return INSTANCE; } }
Step 5: Save Notifications in Your Service
Update your NotificationService to insert captured notifications into the database. Important: Database operations can't run on the main thread, so use a background thread for this:
@Override public void onNotificationPosted(StatusBarNotification sbn) { super.onNotificationPosted(sbn); String packageName = sbn.getPackageName(); // Only process WhatsApp notifications if ("com.whatsapp".equals(packageName)) { Notification notification = sbn.getNotification(); // Extract notification data (note: some fields vary by Android version) String sender = notification.extras.getString(Notification.EXTRA_TITLE); String message = notification.extras.getString(Notification.EXTRA_TEXT); long postTime = sbn.getPostTime(); // Create notification object WhatsAppNotification waNotification = new WhatsAppNotification(sender, message, postTime, packageName); // Insert into database on a background thread new Thread(() -> { AppDatabase db = AppDatabase.getDatabase(getApplicationContext()); db.notificationDao().insertNotification(waNotification); }).start(); } }
NotificationListenerService is system-managed, but Android's battery optimizations can still kill it. Here's how to make it more reliable:
a. Ensure Notification Access Permission
Guide users to grant your app notification access. Add this code to your main Activity:
import android.content.Intent; import android.provider.Settings; // Call this when your app starts (e.g., in onCreate) private void requestNotificationAccess() { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS); startActivity(intent); }
b. Disable Battery Optimization for Your App
Android's Doze mode can shut down background services. Prompt users to exclude your app:
import android.content.Intent; import android.net.Uri; import android.os.PowerManager; import android.provider.Settings; import android.content.Context; private void requestBatteryOptimizationExemption() { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); String packageName = getPackageName(); if (!pm.isIgnoringBatteryOptimizations(packageName)) { Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); } }
Add this permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
c. Handle Custom ROM Restrictions
On devices with custom ROMs (Xiaomi, Huawei, Samsung), users may need to manually add your app to the "background protection" or "autostart" list. Add a screen in your app explaining how to do this for popular devices.
- Load Saved Notifications: When your app starts, fetch data from the Room database using
getAllNotifications()and display it in your UI. - Handle Notification Removal: Override
onNotificationRemoved()in your service if you want to delete or mark notifications as read in the database when they're cleared from the status bar. - Test Across Android Versions: Notification APIs change between versions—test on Android 10, 12, and 13 to ensure data extraction works correctly.
- Explain Permissions: Users are more likely to grant permissions if you clearly explain why your app needs them (e.g., "We need notification access to save your WhatsApp messages, and battery exemption to keep the service running").
Take it slow, and don't hesitate to ask follow-up questions if you get stuck on any part!
内容的提问来源于stack exchange,提问作者PrincEVergil

