Android服务中设置日期为当日时通知无法触发问题求助
Hey there! Let's pinpoint why your notification isn't firing when the item's date is set to today—and it's not your Service class at fault. The root problem lies in how you're comparing Date objects.
The Core Issue: Precise Date Comparison
When you use dateFormat.equals(tomorrow), you're comparing two Date objects down to the millisecond. Here's what happens:
- The date parsed from Firebase (via
SimpleDateFormat) defaults to00:00:00for the time portion. - The
tomorrowdate you create withCalendar.getInstance().add(Calendar.DAY_OF_MONTH, 1)includes the current time (e.g., 2:30 PM if you run the code then).
These two dates will never be equal, even if they're the same calendar day, because their time parts don't match. That's why removing the date check makes notifications work—you're skipping this faulty comparison.
Solution 1: Compare Dates Without Time (Using Calendar)
Modify your date comparison to ignore the time component by normalizing both dates to midnight:
databaseReference = FirebaseDatabase.getInstance().getReference().child("Groups").child(mGroupUid).child("HomeFragment").child("FreezerItems"); childEventListener = databaseReference.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { HashMap<String, String> value = (HashMap<String, String>) dataSnapshot.getValue(); if (value != null) { String name = value.get("Name"); String date = value.get("Date"); SimpleDateFormat sdf = new SimpleDateFormat("M/dd/yyyy", Locale.US); try { Date itemDate = sdf.parse(date); // Normalize item date to midnight Calendar itemCal = Calendar.getInstance(); itemCal.setTime(itemDate); itemCal.set(Calendar.HOUR_OF_DAY, 0); itemCal.set(Calendar.MINUTE, 0); itemCal.set(Calendar.SECOND, 0); itemCal.set(Calendar.MILLISECOND, 0); // Normalize tomorrow's date to midnight Calendar tomorrowCal = Calendar.getInstance(); tomorrowCal.add(Calendar.DAY_OF_MONTH, 1); tomorrowCal.set(Calendar.HOUR_OF_DAY, 0); tomorrowCal.set(Calendar.MINUTE, 0); tomorrowCal.set(Calendar.SECOND, 0); tomorrowCal.set(Calendar.MILLISECOND, 0); if (itemCal.equals(tomorrowCal)) { // Your notification code here GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(getApplicationContext()); if (account != null) { String firstname = account.getGivenName(); mContentTitle = "Your " + name + " is about to be expired!"; mContentText = firstname + ", make sure to cook or eat your " + name + " by " + date; } Intent openApp = new Intent(getApplicationContext(), MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 100, openApp, PendingIntent.FLAG_UPDATE_CURRENT); notification = new NotificationCompat.Builder(getApplicationContext(), "Default") .setSmallIcon(R.drawable.ic_restaurant_black_24dp) .setContentTitle(mContentTitle) .setContentText(mContentText) .setLights(Color.GREEN, 2000, 1000) .setPriority(NotificationCompat.PRIORITY_MAX) .setStyle(new NotificationCompat.BigTextStyle().bigText(mContentText)) .setContentIntent(contentIntent) .setAutoCancel(true); createNotificationChannel(getApplicationContext()); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext()); notificationManager.notify(uniqueID, notification.build()); } } catch (ParseException e) { Log.wtf("FailedtoChangeDate", "Fail"); } } } // Rest of your ChildEventListener methods... @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { } });
Solution 2: Use Java 8+ LocalDate (Cleaner Approach)
If your project targets API 26+ or uses desugar support, LocalDate is a more intuitive way to handle date-only comparisons:
// Replace the date parsing and comparison part with this DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/dd/yyyy", Locale.US); try { LocalDate itemDate = LocalDate.parse(date, formatter); LocalDate tomorrow = LocalDate.now().plusDays(1); if (itemDate.equals(tomorrow)) { // Your notification code here (same as before) } } catch (DateTimeParseException e) { Log.wtf("FailedtoChangeDate", "Fail"); }
Additional Notes
- Double-Check Your Logic: If you want to trigger notifications for items expiring today (not tomorrow), compare
itemDatetoLocalDate.now()instead oftomorrow. - Service Lifecycle: Keep in mind that regular Services can be killed by the system when the app is in the background. For reliable background checks, consider using WorkManager to schedule periodic checks of your Firebase database, or convert your Service to a Foreground Service to avoid being terminated.
内容的提问来源于stack exchange,提问作者Kristofer

